DLMain.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:22k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  Dungeon Looter main unit
  3.  (C) 2006-2007 George "Mirage" Bakhtadze, mirage@casteng.com
  4.  Unit contains main application class
  5. *)
  6. {$Include GDefines.inc}
  7. {$Include C2Defines.inc}
  8. unit DLMain;
  9. interface
  10. uses
  11.   SysUtils,
  12.   TextFile,
  13.   Props, OSUtils, Basics, Base3D, Resources,
  14.   BaseTypes, BaseClasses, BaseMsg, GUIMsg, C2GUI, BaseGraph,
  15.   C2VisItems, C22D, C2Materials, C2Res,
  16.   AppsInit, GUIHelper, C2AppHelper, ACSHelper,
  17.   ACSBase, ACS, ACSAdv,
  18.   C2FX, C2Affectors, C2Core,
  19.   C2Anim,
  20.   C2Maps, C2Land, C2TileMaps,
  21.   GWorld, GameMsg,
  22.   DLSound;
  23. const
  24.   HighScoresCount  = 10;
  25.   SplashTimeOut  = 5.000;
  26.   MessageTimeout = 2.000;
  27.   RelSoundsDir = 'sounds';
  28.   GameInfoURL = 'http://avagames.net/content/dungeonlooter';
  29. type
  30.   // Application class
  31.   TDLApp = class(TCast2App)
  32.   private
  33.     FGameState: TGameState;
  34.     SplashFader, GameOverFader: TFader;
  35.     TargetTileX: Integer;
  36.     DefaultConfig: TNiceFileConfig;
  37.     MessageID: Integer;
  38.     SoundsDir: string;
  39.     procedure ClearMessage(EventID: Integer; const ErrorDelta: TTimeUnit);
  40.     procedure OpenShop;
  41.     procedure SetGameState(const Value: TGameState);
  42.     // Checks if menu "Back" button should be enabled
  43.     function IsMenuBackEnabled(Caller: TGUIItem): Boolean;
  44.     // Checks if menu "Save game" button should be enabled
  45.     function IsMenuSaveEnabled(Caller: TGUIItem): Boolean;
  46.     // Checks if menu "Load game" button should be enabled
  47.     function IsMenuLoadEnabled(Caller: TGUIItem): Boolean;
  48.   public
  49.     GUIHelper: TACSHelper;                                   // Helper class to simplify GUI tasks
  50.     constructor Create(const AProgramName: string; AStarter: TAppStarter); override;
  51.     destructor Destroy; override;
  52.     procedure Init;
  53.     // Places current score to high scores list
  54.     procedure UpdateHighScores;
  55.     procedure CreateCore(CoreClass: CCore); override;
  56.     procedure PreviewOptions(OptionName, Value: string); override;
  57.     procedure ApplyOptionSet(const OptionSet: string); override;
  58.     procedure ApplyOptions; override;
  59.     function ApplyVideoOptions: Boolean; override;
  60.     function ApplyAudioOptions: Boolean; 
  61.     procedure PrintMessage(const Text: string);
  62.     // Moves character to point where mouse was clicked
  63.     procedure ProcessMouseControl;
  64.     // Determines the point where mouse was clicked
  65.     procedure HandleMouseControl(MX, MY: Integer);
  66.     // Handles a click on a GUI element
  67.     procedure OnGUIClick(Item: TGUIItem);
  68.     // Message handling
  69.     procedure HandleMessage(const Msg: TMessage); override;
  70.     // Main game processing cycle
  71.     procedure Process; override;
  72.     // Changes game state to next stage. E.g. intro screen to main menu, etc
  73.     procedure GoToNextGameState;
  74.     // Current game state. Currently visible items set depends on the state.
  75.     property GameState: TGameState read FGameState write SetGameState;
  76.   end;
  77. var
  78.   App: TDLApp;
  79.   ShopItemsList: TList;
  80. implementation
  81. { TDLApp }
  82. procedure TDLApp.ClearMessage(EventID: Integer; const ErrorDelta: TTimeUnit);
  83. begin
  84.   if EventID = MessageID then GUIHelper.SetControlText('Message', '');
  85. end;
  86. procedure TDLApp.OpenShop;
  87. var i: Integer; s: string;
  88. begin
  89.   GUIHelper.ShowControl('Inventory');
  90.   s := '';
  91.   for i := 0 to TotalGemTypes-1 do
  92.     s := s + Format('[#%S]%S[#] (%D gold): %D [E]', [GemColors[i], GemNames[i], GemPrices[i], World.Player.Inventory.Gems[i]]);
  93. //  GUIHelper.SetGUIItemText('InventoryInfo', s);
  94.   GUIHelper.SetControlText('ShopInfo', s);
  95.   GUIHelper.SetControlText('ShopStatus', 'Gold: ' + IntToStr(World.Player.Inventory.Gold));
  96.   GUIHelper.ShowControl('Shop');
  97.   
  98. end;
  99. procedure TDLApp.SetGameState(const Value: TGameState);
  100. begin
  101.   FGameState := Value;
  102.   GUIHelper.HideControl('LabelGameOver');
  103.   case Value of
  104.     gsIntro: begin
  105.       SplashFader.Show;
  106.       Core.Timer.SetEvent(SplashTimeOut, TTimeOutMsg);            // Set event to go further after some time
  107.     end;
  108.     gsMenu: begin
  109.       SplashFader.FadeOut;                                        // Fadeout splash screens if any
  110.       GameOverFader.FadeOut;
  111.       HandleMessage(TMenuToggleMsg.Create);
  112.     end;
  113.     gsPlay: begin
  114.       SplashFader.FadeOut;
  115.       GameOverFader.FadeOut;
  116.     end;
  117.     gsGameOver: begin
  118.       GameOverFader.Show;
  119.       GUIHelper.ShowControl('LabelGameOver');
  120.       Core.Timer.SetEvent(SplashTimeOut, TTimeOutMsg);
  121.     end;
  122.     gsOutro: ;
  123.     gsCredits: ;
  124.     else Assert(False, 'TDLApp.SetGameState: Invalid game state');
  125.   end;
  126. end;
  127. function TDLApp.IsMenuBackEnabled(Caller: TGUIItem): Boolean;
  128. begin
  129.   Result := FGameState = gsPlay;
  130. end;
  131. function TDLApp.IsMenuSaveEnabled(Caller: TGUIItem): Boolean;
  132. begin
  133.   Result := (FGameState = gsPlay) and (not World.Player.IsDead);
  134. end;
  135. function TDLApp.IsMenuLoadEnabled(Caller: TGUIItem): Boolean;
  136. begin
  137.   Result := FileExists(Config['UserName'] + '.sg');
  138. end;
  139. constructor TDLApp.Create(const AProgramName: string; AStarter: TAppStarter);
  140. var i: Integer; s: string; HSList: TList; TF: Text;
  141. begin
  142.   // Bind some default key which can be redefined a user profile (.pfl) file
  143.   BindAction(TInventoryToggleMsg, 'Inventory',  'I', '');
  144.   BindAction(TTeleportUseMsg,     'Teleport',   'T', '');
  145.   BindAction(TGameActionMsg,      'Action',     'ENTER', '');
  146.   BindAction(TFireMsg,            'Fire',       'SPACE', '');
  147.   // Cheat codes
  148.   BindAction(TGodModeToggleMsg,   'CheatGodMode',         'G,O,D,M,O,D,E',     '');
  149.   BindAction(TThousandTorchesMsg, 'CheatThousandTorches', '1,0,0,0,T,O,R,C,H,E,S', '');
  150.   BindAction(TGiveMoneyMsg,       'CheatManyMoney',       'M,A,N,Y,M,O,N,E,Y',   '');
  151.   inherited;
  152.   GUIHelper := TACSHelper.Create(Core, Config);
  153.   // Load default config used to reset configuration
  154.   DefaultConfig := TNiceFileConfig.Create(UserNameToFileName('default'));
  155.   GUIHelper.DefaultConfig := DefaultConfig;
  156. //  if not DefaultConfig.LoadFrom() then
  157. //    Log.Log('Default user profile file "' + UserNameToFileName('default') + '"not found', lkWarning);
  158.   // Load scene file
  159.   LoadScene('dlooter.cbf');
  160.   // Initialize spash screens
  161.   SplashFader   := Core.Root.GetChildByName('SplashFader', True) as TFader;
  162.   GameOverFader := Core.Root.GetChildByName('GameOverFader', True) as TFader;
  163.   // Load GUI forms list
  164.   GUIHelper.LoadForms('game.gui');
  165.   // Read high scores
  166.   try
  167.     HSList := Core.Root.GetChildByName('HiScoresList', True) as TList;
  168.     HSList.Items.TotalItems := HighScoresCount;
  169.     AssignFile(TF, 'HIScore.dat'); Reset(TF);
  170.     for i := 0 to HSList.Items.TotalItems-1 do begin
  171.       ReadLn(TF, s);
  172.       HSList.Items[i] := s;
  173.     end;
  174.     CloseFile(TF);
  175.   except
  176.   end;
  177.   // Check for errors
  178.   if not Assigned(World) then begin
  179.     Log.Log('An item of the class TGameWorld not found in the scene', lkFatalError);
  180.     Starter.Terminate;
  181.     Exit;
  182.   end;
  183.   // Logon user and load user's profile from file "player.pfl". The settings will override current config.
  184.   LogOn('Player');
  185.   // Load sounds
  186.   SoundsDir := Starter.ProgramWorkDir + RelSoundsDir;
  187.   World.Sound := TAudiereSound.Create(Core.Timer);
  188.   World.Sound.Load('Step',    SoundsDir + 'step.wav',    False);
  189.   World.Sound.Load('Click',   SoundsDir + 'click.wav',   False);
  190.   World.Sound.Load('Pickup',  SoundsDir + 'pickup.wav',  False);
  191.   World.Sound.Load('Warning', SoundsDir + 'warning.wav', False);
  192.   World.Sound.Load('Breakin', SoundsDir + 'breakin.wav', False);
  193.   World.Sound.Load('Dig',     SoundsDir + 'dig.wav',     False);
  194.   World.Sound.Load('DigEnd',  SoundsDir + 'digend.wav',  False);
  195.   World.Sound.Load('Fire',    SoundsDir + 'fire.wav',    False);
  196.   World.Sound.Load('Gold',    SoundsDir + 'gold.wav',    False);
  197.   World.Sound.Load('Die',     SoundsDir + 'die.wav',     False);
  198.   World.Sound.Load('Music',   SoundsDir + 'game.xm',     False);
  199.   // Set minimum delay between steps
  200.   World.Sound.SetDelay('Step', 0.400);
  201.   World.Sound.SetVolume('Step', 35);
  202.   // Cycle music
  203.   World.Sound.SetRepeat('Music', True);
  204.   World.Sound.SetVolume('Music', 25);
  205.   // Turn the music on
  206.   World.Sound.Play('Music');
  207.   // Apply audio options such as master volume, etc
  208.   ApplyAudioOptions;
  209. end;
  210. procedure TDLApp.CreateCore(CoreClass: CCore);
  211. begin
  212.   inherited;
  213.   GWorld.Core := Core;
  214.   // Register item classes
  215.   Core.RegisterItemClasses(Resources.GetUnitClassList);            // Base resources
  216.   Core.RegisterItemClasses(BaseGraph.GetUnitClassList);            // Base graphics
  217.   // Engine classes
  218.   Core.RegisterItemClasses(C2Core.GetUnitClassList);               // Engine general classes
  219.   Core.RegisterItemClasses(C2Res.GetUnitClassList);                // CAST II resource
  220.   Core.RegisterItemClasses(C2VisItems.GetUnitClassList);           // Some visible item classes
  221.   Core.RegisterItemClasses(C2Anim.GetUnitClassList);               // Animated item classes
  222.   Core.RegisterItemClasses(C22D.GetUnitClassList);                 // 2D via CAST II wrapper classes
  223.   Core.RegisterItemClasses(C2FX.GetUnitClassList);                 // Some visual effects classes
  224.   Core.RegisterItemClasses(C2Land.GetUnitClassList);               // Landscape classes
  225.   Core.RegisterItemClasses(C2TileMaps.GetUnitClassList);           // Tilemap classes
  226.   // ACS classes
  227.   Core.RegisterItemClasses(ACS.GetUnitClassList);                  // Base controls
  228.   Core.RegisterItemClasses(ACSAdv.GetUnitClassList);               // Advanced controls
  229.   Core.RegisterItemClasses(C2GUI.GetUnitClassList);                // CAST II wrapper classes
  230.   // Partcile system classes
  231.   Core.RegisterItemClasses(C2Affectors.GetUnitClassList);          // Base particle system related classes
  232.   // Game specific classes
  233.   Core.RegisterItemClasses(GWorld.GetUnitClassList);        // Advanced particle system related classes
  234. end;
  235. procedure TDLApp.PreviewOptions(OptionName, Value: string);
  236. begin
  237.   inherited;
  238.   //  ApplyAudioOptions;
  239.   if OptionName = 'SOUNDVOLUME' then World.Sound.SetVolume('',      StrToIntDef(Value, 50));        // Master volume
  240.   if OptionName = 'MUSICVOLUME' then World.Sound.SetVolume('Music', StrToIntDef(Value, 50));
  241. end;
  242. procedure TDLApp.ApplyOptionSet(const OptionSet: string);
  243. begin
  244.   inherited;
  245.   if OptionSet = 'AUDIOOPTIONS' then ApplyAudioOptions;
  246. end;
  247. procedure TDLApp.ApplyOptions;
  248. begin
  249.   inherited;
  250.   ApplyAudioOptions;
  251. end;
  252. function TDLApp.ApplyAudioOptions: Boolean;
  253. begin
  254.   Result := True;
  255.   if not Assigned(World) or not Assigned(World.Sound) then Exit;
  256.   World.Sound.SetVolume('',      StrToIntDef(Config['SoundVolume'], 50));                           // Master volume
  257.   World.Sound.SetVolume('Music', StrToIntDef(Config['MusicVolume'], 50));
  258. end;
  259. function TDLApp.ApplyVideoOptions: Boolean;
  260. begin
  261.   Result := inherited ApplyVideoOptions;
  262.   if Assigned(World) and Assigned(World.Map) then begin
  263. {    if Config['Bump'] = OnOffStr[True] then begin
  264.       World.BgMap.CurTechnique := World.BgMap.Material.GetChildByName('DOT3 Bump', False) as TTechnique;
  265.       World.Map.CurTechnique := World.Map.Material.GetChildByName('DOT3 Bump', False) as TTechnique;
  266.     end else begin
  267.       World.BgMap.CurTechnique := World.BgMap.Material.GetChildByName('Diffuse', False) as TTechnique;
  268.       World.Map.CurTechnique := World.Map.Material.GetChildByName('Diffuse', False) as TTechnique;
  269.     end;}
  270.   end;
  271. end;
  272. destructor TDLApp.Destroy;
  273. var
  274.   i: Integer; HSList: TList; TF: Text;
  275. begin
  276.   if Assigned(World) then FreeAndNil(World.Sound);
  277.   // Write high scores to file
  278.   HSList := Core.Root.GetChildByName('HiScoresList', True) as TList;
  279.   AssignFile(TF, 'HIScore.dat');
  280.   try
  281.     Rewrite(TF);
  282.     for i := 0 to HSList.Items.TotalItems-1 do WriteLn(TF, HSList.Items[i]);
  283.     CLoseFile(TF);
  284.   except
  285.   end;
  286.   FreeAndNil(DefaultConfig);
  287.   FreeAndNil(GUIHelper);
  288.   inherited;
  289. end;
  290. procedure TDLApp.Init;
  291. var i: TGameItem; s: string; Button: TGUIItem;
  292. begin
  293.   // Game world initialization
  294.   World.Init;
  295.   ApplyVideoOptions;
  296.   // Set current game state to intro
  297.   GameState := gsIntro;
  298.   // Fill shop list GUI element 
  299.   for i := Low(TGameItem) to High(TGameItem) do begin
  300.     s := s + Format('%S (%D gold)', [ItemNames[i], ItemPrices[i]]);
  301.     if i < High(TGameItem) then s := s + '&';
  302.   end;
  303.   ShopItemsList := Core.Root.GetChildByName('ShopItemList', True) as TList;
  304.   ShopItemsList.Items.VariantsText := s;
  305.   Button := Core.Root.GetChildByName('MenuCloseBut', True) as TGUIItem;
  306.   Button.IsEnabledDelegate := IsMenuBackEnabled;
  307.   Button := Core.Root.GetChildByName('SaveBut', True) as TGUIItem;
  308.   Button.IsEnabledDelegate := IsMenuSaveEnabled;
  309.   Button := Core.Root.GetChildByName('LoadBut', True) as TGUIItem;
  310.   Button.IsEnabledDelegate := IsMenuLoadEnabled;
  311.   TargetTileX := -1;
  312. end;
  313. procedure TDLApp.PrintMessage(const Text: string);
  314. begin
  315.   Inc(MessageID);
  316.   GUIHelper.SetControlText('Message', Text);
  317.   Core.Timer.SetEvent(MessageTimeout, ClearMessage, MessageID);
  318. end;
  319. procedure TDLApp.ProcessMouseControl;
  320. var PlTileX, PlTileY: Integer;
  321. begin
  322.   if TargetTileX = -1 then Exit;
  323.   World.Map.ObtainTileAt(World.Player.GetAbsLocation.X, World.Player.GetAbsLocation.Y, PlTileX, PlTileY);
  324.   if TargetTileX < PlTileX then World.Player.Action := caMoveLeft;
  325.   if TargetTileX > PlTileX then World.Player.Action := caMoveRight;
  326. end;
  327. procedure TDLApp.HandleMouseControl(MX, MY: Integer);
  328. var TileX, TileY, PlTileX, PlTileY: Integer;
  329. begin
  330.   World.Map.ObtainTileAtScreen(MX, MY, Core.Renderer.MainCamera, TileX, TileY);
  331.   TargetTileX := TileX;
  332.   World.Map.ObtainTileAt(World.Player.GetAbsLocation.X, World.Player.GetAbsLocation.Y, PlTileX, PlTileY);
  333.   if Abs(TargetTileX - PlTileX) <= 1 then World.Player.PerformAction;
  334. end;
  335. procedure TDLApp.OnGUIClick(Item: TGUIItem);
  336. var i, ItemIndex: Integer; AllowBuy: Boolean; ii: TGameItem;
  337. begin
  338.   if Item is TButton then World.Sound.Play('Click');
  339.   if Item.Name = 'CreditsLink' then GotoURL(GameInfoURL);
  340.   // Menu
  341.   if (Item.Name = 'MenuToggleBut') or (Item.Name = 'MenuCloseBut') then begin
  342.     HandleMessage(TMenuToggleMsg.Create);
  343.   end;
  344.   if Item.Name = 'NewGameInvoke' then begin
  345.     UpdateHighScores;
  346.     GameState := gsPlay;
  347.     World.StartNewGame;
  348.     ApplyVideoOptions;
  349.     HandleMessage(TMenuToggleMsg.Create);
  350.   end;
  351.   if Item.Name = 'SaveBut' then begin
  352.     World.SaveGame(Config['UserName'] + '.sg');
  353.     GameState := gsPlay;
  354.     HandleMessage(TMenuToggleMsg.Create);
  355.     PrintMessage('Game saved');
  356.   end;
  357.   if Item.Name = 'LoadBut' then begin
  358.     UpdateHighScores;
  359.     World.LoadGame(Config['UserName'] + '.sg');
  360.     GUIHelper.HideControl('Shop');
  361.     GameState := gsPlay;
  362.     ApplyVideoOptions;
  363.     HandleMessage(TMenuToggleMsg.Create);
  364.     PrintMessage('Game loaded');
  365.   end;
  366.   // Shop
  367.   if Item.Name = 'SellAllBut' then begin
  368.     for i := 0 to TotalGemTypes-1 do begin
  369.       Inc(World.Player.Inventory.Gold, GemPrices[i] * World.Player.Inventory.Gems[i]);
  370.       World.Player.Inventory.Gems[i] := 0;
  371.       World.Sound.Play('Gold');
  372.       OpenShop;
  373.     end;
  374.     OpenShop;
  375.   end;
  376.   if Item.Name = 'BuyBut' then begin
  377.     ItemIndex := ShopItemsList.ItemIndex;
  378.     if (ItemIndex >= 0) then begin
  379.       if (World.Player.Inventory.Gold >= ItemPrices[TGameItem(ItemIndex)]) then begin
  380.         if (World.Player.Inventory.Capacity-World.Player.Inventory.Occupied >= MaxI(0, ItemSizes[TGameItem(ItemIndex)])) then begin
  381.           AllowBuy := True;
  382.           for ii := High(TGameItem) downto Low(TGameItem) do
  383.             if (ItemGroups[TGameItem(ItemIndex)] < 0) and (ItemGroups[TGameItem(ItemIndex)] = ItemGroups[ii]) then
  384.               if (ItemIndex <= Ord(ii)) and (World.Player.Inventory.Items[ii] > 0) then begin
  385.                 AllowBuy := False;
  386.                 PrintMessage('You already have ' + ItemNames[ii]);
  387.               end else World.Player.Inventory.Items[ii] := 0;
  388.           if AllowBuy then begin
  389.             World.Sound.Play('Gold');
  390.             Dec(World.Player.Inventory.Gold, ItemPrices[TGameItem(ItemIndex)]);
  391.             Inc(World.Player.Inventory.Items[TGameItem(ItemIndex)]);
  392.           end else World.Sound.Play('Warning');
  393.         end else begin
  394.           PrintMessage('Not enough inventory space!');
  395.           World.Sound.Play('Warning');
  396.         end;  
  397.       end else begin
  398.         PrintMessage('Not enough gold!');
  399.         World.Sound.Play('Warning');
  400.       end;
  401.     end;
  402.     OpenShop;
  403.   end;
  404.   // Help
  405.   if Item.Name = 'HelpMainShow' then begin
  406.     GUIHelper.HideControl('HelpItems');
  407.     GUIHelper.HideControl('HelpControls');
  408.   end;
  409.   if Item.Name = 'HelpItemsShow' then begin
  410.     GUIHelper.HideControl('HelpMain');
  411.     GUIHelper.HideControl('HelpControls');
  412.   end;
  413.   if Item.Name = 'HelpControlsShow' then begin
  414.     GUIHelper.HideControl('HelpMain');
  415.     GUIHelper.HideControl('HelpItems');
  416.   end;
  417. end;
  418. procedure TDLApp.HandleMessage(const Msg: TMessage);
  419. begin
  420.   if Starter.Terminated then Exit;
  421.   inherited;
  422.   if Assigned(World) then World.HandleMessage(Msg);
  423.   // Skip intros when a mouse clicked or by timeout
  424.   if (Msg.ClassType = TMouseDownMsg) or (Msg.ClassType = TTimeOutMsg) then
  425.     case GameState of
  426.       gsPlay: if Msg.ClassType = TMouseDownMsg then with TMouseDownMsg(Msg) do        // Handle character moving with mouse
  427.         if not GUIHelper.IsWithinGUI(X, Y) then HandleMouseControl(X, Y);
  428.       gsMenu: ;
  429.       else GoToNextGameState;
  430.     end;
  431.   if Assigned(GUIHelper) then begin
  432.     GUIHelper.HandleMessage(Msg);
  433.     if Msg.ClassType = TInventoryToggleMsg then if GameState = gsPlay then GUIHelper.ToggleControl('Inventory');
  434.     if Msg.ClassType = TMenuToggleMsg then begin
  435.       if GUIHelper.IsControlVisible('Menu', False) then begin
  436.         if IsMenuBackEnabled(nil) then GUIHelper.HideControl('Menu');
  437.       end else GUIHelper.ShowControl('Menu');
  438.       Core.Paused := GUIHelper.IsControlVisible('Menu', False);
  439.     end;
  440.     if Msg.ClassType = THelpToggleMsg then GUIHelper.ToggleControl('HelpMain');
  441.   end;
  442.   // Input messages
  443.   if Msg.ClassType = TGameActionMsg then  World.Player.PerformAction;
  444.   if Msg.ClassType = TFireMsg       then  World.Player.Fire;
  445.   if Msg.ClassType = TTeleportUseMsg then World.Player.PerformTeleport;
  446.     // Gameplay messages
  447.   // A gem was picked up
  448.   if Msg.ClassType = TGemPickedUpMsg then with TGemPickedUpMsg(Msg) do begin
  449.     PrintMessage( GemNames[GemType-1] + ' collected');
  450.     World.Sound.Play('Pickup');
  451.   end;
  452.   // Some item is needed to perform an action
  453.   if Msg.ClassType = TItemLackMsg then with TItemLackMsg(Msg) do begin
  454.     PrintMessage('[#FF0000]' + ItemNames[ItemType]  + ' needed!');
  455.     World.Sound.Play('Warning');
  456.   end;
  457.   // Gameplay GUI messages
  458.   if Msg.ClassType = TShopOpenMsg  then OpenShop;
  459.   if Msg.ClassType = TShopCloseMsg then GUIHelper.HideControl('Shop');
  460.   if Msg.ClassType = TGUIClickMsg then OnGUIClick((Msg as TGUIClickMsg).Item);
  461.   if Msg.ClassType = TGameOverMsg then begin
  462.     UpdateHighScores;
  463.     GameState := gsGameOver;
  464.     World.Sound.Play('Die');
  465.   end;
  466.   // Cheats
  467.   if (Msg is TCheatCodeMsg) and (GameState = gsPlay) then begin
  468.     if Msg.ClassType = TGodModeToggleMsg then World.GodMode := True;
  469.     if Msg.ClassType = TThousandTorchesMsg then begin
  470.       World.Player.Inventory.Items[giTorch] := 1000;
  471.       World.Sound.Play('Fire');
  472.     end;  
  473.     if Msg.ClassType = TGiveMoneyMsg then begin
  474.       World.Player.Inventory.Gold := 100000;
  475.       World.Sound.Play('Gold');
  476.     end;
  477.     PrintMessage('Cheater');
  478.   end;
  479. end;
  480. procedure TDLApp.Process;
  481.   procedure DrawInventory;
  482.   var i: Integer; ii: TGameItem; s: string;
  483.   begin
  484.     GUIHelper.SetControlText('InventoryTitle', Format('Inventory (%D/%D)', [World.Player.Inventory.Occupied, World.Player.Inventory.Capacity]));
  485.     s := 'Gold: ' + IntToStr(World.Player.Inventory.Gold) + ' [E]';
  486.     for ii := Low(TGameItem) to High(TGameItem) do if World.Player.Inventory.Items[ii] > 0 then
  487.       s := s + Format('%S: %D [E]', [ItemNames[ii], World.Player.Inventory.Items[ii]]);
  488.     for i := 0 to TotalGemTypes-1 do
  489.       s := s + Format('[#%S]%S[#]: %D [E]', [GemColors[i], GemNames[i], World.Player.Inventory.Gems[i]]);
  490.     GUIHelper.SetControlText('InventoryInfo', s);
  491.     // HUD
  492.     if World.Player.IsInLight then s := '' else s := '[#FFFF0000]!!![#]';
  493.     GUIHelper.SetControlText('HUDTorches', Format('%s T: %D, I: %D', [s, World.Player.Inventory.Items[giTorch], World.Player.Inventory.Capacity - World.Player.Inventory.Occupied]));
  494.     GUIHelper.SetControlText('HUDMoney',   'Gold: ' + IntToStr(World.Player.Inventory.Gold));
  495.     GUIHelper.SetControlText('HUDScore',   'Score: ' + IntToStr(World.Player.Score));
  496.   end;
  497. begin
  498.   inherited;
  499.   GUIHelper.SetControlText('FPSCounter', Format('FPS: %3.1F', [Core.PerfProfile.FramesPerSecond]));
  500.   DrawInventory;
  501.   // Convert application actions to character's actions
  502.   if Action['Right'] then World.Player.Action := caMoveRight else
  503.     if Action['Left'] then World.Player.Action := caMoveLeft else
  504.       World.Player.Action := caNone;
  505.   if Action['Forward'] then World.Player.Action := caJump;
  506.   if Action['Left'] or Action['Right'] or Action['Forward'] then TargetTileX := -1;
  507.   ProcessMouseControl;
  508. end;
  509. procedure TDLApp.UpdateHighScores;
  510. var HSList: TList;
  511. begin
  512.   HSList := Core.Root.GetChildByName('HiScoresList', True) as TList;
  513.   HSList.Items.Add(Format('%8.8D - Player', [World.Player.Score]));
  514.   HSList.Items.Sort(False, nil);
  515.   HSList.Items.TotalItems := HighScoresCount;
  516. end;
  517. procedure TDLApp.GoToNextGameState;
  518. begin
  519.   case FGameState of
  520.     gsIntro:    GameState := gsMenu;
  521.     gsMenu:     GameState := gsMenu;
  522.     gsPlay:     GameState := gsPlay;
  523.     gsGameOver: GameState := gsMenu;
  524.     gsOutro:    GameState := gsCredits;
  525.     gsCredits:  GameState := gsMenu;
  526.   end;
  527. end;
  528. end.