From f239958dd3422530a4653bd5fed9654f5b5230fa Mon Sep 17 00:00:00 2001 From: gandifil Date: Sun, 12 Jul 2026 15:46:39 +0300 Subject: [PATCH 1/7] Fix names in TResourceSchema --- sources/Game/Elinor.MediaPlayer.pas | 2 +- sources/Game/Elinor.NewResources.pas | 38 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sources/Game/Elinor.MediaPlayer.pas b/sources/Game/Elinor.MediaPlayer.pas index ac02ded..6584d8b 100644 --- a/sources/Game/Elinor.MediaPlayer.pas +++ b/sources/Game/Elinor.MediaPlayer.pas @@ -96,7 +96,7 @@ function TMediaPlayer.PlayMusic(const FileName: string; F: Boolean): Boolean; begin StopMusic; CurrentChannel := MusicChannel; - Play(R.Music[FileName + '.mp3'], F, mtMusic); + Play(R.Musics[FileName + '.mp3'], F, mtMusic); CurrentChannel := SoundChannel; end; diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index 3cbca7c..b7f3617 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -76,21 +76,21 @@ TPNGImageLoader = class(TInterfacedObject, IResourceLoader) TResourceSchema = class private - FMusic, FSound: IResourceLoader; + FMusics, FSounds: IResourceLoader; - FCharacter, FItem, FSpell: IResourceLoader; + FCharacters, FItems, FSpells: IResourceLoader; - FCharacterCache, FItemCache, FSpellCache: IResourceCache; + FCharactersCache, FItemsCache, FSpellsCache: IResourceCache; public constructor Create(); procedure LoadAll(); - property Music: IResourceLoader read FMusic; - property Sound: IResourceLoader read FSound; - property Character: IResourceLoader read FCharacter; - property Item: IResourceLoader read FItem; - property Spell: IResourceLoader read FSpell; + property Musics: IResourceLoader read FMusics; + property Sounds: IResourceLoader read FSounds; + property Characters: IResourceLoader read FCharacters; + property Items: IResourceLoader read FItems; + property Spells: IResourceLoader read FSpells; end; const @@ -239,34 +239,34 @@ constructor TResourceSchema.Create(); basePath := ExtractFilePath(ParamStr(0)) + 'resources/'; echo := TEchoResourceLoader.Create(); - FMusic := TPrefixedResourceLoader.Create(echo, basePath + 'music/'); - FSound := TPrefixedResourceLoader.Create(echo, basePath + 'sound/'); + FMusics := TPrefixedResourceLoader.Create(echo, basePath + 'music/'); + FSounds := TPrefixedResourceLoader.Create(echo, basePath + 'sounds/'); png := TPNGImageLoader.Create(); cache := TCachedResourceLoader.Create( TPrefixedResourceLoader.Create(png, basePath + 'character/') ); - FCharacter := cache; - FCharacterCache := cache; + FCharacters := cache; + FCharactersCache := cache; cache := TCachedResourceLoader.Create( TPrefixedResourceLoader.Create(png, basePath + 'item/') ); - FItem := cache; - FItemCache := cache; + FItems := cache; + FItemsCache := cache; cache := TCachedResourceLoader.Create( TPrefixedResourceLoader.Create(png, basePath + 'spell/') ); - FSpell := cache; - FSpellCache := cache; + FSpells := cache; + FSpellsCache := cache; end; procedure TResourceSchema.LoadAll(); begin - FCharacterCache.LoadAll(); - FItemCache.LoadAll(); - FSpellCache.LoadAll(); + FCharactersCache.LoadAll(); + FItemsCache.LoadAll(); + FSpellsCache.LoadAll(); end; initialization From da66c47b1d2dda3e72e8442a81373bb7e3e6e0fa Mon Sep 17 00:00:00 2001 From: devapromix Date: Sun, 12 Jul 2026 22:36:10 +0300 Subject: [PATCH 2/7] Added spells sprites and spells section to resources/resources.json. --- resources/resources.json | 19 +++++++++++++++++++ resources/spells/bless.png | Bin 0 -> 9074 bytes resources/spells/bone_golem.png | Bin 0 -> 6943 bytes resources/spells/chains_of_dread.png | Bin 0 -> 3635 bytes resources/spells/concealment.png | Bin 0 -> 6898 bytes resources/spells/curse.png | Bin 0 -> 8091 bytes resources/spells/eagle_eye.png | Bin 0 -> 8435 bytes resources/spells/fire_golem.png | Bin 0 -> 6943 bytes resources/spells/living_armor.png | Bin 0 -> 9243 bytes resources/spells/meteor_shower.png | Bin 0 -> 8574 bytes resources/spells/plague.png | Bin 0 -> 3468 bytes resources/spells/rust.png | Bin 0 -> 8723 bytes resources/spells/skeletion.png | Bin 0 -> 6943 bytes resources/spells/speed.png | Bin 0 -> 9520 bytes resources/spells/stone_golem.png | Bin 0 -> 6943 bytes resources/spells/strength.png | Bin 0 -> 10368 bytes resources/spells/true_healing.png | Bin 0 -> 3509 bytes resources/spells/weaken.png | Bin 0 -> 7366 bytes sources/Game/Elinor.NewResources.pas | 7 +++---- 19 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 resources/spells/bless.png create mode 100644 resources/spells/bone_golem.png create mode 100644 resources/spells/chains_of_dread.png create mode 100644 resources/spells/concealment.png create mode 100644 resources/spells/curse.png create mode 100644 resources/spells/eagle_eye.png create mode 100644 resources/spells/fire_golem.png create mode 100644 resources/spells/living_armor.png create mode 100644 resources/spells/meteor_shower.png create mode 100644 resources/spells/plague.png create mode 100644 resources/spells/rust.png create mode 100644 resources/spells/skeletion.png create mode 100644 resources/spells/speed.png create mode 100644 resources/spells/stone_golem.png create mode 100644 resources/spells/strength.png create mode 100644 resources/spells/true_healing.png create mode 100644 resources/spells/weaken.png diff --git a/resources/resources.json b/resources/resources.json index 30b28c9..13e9fed 100644 --- a/resources/resources.json +++ b/resources/resources.json @@ -1,4 +1,23 @@ { + "spells": { + "bless": "bless.png", + "bone_golem": "bone_golem.png", + "chains_of_dread": "chains_of_dread.png", + "concealment": "concealment.png", + "curse": "curse.png", + "eagle_eye": "eagle_eye.png", + "fire_golem": "fire_golem.png", + "living_armor": "living_armor.png", + "meteor_shower": "meteor_shower.png", + "plague": "plague.png", + "rust": "rust.png", + "skeletion": "skeletion.png", + "speed": "speed.png", + "stone_golem": "stone_golem.png", + "strength": "strength.png", + "true_healing": "true_healing.png", + "weaken": "weaken.png" + } "sounds": { "click": "click.wav" }, diff --git a/resources/spells/bless.png b/resources/spells/bless.png new file mode 100644 index 0000000000000000000000000000000000000000..1161fa6a62dd6ba2c4bf733c1964c5de385fcc53 GIT binary patch literal 9074 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 FV1i)!*c1Q& literal 0 HcmV?d00001 diff --git a/resources/spells/concealment.png b/resources/spells/concealment.png new file mode 100644 index 0000000000000000000000000000000000000000..c6aa5b16d66e429ff3af46689e13f475d06c2180 GIT binary patch literal 6898 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 literal 0 HcmV?d00001 diff --git a/resources/spells/curse.png b/resources/spells/curse.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6f9e6db5bcbb2862b5f5424c9d9d9d460f796f GIT binary patch literal 8091 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 literal 0 HcmV?d00001 diff --git a/resources/spells/eagle_eye.png b/resources/spells/eagle_eye.png new file mode 100644 index 0000000000000000000000000000000000000000..90df9ac5ecd45c53d6dd5534880c2967daed39eb GIT binary patch literal 8435 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 literal 0 HcmV?d00001 diff --git a/resources/spells/meteor_shower.png b/resources/spells/meteor_shower.png new file mode 100644 index 0000000000000000000000000000000000000000..71df5e569c011dd4cb07f175be006071d8fe8627 GIT binary patch literal 8574 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 Ef=B)I(f|Me literal 0 HcmV?d00001 diff --git a/resources/spells/plague.png b/resources/spells/plague.png new file mode 100644 index 0000000000000000000000000000000000000000..c741821a7c19942ba189468cd188890c3f885b46 GIT binary patch literal 3468 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 literal 0 HcmV?d00001 diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index b7f3617..aee4878 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -85,7 +85,6 @@ TResourceSchema = class public constructor Create(); procedure LoadAll(); - property Musics: IResourceLoader read FMusics; property Sounds: IResourceLoader read FSounds; property Characters: IResourceLoader read FCharacters; @@ -244,19 +243,19 @@ constructor TResourceSchema.Create(); png := TPNGImageLoader.Create(); cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'character/') + TPrefixedResourceLoader.Create(png, basePath + 'characters/') ); FCharacters := cache; FCharactersCache := cache; cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'item/') + TPrefixedResourceLoader.Create(png, basePath + 'items/') ); FItems := cache; FItemsCache := cache; cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'spell/') + TPrefixedResourceLoader.Create(png, basePath + 'spells/') ); FSpells := cache; FSpellsCache := cache; From 3f3c31bb89f9336b62dd19e358346060dc8ac5b3 Mon Sep 17 00:00:00 2001 From: devapromix Date: Tue, 14 Jul 2026 18:59:37 +0300 Subject: [PATCH 3/7] Loads res from json --- resources/resources.json | 2 +- sources/Game/Elinor.NewResources.pas | 235 ++++++++++++++++++--------- 2 files changed, 163 insertions(+), 74 deletions(-) diff --git a/resources/resources.json b/resources/resources.json index 13e9fed..867a177 100644 --- a/resources/resources.json +++ b/resources/resources.json @@ -17,7 +17,7 @@ "strength": "strength.png", "true_healing": "true_healing.png", "weaken": "weaken.png" - } + }, "sounds": { "click": "click.wav" }, diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index aee4878..6308c7b 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -6,26 +6,18 @@ interface System.SysUtils, System.Generics.Collections, System.StrUtils, + System.IOUtils, + System.JSON, Vcl.Imaging.PNGImage; type - // Базовый интерфейс для чтения данных о ресурсах IResourceLoader = interface - /// - /// Возвращает объект по ключу. Если ключ не найден — бросает ***. - /// + ['{8B5E8C4A-5F2D-4E8A-9B3C-7D1E2F4A6B9C}'] function Get(const Key: string): T; - property Items[const Key: string]: T read Get; default; - - /// - /// Возвращает ключи всех доступных ресурсов, которые начинаются с префикса. - /// function GetKeys(const prefix: string = ''): TArray; end; - // возвращает сам ключ - // использовать в тех местах, где нужен только путь к файлу TEchoResourceLoader = class(TInterfacedObject, IResourceLoader) private function Get(const Key: string): string; @@ -38,16 +30,36 @@ TPrefixedResourceLoader = class(TInterfacedObject, IResourceLoader) private FParent: IResourceLoader; FPrefix: string; - function Get(const Key: string): T; public constructor Create(AParent: IResourceLoader; const APrefix: string); - property Items[const Key: string]: T read Get; default; function GetKeys(const prefix: string = ''): TArray; end; + TJsonResourceLoader = class(TInterfacedObject, IResourceLoader) + private + FSection: TJSONObject; + function Get(const Key: string): string; + public + constructor Create(ARoot: TJSONObject; const ASectionName: string); + property Items[const Key: string]: string read Get; default; + function GetKeys(const prefix: string = ''): TArray; + end; + + TValuePathResourceLoader = class(TInterfacedObject, IResourceLoader) + private + FParent: IResourceLoader; + FBasePath: string; + function Get(const Key: string): string; + public + constructor Create(AParent: IResourceLoader; const ABasePath: string); + property Items[const Key: string]: string read Get; default; + function GetKeys(const prefix: string = ''): TArray; + end; + IResourceCache = interface + ['{3F2A1B7C-8D4E-4F9A-9B2C-1E7F5A3D6B8E}'] procedure LoadAll(); end; @@ -55,12 +67,10 @@ TCachedResourceLoader = class(TInterfacedObject, IResourceLoader, IResou private FParent: IResourceLoader; FCache: TDictionary; - function Get(const Key: string): T; public constructor Create(AParent: IResourceLoader); destructor Destroy; override; - property Items[const Key: string]: T read Get; default; function GetKeys(const prefix: string = ''): TArray; procedure LoadAll(); @@ -76,15 +86,15 @@ TPNGImageLoader = class(TInterfacedObject, IResourceLoader) TResourceSchema = class private + FJsonRoot: TJSONObject; FMusics, FSounds: IResourceLoader; - FCharacters, FItems, FSpells: IResourceLoader; - FCharactersCache, FItemsCache, FSpellsCache: IResourceCache; - public constructor Create(); + destructor Destroy; override; procedure LoadAll(); + property Musics: IResourceLoader read FMusics; property Sounds: IResourceLoader read FSounds; property Characters: IResourceLoader read FCharacters; @@ -93,14 +103,14 @@ TResourceSchema = class end; const - CMusicGame = 'soliloquy'; - CMusicMagic = 'wasteland-theme'; - CMusicBattle = 'wasteland-showdown'; - CMusicVictory = 'warsong'; - CMusicDefeat = 'defeat'; - CMusicBattleWin = 'ubermensch'; - CMusicMap = 'prologue'; - CMusicMenu = 'stellardrone'; + CMusicGame = 'game'; + CMusicMagic = 'magic'; + CMusicBattle = 'battle'; + CMusicVictory = 'victory'; + CMusicDefeat = 'defeat'; + CMusicBattleWin = 'battle_win'; + CMusicMap = 'map'; + CMusicMenu = 'menu'; var R: TResourceSchema; @@ -131,6 +141,7 @@ constructor TCachedResourceLoader.Create(AParent: IResourceLoader); inherited Create; if not Assigned(AParent) then raise Exception.Create('Parent IResourceLoader must be not nil!'); + FParent := AParent; FCache := TDictionary.Create; end; @@ -140,14 +151,14 @@ function TCachedResourceLoader.GetKeys(const prefix: string = ''): TArray.LoadAll(); -var keys: TArray; key: string; +procedure TCachedResourceLoader.LoadAll; +var + keys: TArray; + key: string; begin - keys := FParent.GetKeys(); + keys := FParent.GetKeys(''); for key in keys do - begin FParent[key]; - end; end; destructor TCachedResourceLoader.Destroy; @@ -161,6 +172,7 @@ constructor TPrefixedResourceLoader.Create(AParent: IResourceLoader; const inherited Create; if not Assigned(AParent) then raise Exception.Create('Parent IResourceLoader must be not nil!'); + FParent := AParent; FPrefix := APrefix; end; @@ -173,108 +185,185 @@ function TPrefixedResourceLoader.Get(const Key: string): T; function TPrefixedResourceLoader.GetKeys(const prefix: string = ''): TArray; var LSearchRec: TSearchRec; - LFileName: string; LFiles: TList; begin - LFiles := TList.Create(); + LFiles := TList.Create; try - if FindFirst(FPrefix + prefix + '*.*', faAnyFile, LSearchRec) = 0 then + if FindFirst(IncludeTrailingPathDelimiter(FPrefix) + prefix + '*.*', faAnyFile, LSearchRec) = 0 then begin repeat - LFileName := LSearchRec.Name; if (LSearchRec.Attr and faDirectory) = 0 then - begin - LFiles.Add(LFileName); - end; + LFiles.Add(LSearchRec.Name); until FindNext(LSearchRec) <> 0; end; FindClose(LSearchRec); - Result := LFiles.ToArray(); + Result := LFiles.ToArray; finally LFiles.Free; end; end; -function TPNGImageLoader.Get(const Key: string): TPNGImage; +constructor TJsonResourceLoader.Create(ARoot: TJSONObject; const ASectionName: string); +var + LValue: TJSONValue; +begin + inherited Create; + if not Assigned(ARoot) then + raise Exception.Create('Root JSON object is nil'); + + LValue := ARoot.GetValue(ASectionName); + if not (Assigned(LValue) and (LValue is TJSONObject)) then + raise Exception.CreateFmt('Секцію "%s" не знайдено в JSON', [ASectionName]); + + FSection := TJSONObject(LValue); +end; + +function TJsonResourceLoader.Get(const Key: string): string; var - LPath: string; + LValue: TJSONValue; + CleanKey: string; +begin + CleanKey := ChangeFileExt(ExtractFileName(Key), ''); + LValue := FSection.GetValue(CleanKey); + if not Assigned(LValue) then + LValue := FSection.GetValue(Key); + + if not Assigned(LValue) then + raise Exception.CreateFmt('Ключ "%s" не знайдено в JSON', [Key]); + + Result := LValue.Value; +end; + +function TJsonResourceLoader.GetKeys(const prefix: string = ''): TArray; +var + LList: TList; + LPair: TJSONPair; +begin + LList := TList.Create; + try + for LPair in FSection do + if StartsText(prefix, LPair.JsonString.Value) then + LList.Add(LPair.JsonString.Value); + + Result := LList.ToArray; + finally + LList.Free; + end; +end; + +constructor TValuePathResourceLoader.Create(AParent: IResourceLoader; const ABasePath: string); +begin + inherited Create; + if not Assigned(AParent) then + raise Exception.Create('Parent IResourceLoader must be not nil!'); + + FParent := AParent; + FBasePath := IncludeTrailingPathDelimiter(ABasePath); +end; + +function TValuePathResourceLoader.Get(const Key: string): string; +begin + Result := FBasePath + FParent.Get(Key); +end; + +function TValuePathResourceLoader.GetKeys(const prefix: string = ''): TArray; +begin + Result := FParent.GetKeys(prefix); +end; + +function TPNGImageLoader.Get(const Key: string): TPNGImage; begin Result := TPNGImage.Create; - Result.LoadFromFile(Key); + try + Result.LoadFromFile(Key); + except + Result.Free; + raise; + end; end; function TPNGImageLoader.GetKeys(const prefix: string = ''): TArray; var LSearchRec: TSearchRec; - LFileName: string; LFiles: TList; begin - LFiles := TList.Create(); + LFiles := TList.Create; try - if FindFirst(prefix + '*.*', faAnyFile, LSearchRec) = 0 then + if FindFirst(IncludeTrailingPathDelimiter(prefix) + '*.*', faAnyFile, LSearchRec) = 0 then begin repeat - LFileName := LSearchRec.Name; if (LSearchRec.Attr and faDirectory) = 0 then - begin - LFiles.Add(LFileName); - end; + LFiles.Add(LSearchRec.Name); until FindNext(LSearchRec) <> 0; end; FindClose(LSearchRec); - Result := LFiles.ToArray(); + Result := LFiles.ToArray; finally LFiles.Free; end; end; -constructor TResourceSchema.Create(); +constructor TResourceSchema.Create; var - basePath: string; - echo: IResourceLoader; + basePath, jsonPath, jsonText: string; png: TPNGImageLoader; cache: TCachedResourceLoader; begin - basePath := ExtractFilePath(ParamStr(0)) + 'resources/'; + basePath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + 'resources'); + + jsonPath := basePath + 'resources.json'; + if not TFile.Exists(jsonPath) then + raise Exception.CreateFmt('Файл ресурсів не знайдено: %s', [jsonPath]); - echo := TEchoResourceLoader.Create(); - FMusics := TPrefixedResourceLoader.Create(echo, basePath + 'music/'); - FSounds := TPrefixedResourceLoader.Create(echo, basePath + 'sounds/'); + jsonText := TFile.ReadAllText(jsonPath, TEncoding.UTF8); + FJsonRoot := TJSONObject.ParseJSONValue(jsonText) as TJSONObject; + if not Assigned(FJsonRoot) then + raise Exception.CreateFmt('Не вдалося розпарсити JSON: %s', [jsonPath]); + + FMusics := TValuePathResourceLoader.Create( + TJsonResourceLoader.Create(FJsonRoot, 'music'), basePath + 'music\'); + + FSounds := TValuePathResourceLoader.Create( + TJsonResourceLoader.Create(FJsonRoot, 'sounds'), basePath + 'sounds'); + + png := TPNGImageLoader.Create; - png := TPNGImageLoader.Create(); cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'characters/') - ); + TPrefixedResourceLoader.Create(png, basePath + 'characters')); FCharacters := cache; FCharactersCache := cache; cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'items/') - ); + TPrefixedResourceLoader.Create(png, basePath + 'items')); FItems := cache; FItemsCache := cache; cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'spells/') - ); + TPrefixedResourceLoader.Create(png, basePath + 'spells\')); FSpells := cache; FSpellsCache := cache; end; -procedure TResourceSchema.LoadAll(); +destructor TResourceSchema.Destroy; begin - FCharactersCache.LoadAll(); - FItemsCache.LoadAll(); - FSpellsCache.LoadAll(); + FMusics := nil; + FSounds := nil; + FJsonRoot.Free; + inherited; end; -initialization +procedure TResourceSchema.LoadAll; +begin + FCharactersCache.LoadAll; + FItemsCache.LoadAll; + FSpellsCache.LoadAll; +end; -R := TResourceSchema.Create(); -R.LoadAll(); +initialization + R := TResourceSchema.Create; + R.LoadAll; finalization - -R.Free; + FreeAndNil(R); end. From d84a7defa8cdc64328d56c59bba9be18c421b4f8 Mon Sep 17 00:00:00 2001 From: devapromix Date: Tue, 14 Jul 2026 19:18:01 +0300 Subject: [PATCH 4/7] Fix bugs --- sources/Game/Elinor.NewResources.pas | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index 6308c7b..9c6a3aa 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -213,7 +213,7 @@ constructor TJsonResourceLoader.Create(ARoot: TJSONObject; const ASectionName: s LValue := ARoot.GetValue(ASectionName); if not (Assigned(LValue) and (LValue is TJSONObject)) then - raise Exception.CreateFmt('Секцію "%s" не знайдено в JSON', [ASectionName]); + raise Exception.CreateFmt('Section "%s" not found in JSON', [ASectionName]); FSection := TJSONObject(LValue); end; @@ -229,7 +229,7 @@ function TJsonResourceLoader.Get(const Key: string): string; LValue := FSection.GetValue(Key); if not Assigned(LValue) then - raise Exception.CreateFmt('Ключ "%s" не знайдено в JSON', [Key]); + raise Exception.CreateFmt('Key "%s" not found in JSON', [Key]); Result := LValue.Value; end; @@ -313,28 +313,28 @@ constructor TResourceSchema.Create; jsonPath := basePath + 'resources.json'; if not TFile.Exists(jsonPath) then - raise Exception.CreateFmt('Файл ресурсів не знайдено: %s', [jsonPath]); + raise Exception.CreateFmt('Resource file not found: %s', [jsonPath]); jsonText := TFile.ReadAllText(jsonPath, TEncoding.UTF8); FJsonRoot := TJSONObject.ParseJSONValue(jsonText) as TJSONObject; if not Assigned(FJsonRoot) then - raise Exception.CreateFmt('Не вдалося розпарсити JSON: %s', [jsonPath]); + raise Exception.CreateFmt('Failed to parse JSON: %s', [jsonPath]); FMusics := TValuePathResourceLoader.Create( TJsonResourceLoader.Create(FJsonRoot, 'music'), basePath + 'music\'); FSounds := TValuePathResourceLoader.Create( - TJsonResourceLoader.Create(FJsonRoot, 'sounds'), basePath + 'sounds'); + TJsonResourceLoader.Create(FJsonRoot, 'sounds'), basePath + 'sounds\'); png := TPNGImageLoader.Create; cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'characters')); + TPrefixedResourceLoader.Create(png, basePath + 'characters\')); FCharacters := cache; FCharactersCache := cache; cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'items')); + TPrefixedResourceLoader.Create(png, basePath + 'items\')); FItems := cache; FItemsCache := cache; From a15d85d1a52c3bc8e9985eaea91a32f93e7dffa6 Mon Sep 17 00:00:00 2001 From: devapromix Date: Tue, 14 Jul 2026 19:58:42 +0300 Subject: [PATCH 5/7] refact --- sources/Game/Elinor.MediaPlayer.pas | 14 +++----------- sources/Game/Elinor.NewResources.pas | 12 +----------- sources/Game/Elinor.Party.pas | 6 +++--- sources/Game/Elinor.Resources.pas | 7 +++---- sources/Scenes/Elinor.Scene.Battle2.pas | 10 +++++----- sources/Scenes/Elinor.Scene.Battle3.pas | 2 +- sources/Scenes/Elinor.Scene.Defeat.pas | 2 +- sources/Scenes/Elinor.Scene.MageTower.pas | 2 +- sources/Scenes/Elinor.Scene.Map.pas | 2 +- sources/Scenes/Elinor.Scene.Menu3.pas | 2 +- sources/Scenes/Elinor.Scene.Name.pas | 2 +- sources/Scenes/Elinor.Scene.Settlement.pas | 2 +- sources/Scenes/Elinor.Scene.Victory.pas | 4 ++-- sources/Scenes/Elinor.Scenes.pas | 2 +- 14 files changed, 25 insertions(+), 44 deletions(-) diff --git a/sources/Game/Elinor.MediaPlayer.pas b/sources/Game/Elinor.MediaPlayer.pas index 6584d8b..c0db2a0 100644 --- a/sources/Game/Elinor.MediaPlayer.pas +++ b/sources/Game/Elinor.MediaPlayer.pas @@ -36,9 +36,7 @@ TMediaPlayer = class(TObject) : Boolean; overload; function PlaySound(const MusicEnum: TMusicEnum; F: Boolean = False) : Boolean; overload; - function PlayMusic(const FileName: string; F: Boolean = True) - : Boolean; overload; - function PlayMusic(const MusicEnum: TMusicEnum; F: Boolean = True) + function PlayMusic(const AKey: string; F: Boolean = True) : Boolean; overload; procedure StopSound; procedure StopMusic; @@ -92,20 +90,14 @@ function TMediaPlayer.IsPlayMusic: Boolean; Result := BASS_ChannelIsActive(FChannel[MusicChannel]) = BASS_ACTIVE_PLAYING; end; -function TMediaPlayer.PlayMusic(const FileName: string; F: Boolean): Boolean; +function TMediaPlayer.PlayMusic(const AKey: string; F: Boolean): Boolean; begin StopMusic; CurrentChannel := MusicChannel; - Play(R.Musics[FileName + '.mp3'], F, mtMusic); + Play(R.Musics[AKey + '.mp3'], F, mtMusic); CurrentChannel := SoundChannel; end; -function TMediaPlayer.PlayMusic(const MusicEnum: TMusicEnum; - F: Boolean): Boolean; -begin - // PlayMusic(ResMusicPath[MusicEnum], F); -end; - function TMediaPlayer.PlaySound(const MusicEnum: TMusicEnum; F: Boolean): Boolean; begin diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index 9c6a3aa..d18e306 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -102,16 +102,6 @@ TResourceSchema = class property Spells: IResourceLoader read FSpells; end; -const - CMusicGame = 'game'; - CMusicMagic = 'magic'; - CMusicBattle = 'battle'; - CMusicVictory = 'victory'; - CMusicDefeat = 'defeat'; - CMusicBattleWin = 'battle_win'; - CMusicMap = 'map'; - CMusicMenu = 'menu'; - var R: TResourceSchema; @@ -356,7 +346,7 @@ procedure TResourceSchema.LoadAll; begin FCharactersCache.LoadAll; FItemsCache.LoadAll; - FSpellsCache.LoadAll; + //FSpellsCache.LoadAll; end; initialization diff --git a/sources/Game/Elinor.Party.pas b/sources/Game/Elinor.Party.pas index e422315..ff48c8d 100644 --- a/sources/Game/Elinor.Party.pas +++ b/sources/Game/Elinor.Party.pas @@ -1313,7 +1313,7 @@ class procedure TLeaderParty.PutAt(const AX, AY: ShortInt; end; reMageTower: begin - Game.MediaPlayer.PlayMusic(CMusicMagic); + Game.MediaPlayer.PlayMusic('magic'); Game.MediaPlayer.PlaySound(mmSettlement); TSceneMageTower.ShowScene; F := False; @@ -1342,14 +1342,14 @@ class procedure TLeaderParty.PutAt(const AX, AY: ShortInt; end; if Game.Map.LeaderTile in Capitals then begin - Game.MediaPlayer.PlayMusic(CMusicGame); + Game.MediaPlayer.PlayMusic('game'); Game.MediaPlayer.PlaySound(mmSettlement); TSceneSettlement.ShowScene(stCapital); F := False; end; if Game.Map.LeaderTile in Cities then begin - Game.MediaPlayer.PlayMusic(CMusicGame); + Game.MediaPlayer.PlayMusic('game'); Game.MediaPlayer.PlaySound(mmSettlement); TSceneSettlement.ShowScene(stCity); F := False; diff --git a/sources/Game/Elinor.Resources.pas b/sources/Game/Elinor.Resources.pas index 836bc77..eecea45 100644 --- a/sources/Game/Elinor.Resources.pas +++ b/sources/Game/Elinor.Resources.pas @@ -1050,10 +1050,9 @@ TResBase = record ); type - TMusicEnum = (mmClick, mmStep, - mmWinBattle, mmDay, mmSettlement, mmLoot, mmLevel, - mmWar, mmExit, mmSwordAttack, mmAxeAttack, mmStaffAttack, mmBowAttack, - mmSpearAttack, mmDaggerAttack, mmClubAttack, mmBlock, mmMiss, + TMusicEnum = (mmClick, mmStep, mmWinBattle, mmDay, mmSettlement, mmLoot, + mmLevel, mmWar, mmExit, mmSwordAttack, mmAxeAttack, mmStaffAttack, + mmBowAttack, mmSpearAttack, mmDaggerAttack, mmClubAttack, mmBlock, mmMiss, mmNosferatAttack, mmLichQueenAttack, mmHumHit, mmHumDeath, mmGoblinHit, mmGoblinDeath, mmSkeletonHit, mmSkeletonDeath, mmOrcHit, mmOrcDeath, mmWolfHit, mmWolfDeath, mmWolfAttack, mmBearHit, mmBearDeath, mmBearAttack, diff --git a/sources/Scenes/Elinor.Scene.Battle2.pas b/sources/Scenes/Elinor.Scene.Battle2.pas index fe8c384..79243b5 100644 --- a/sources/Scenes/Elinor.Scene.Battle2.pas +++ b/sources/Scenes/Elinor.Scene.Battle2.pas @@ -231,12 +231,12 @@ procedure TSceneBattle2.ChCond; FBattle.BattleLog.WinInBattle; ChExperience; Game.MediaPlayer.PlaySound(mmWinBattle); - Game.MediaPlayer.PlayMusic(CMusicBattleWin); + Game.MediaPlayer.PlayMusic('battle_win'); end; if LeaderParty.IsClear then begin FBattle.BattleLog.LoseInBattle; - Game.MediaPlayer.PlayMusic(CMusicDefeat); + Game.MediaPlayer.PlayMusic('defeat'); Enabled := True; end; end; @@ -314,7 +314,7 @@ procedure TSceneBattle2.Victory; InformDialog ('Вы победили на дуэли и воины вражеского отряда разбежались!'); end; - Game.MediaPlayer.PlayMusic(CMusicMap); + Game.MediaPlayer.PlayMusic('map'); PartyList.Party[PartyList.GetPartyIndex(TLeaderParty.Leader.X, TLeaderParty.Leader.Y)].Clear; if IsNewAbility then @@ -337,7 +337,7 @@ procedure TSceneBattle2.Defeat; if IsSummon then begin IsSummon := False; - Game.MediaPlayer.PlayMusic(CMusicMap); + Game.MediaPlayer.PlayMusic('map'); Game.Show(scMap); Exit; end; @@ -1038,7 +1038,7 @@ procedure TSceneBattle2.Show(const ASceneEnum: TSceneEnum); IsNewAbility := False; FIsShowBattleLog := False; StartBattle; - Game.MediaPlayer.PlayMusic(CMusicBattle); + Game.MediaPlayer.PlayMusic('battle'); end; procedure TSceneBattle2.ShowBattleLog; diff --git a/sources/Scenes/Elinor.Scene.Battle3.pas b/sources/Scenes/Elinor.Scene.Battle3.pas index 103ed20..a266092 100644 --- a/sources/Scenes/Elinor.Scene.Battle3.pas +++ b/sources/Scenes/Elinor.Scene.Battle3.pas @@ -92,7 +92,7 @@ procedure TSceneBattle3.Show(const S: TSceneEnum); begin inherited; Start; - Game.MediaPlayer.PlayMusic(CMusicBattle); + Game.MediaPlayer.PlayMusic('battle'); end; procedure TSceneBattle3.Timer; diff --git a/sources/Scenes/Elinor.Scene.Defeat.pas b/sources/Scenes/Elinor.Scene.Defeat.pas index 8490be9..3e6041f 100644 --- a/sources/Scenes/Elinor.Scene.Defeat.pas +++ b/sources/Scenes/Elinor.Scene.Defeat.pas @@ -57,7 +57,7 @@ class procedure TSceneDefeat.ShowScene; class procedure TSceneDefeat.HideScene; begin Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlayMusic(CMusicMenu); + Game.MediaPlayer.PlayMusic('menu'); Game.IsGame := False; Game.LeaderRecordsTable.AddRecord(TCreature.GetName, TLeaderParty.Leader.Owner, TLeaderParty.Leader.LeaderClass, diff --git a/sources/Scenes/Elinor.Scene.MageTower.pas b/sources/Scenes/Elinor.Scene.MageTower.pas index 97c0368..1884985 100644 --- a/sources/Scenes/Elinor.Scene.MageTower.pas +++ b/sources/Scenes/Elinor.Scene.MageTower.pas @@ -97,7 +97,7 @@ procedure TSceneMageTower.TryLearnSpell; class procedure TSceneMageTower.HideScene; begin - Game.MediaPlayer.PlayMusic(CMusicMap); + Game.MediaPlayer.PlayMusic('map'); Game.Show(scMap); Game.MediaPlayer.PlaySound(mmClick); end; diff --git a/sources/Scenes/Elinor.Scene.Map.pas b/sources/Scenes/Elinor.Scene.Map.pas index 75d0010..684a23d 100644 --- a/sources/Scenes/Elinor.Scene.Map.pas +++ b/sources/Scenes/Elinor.Scene.Map.pas @@ -74,7 +74,7 @@ procedure TSceneMap.Escape; Spells.ActiveSpell.Clear(); Exit; end; - Game.MediaPlayer.PlayMusic(CMusicMenu); + Game.MediaPlayer.PlayMusic('menu'); Game.MediaPlayer.PlaySound(mmClick); Game.MediaPlayer.PlaySound(mmSettlement); TSceneMenu3(Game.GetScene(scMenu)).CurrentIndex := 1; diff --git a/sources/Scenes/Elinor.Scene.Menu3.pas b/sources/Scenes/Elinor.Scene.Menu3.pas index b7e3227..5182124 100644 --- a/sources/Scenes/Elinor.Scene.Menu3.pas +++ b/sources/Scenes/Elinor.Scene.Menu3.pas @@ -124,7 +124,7 @@ procedure TSceneMenu3.ContinueGame; begin if Game.IsGame then begin - Game.MediaPlayer.PlayMusic(CMusicMap); + Game.MediaPlayer.PlayMusic('map'); Game.Show(scMap); end; end; diff --git a/sources/Scenes/Elinor.Scene.Name.pas b/sources/Scenes/Elinor.Scene.Name.pas index dfa562e..816bb67 100644 --- a/sources/Scenes/Elinor.Scene.Name.pas +++ b/sources/Scenes/Elinor.Scene.Name.pas @@ -251,7 +251,7 @@ class procedure TSceneName.ShowScene; class procedure TSceneName.HideScene; begin Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlayMusic(CMusicGame); + Game.MediaPlayer.PlayMusic('game'); Game.MediaPlayer.PlaySound(mmExit); TSceneSettlement.ShowScene(stCapital); end; diff --git a/sources/Scenes/Elinor.Scene.Settlement.pas b/sources/Scenes/Elinor.Scene.Settlement.pas index f1e5f5c..eb527a6 100644 --- a/sources/Scenes/Elinor.Scene.Settlement.pas +++ b/sources/Scenes/Elinor.Scene.Settlement.pas @@ -108,7 +108,7 @@ class procedure TSceneSettlement.HideScene; Exit; end; end; - Game.MediaPlayer.PlayMusic(CMusicMap); + Game.MediaPlayer.PlayMusic('map'); Game.Show(scMap); Game.MediaPlayer.PlaySound(mmClick); Game.NewDay; diff --git a/sources/Scenes/Elinor.Scene.Victory.pas b/sources/Scenes/Elinor.Scene.Victory.pas index 8b304ff..a89419a 100644 --- a/sources/Scenes/Elinor.Scene.Victory.pas +++ b/sources/Scenes/Elinor.Scene.Victory.pas @@ -52,13 +52,13 @@ class procedure TSceneVictory.ShowScene; begin ActivePartyPosition := TLeaderParty.GetPosition; Game.Show(scVictory); - Game.MediaPlayer.PlayMusic(CMusicVictory); + Game.MediaPlayer.PlayMusic('victory'); end; class procedure TSceneVictory.HideScene; begin Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlayMusic(CMusicMenu); + Game.MediaPlayer.PlayMusic('menu'); Game.IsGame := False; Game.LeaderRecordsTable.AddRecord (TCreature.Character(TLeaderParty.Leader.Enum).Name[0], diff --git a/sources/Scenes/Elinor.Scenes.pas b/sources/Scenes/Elinor.Scenes.pas index 5865b6a..a030501 100644 --- a/sources/Scenes/Elinor.Scenes.pas +++ b/sources/Scenes/Elinor.Scenes.pas @@ -340,7 +340,7 @@ constructor TGame.Create; Statistics := TStatistics.Create; Scenario := TScenario.Create; MediaPlayer := TMediaPlayer.Create; - MediaPlayer.PlayMusic(CMusicMenu); + MediaPlayer.PlayMusic('menu'); SceneEnum := scIntro; end; From 9266fe5a459cb628126bd14619c627eda22f5cfd Mon Sep 17 00:00:00 2001 From: devapromix Date: Tue, 14 Jul 2026 22:08:38 +0300 Subject: [PATCH 6/7] fix sounds --- resources/resources.json | 108 ++++++++++-- sources/Game/Elinor.Battle.pas | 6 +- sources/Game/Elinor.Creatures.pas | 131 +++++++------- sources/Game/Elinor.MediaPlayer.pas | 20 +-- sources/Game/Elinor.NewResources.pas | 73 ++++---- sources/Game/Elinor.Party.pas | 44 ++--- sources/Game/Elinor.Resources.pas | 179 -------------------- sources/Game/Elinor.Spells.Types.pas | 2 +- sources/Game/Elinor.Spells.pas | 36 ++-- sources/Scenes/DisciplesRL.Scene.Hire.pas | 4 +- sources/Scenes/Elinor.Scene.Abilities.pas | 6 +- sources/Scenes/Elinor.Scene.Barracks.pas | 14 +- sources/Scenes/Elinor.Scene.Base.Party.pas | 2 +- sources/Scenes/Elinor.Scene.Battle2.pas | 24 +-- sources/Scenes/Elinor.Scene.Battle3.pas | 2 +- sources/Scenes/Elinor.Scene.Defeat.pas | 2 +- sources/Scenes/Elinor.Scene.Difficulty.pas | 2 +- sources/Scenes/Elinor.Scene.Faction.pas | 2 +- sources/Scenes/Elinor.Scene.Inventory.pas | 6 +- sources/Scenes/Elinor.Scene.Leader.pas | 4 +- sources/Scenes/Elinor.Scene.Loot2.pas | 14 +- sources/Scenes/Elinor.Scene.MageTower.pas | 10 +- sources/Scenes/Elinor.Scene.Map.pas | 6 +- sources/Scenes/Elinor.Scene.Menu.Simple.pas | 4 +- sources/Scenes/Elinor.Scene.Menu.Wide.pas | 4 +- sources/Scenes/Elinor.Scene.Menu3.pas | 2 +- sources/Scenes/Elinor.Scene.Merchant.pas | 10 +- sources/Scenes/Elinor.Scene.Name.pas | 8 +- sources/Scenes/Elinor.Scene.NewAbility.pas | 4 +- sources/Scenes/Elinor.Scene.Party2.pas | 8 +- sources/Scenes/Elinor.Scene.Records.pas | 8 +- sources/Scenes/Elinor.Scene.Recruit.pas | 6 +- sources/Scenes/Elinor.Scene.Scenario.pas | 2 +- sources/Scenes/Elinor.Scene.SelectUnit.pas | 52 +++--- sources/Scenes/Elinor.Scene.Settlement.pas | 18 +- sources/Scenes/Elinor.Scene.Spellbook.pas | 10 +- sources/Scenes/Elinor.Scene.Temple.pas | 16 +- sources/Scenes/Elinor.Scene.Victory.pas | 2 +- sources/Scenes/Elinor.Scenes.pas | 8 +- 39 files changed, 379 insertions(+), 480 deletions(-) diff --git a/resources/resources.json b/resources/resources.json index 867a177..629c0c7 100644 --- a/resources/resources.json +++ b/resources/resources.json @@ -1,25 +1,97 @@ { "spells": { - "bless": "bless.png", - "bone_golem": "bone_golem.png", - "chains_of_dread": "chains_of_dread.png", - "concealment": "concealment.png", - "curse": "curse.png", - "eagle_eye": "eagle_eye.png", - "fire_golem": "fire_golem.png", - "living_armor": "living_armor.png", - "meteor_shower": "meteor_shower.png", - "plague": "plague.png", - "rust": "rust.png", - "skeletion": "skeletion.png", - "speed": "speed.png", - "stone_golem": "stone_golem.png", - "strength": "strength.png", - "true_healing": "true_healing.png", - "weaken": "weaken.png" + "bless": "bless.png", + "bone_golem": "bone_golem.png", + "chains_of_dread": "chains_of_dread.png", + "concealment": "concealment.png", + "curse": "curse.png", + "eagle_eye": "eagle_eye.png", + "fire_golem": "fire_golem.png", + "living_armor": "living_armor.png", + "meteor_shower": "meteor_shower.png", + "plague": "plague.png", + "rust": "rust.png", + "skeletion": "skeletion.png", + "speed": "speed.png", + "stone_golem": "stone_golem.png", + "strength": "strength.png", + "true_healing": "true_healing.png", + "weaken": "weaken.png" }, "sounds": { - "click": "click.wav" + "click": "click.wav", + "heal": "heal.wav", + "critical_attack": "critical_attack.wav", + "settlement": "settlement.wav", + "gold": "coin.wav", + "mana": "mana.wav", + "revive": "revive.wav", + "dismiss": "dismiss.wav", + "spellbook": "spellbook.mp3", + "prepare_magic": "prepare_magic.wav", + "exit": "exit.wav", + "use_orb": "use_orb.ogg", + "imp_hit": "imp_hit.ogg", + "goblin_hit": "goblin_hit.wav", + "raise_dead": "raise_dead.wav", + "zombie_hit": "zombie_hit.ogg", + "lizardman_hit": "lizardman_hit.wav", + "explosion": "explosion.wav", + "rust": "rust.wav", + "flask_shatter": "flask_shatter.wav", + "loot": "loot.wav", + "step": "step.wav", + "battle_win": "himwar.wav", + "new_day": "day.ogg", + "new_level": "level.wav", + "battle_round": "war.wav", + "sword_attack": "sword_attack.wav", + "axe_attack": "axe_attack.wav", + "staff_attack": "staff_attack.wav", + "bow_attack": "bow_attack.wav", + "spear_attack": "spear_attack.wav", + "dagger_attack": "dagger_attack.wav", + "club_attack": "club_attack.wav", + "block": "block.wav", + "miss": "miss.ogg", + "nosferat_attack": "nosferat_attack.mp3", + "lich_queen_attack": "lich_queen_attack.mp3", + "hum_hit": "hum_hit.wav", + "hum_death": "hum_death.ogg", + "goblin_death": "goblin_death.wav", + "skeleton_hit": "skeleton_hit.wav", + "skeleton_death": "skeleton_death.wav", + "orc_hit": "orc_hit.ogg", + "orc_death": "orc_death.ogg", + "wolf_hit": "wolf_hit.wav", + "wolf_death": "wolf_death.wav", + "wolf_attack": "wolf_attack.wav", + "bear_hit": "bear_hit.wav", + "bear_death": "bear_death.wav", + "bear_attack": "bear_attack.wav", + "spider_hit": "spider_hit.wav", + "spider_death": "spider_death.wav", + "spider_attack": "spider_attack.wav", + "ghost_hit": "spider_hit.wav", + "ghost_death": "spider_death.wav", + "ghost_attack": "spider_attack.wav", + "ghoul_attack": "ghoul_attack.ogg", + "ghoul_hit": "ghoul_hit.ogg", + "ghoul_death": "ghoul_death.ogg", + "hit": "step.wav", + "death": "step.wav", + "attack": "step.wav", + "dispell": "dispell.wav", + "plague": "plague.wav", + "invisibility": "invisibility.wav", + "speed": "speed.wav", + "learn": "learn.wav", + "drink": "use_elixir.ogg", + "imp_death": "imp_death.wav", + "zombie_death": "zombie_death.ogg", + "zombie_attack": "zombie_attack.ogg", + "lizardman_death": "lizardman_death.wav", + "boost": "boost.wav" }, "music": { "game": "soliloquy.mp3", diff --git a/sources/Game/Elinor.Battle.pas b/sources/Game/Elinor.Battle.pas index 7d0b4db..2a814df 100644 --- a/sources/Game/Elinor.Battle.pas +++ b/sources/Game/Elinor.Battle.pas @@ -81,7 +81,7 @@ procedure TBattle.CheckArtifactVampiricAttack(const AAtkParty, LDamage := AAtkParty.Creature[AAtkPos].Damage.GetFullValue; LValue := Percent(LDamage, TLeaderParty.LeaderVampiricAttackValue); Sleep(50); - Game.MediaPlayer.PlaySound(mmHeal); + Game.MediaPlayer.PlaySound('heal'); AAtkParty.Heal(AAtkPos, EnsureRange(LValue, 5, 50)); LStr := TResources.RandomValue('battle.string', 'drain_life'); FBattleLog.Log.Add(Format(LStr, [TCreature.Character(AAtkCrEnum).Name[0], @@ -172,7 +172,7 @@ procedure TBattle.DamageCreature(LAtkCrEnum: TCreatureEnum; AAtkParty: TParty; if LIsCrit then begin FBattleLog.CriticalAttack; - Game.MediaPlayer.PlaySound(mmCriticalAttack); + Game.MediaPlayer.PlaySound('critical_attack'); Sleep(50); end else @@ -181,7 +181,7 @@ procedure TBattle.DamageCreature(LAtkCrEnum: TCreatureEnum; AAtkParty: TParty; atDrainLife: begin Sleep(50); - Game.MediaPlayer.PlaySound(mmHeal); + Game.MediaPlayer.PlaySound('heal'); AAtkParty.Heal(AAtkPos, EnsureRange(LDamage div 2, 5, 100)); end; end; diff --git a/sources/Game/Elinor.Creatures.pas b/sources/Game/Elinor.Creatures.pas index dcece12..6ce6408 100644 --- a/sources/Game/Elinor.Creatures.pas +++ b/sources/Game/Elinor.Creatures.pas @@ -309,7 +309,7 @@ TCreatureBase = record SourceEnum: TSourceEnum; ReachEnum: TReachEnum; Gold: Integer; - Sound: array [TCrSoundEnum] of TMusicEnum; + Sound: array [TCrSoundEnum] of string; Gender: TCreatureGender; AttackEnum: TAttackEnum; AbilityEnum: TAbilityEnum; @@ -376,7 +376,7 @@ implementation Size: szSmall; Name: ('', ''); Description: ('', '', ''); HitPoints: 0; Initiative: 0; ChancesToHit: 0; Leadership: 0; Level: 0; Damage: 0; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 0; - Sound: (mmHit, mmDeath, mmAttack); Gender: cgMale; AttackEnum: atMagic; + Sound: ('hit', 'death', 'attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 0;), // The Empire {$REGION The Empire} @@ -388,7 +388,7 @@ implementation 'He protects the capital from enemies.'); HitPoints: 900; Initiative: 90; ChancesToHit: 95; Leadership: 5; Level: 1; Damage: 250; Armor: 50; Heal: 0; SourceEnum: seLife; ReachEnum: reAll; Gold: 0; - Sound: (mmHit, mmDeath, mmAttack); Gender: cgMale; AttackEnum: atMagic; + Sound: ('hit', 'death', 'attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 0;), // Paladin (Ident: 'none'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrPaladin; @@ -398,7 +398,7 @@ implementation 'carries him over fields and forests.'); HitPoints: 150; Initiative: 50; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 50; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atPaladinSword; AbilityEnum: abBannerBearer; Rating: 0;), // Ranger (Ident: 'none'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrRanger; @@ -408,7 +408,7 @@ implementation 'ten sends them on scouting missions.'); HitPoints: 90; Initiative: 60; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 40; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmBowAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'bow_attack'); Gender: cgMale; AttackEnum: atHunterBow; AbilityEnum: abTravelLore; Rating: 0;), // Archmage (Ident: 'none'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrArchmage; @@ -417,7 +417,7 @@ implementation 'only commander in the Empire who can', 'use scrolls and staves.'); HitPoints: 65; Initiative: 40; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 30; Armor: 0; Heal: 0; SourceEnum: seAir; ReachEnum: reAll; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmStaffAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'staff_attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abUseStaffsAndScrolls; Rating: 0;), // Thief (Ident: 'none'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrThief; @@ -427,7 +427,7 @@ implementation 'serve the Empire by gathering vital intel.'); HitPoints: 100; Initiative: 60; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 30; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmDaggerAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atDagger; AbilityEnum: abStealth; Rating: 0;), // Warlord (Ident: 'none'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrWarlord; @@ -436,7 +436,7 @@ implementation 'Empire with loyalty and ruthlessly', 'deals with its enemies.'); HitPoints: 120; Initiative: 55; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 40; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 0; Sound: (mmHumHit, mmHumDeath, mmAxeAttack); Gender: cgMale; + Gold: 0; Sound: ('hum_hit', 'hum_death', 'axe_attack'); Gender: cgMale; AttackEnum: atBattleAxe; AbilityEnum: abTemplar; Rating: 0;), // Squire (Ident: 'squire'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrSquire; @@ -445,7 +445,7 @@ implementation 'his weaker compatriots, keeping', 'foes at sword’s length.'); HitPoints: 100; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 50; Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Gold: 50; Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atLongSword; AbilityEnum: abNone; Rating: 25;), // Archer (Ident: 'archer'; Faction: faTheEmpire; SubRace: reHuman; ResEnum: mrArcher; @@ -454,7 +454,7 @@ implementation 'enemies hiding behind the backs', 'of their stronger comrades.'); HitPoints: 45; Initiative: 60; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; - Gold: 40; Sound: (mmHumHit, mmHumDeath, mmBowAttack); Gender: cgMale; + Gold: 40; Sound: ('hum_hit', 'hum_death', 'bow_attack'); Gender: cgMale; AttackEnum: atBow; AbilityEnum: abNone; Rating: 10;), // Apprentice (Ident: 'apprentice'; Faction: faTheEmpire; SubRace: reHuman; @@ -463,7 +463,7 @@ implementation 'from afar, unleashing lightning', 'upon them.'); HitPoints: 35; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 15; Armor: 0; Heal: 0; SourceEnum: seAir; ReachEnum: reAll; Gold: 60; - Sound: (mmHumHit, mmHumDeath, mmStaffAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'staff_attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 5;), // Acolyte (Ident: 'acolyte'; Faction: faTheEmpire; SubRace: reHuman; @@ -472,7 +472,7 @@ implementation 'can tend to wounded allies, treating', 'their injuries one by one.'); HitPoints: 50; Initiative: 10; ChancesToHit: 100; Leadership: 0; Level: 1; Damage: 0; Armor: 0; Heal: 20; SourceEnum: seAir; ReachEnum: reAny; - Gold: 100; Sound: (mmHit, mmDeath, mmAttack); Gender: cgFemale; + Gold: 100; Sound: ('hit', 'death', 'attack'); Gender: cgFemale; AttackEnum: atHealing; AbilityEnum: abNone; Rating: 5;), {$ENDREGION The Empire} // Undead Hordes @@ -484,7 +484,7 @@ implementation 'the high priest of Alkmaar.', 'He never leaves the capital unguarded.'); HitPoints: 900; Initiative: 90; ChancesToHit: 95; Leadership: 5; Level: 1; Damage: 250; Armor: 50; Heal: 0; SourceEnum: seLife; ReachEnum: reAll; - Gold: 0; Sound: (mmHit, mmDeath, mmAttack); Gender: cgMale; + Gold: 0; Sound: ('hit', 'death', 'attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 0;), // Death Knight (Ident: 'none'; Faction: faUndeadHordes; SubRace: reUndead; @@ -495,7 +495,7 @@ implementation 'from oblivion by Mortis through the Death Knights.'); HitPoints: 150; Initiative: 50; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 50; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atSlayerSword; AbilityEnum: abBannerBearer; Rating: 0;), // Nosferat (Ident: 'none'; Faction: faUndeadHordes; SubRace: reVampire; @@ -505,7 +505,7 @@ implementation 'Mortis in exchange for power over death.'); HitPoints: 90; Initiative: 50; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 10; Armor: 0; Heal: 0; SourceEnum: seDeath; ReachEnum: reAny; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmNosferatAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'nosferat_attack'); Gender: cgMale; AttackEnum: atDrainLife; AbilityEnum: abVampirism; Rating: 0;), // Lich Queen (Ident: 'none'; Faction: faUndeadHordes; SubRace: reUndead; @@ -514,8 +514,9 @@ implementation 'Alkmaar, returned by the will of Mortis', 'as merciless Lich Queens.'); HitPoints: 65; Initiative: 40; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 30; Armor: 0; Heal: 0; SourceEnum: seFire; ReachEnum: reAll; - Gold: 0; Sound: (mmHumHit, mmHumDeath, mmLichQueenAttack); Gender: cgFemale; - AttackEnum: atMagic; AbilityEnum: abUseStaffsAndScrolls; Rating: 0;), + Gold: 0; Sound: ('hum_hit', 'hum_death', 'lich_queen_attack'); + Gender: cgFemale; AttackEnum: atMagic; AbilityEnum: abUseStaffsAndScrolls; + Rating: 0;), // Thug (Ident: 'none'; Faction: faUndeadHordes; SubRace: reUndead; ResEnum: mrThug; Size: szSmall; Name: ('Thug', 'Thug'); @@ -524,7 +525,7 @@ implementation 'ning where strength is not enough.'); HitPoints: 100; Initiative: 60; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 30; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmDaggerAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atDaggerOfShadows; AbilityEnum: abStealth; Rating: 0;), // Dominator (Ident: 'none'; Faction: faUndeadHordes; SubRace: reUndead; @@ -533,7 +534,7 @@ implementation 'turned to life by Mortis to sow death', 'and destruction all around.'); HitPoints: 125; Initiative: 50; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 35; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 0; Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Gold: 0; Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atBattleAxe; AbilityEnum: abTemplar; Rating: 0;), // Fighter (Ident: 'fighter'; Faction: faUndeadHordes; SubRace: reUndead; @@ -543,7 +544,7 @@ implementation 'They know neither fear nor mercy.'); HitPoints: 120; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 50; - Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atLongSword; AbilityEnum: abNone; Rating: 30;), // Ghost (Ident: 'ghost'; Faction: faUndeadHordes; SubRace: reUndead; @@ -552,7 +553,7 @@ implementation 'to the world of the living.'); HitPoints: 45; Initiative: 20; ChancesToHit: 60; Leadership: 0; Level: 1; Damage: 0; Armor: 0; Heal: 0; SourceEnum: seMind; ReachEnum: reAny; Gold: 50; - Sound: (mmGhostHit, mmGhostDeath, mmGhostAttack); Gender: cgMale; + Sound: ('ghost_hit', 'ghost_death', 'ghost_attack'); Gender: cgMale; AttackEnum: atParalyze; AbilityEnum: abNone; Rating: 10;), // Initiate (Ident: 'initiate'; Faction: faUndeadHordes; SubRace: reUndead; @@ -562,7 +563,7 @@ implementation 'of their goddess Mortis.'); HitPoints: 45; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 15; Armor: 0; Heal: 0; SourceEnum: seDeath; ReachEnum: reAll; Gold: 60; - Sound: (mmHumHit, mmHumDeath, mmStaffAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'staff_attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 10;), // Wyvern (Ident: 'wyvern'; Faction: faUndeadHordes; SubRace: reUndeadDragon; @@ -571,7 +572,7 @@ implementation 'thus creating wyverns that fight', 'in the ranks of the undead army.'); HitPoints: 225; Initiative: 35; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seDeath; ReachEnum: reAll; - Gold: 100; Sound: (mmHit, mmDeath, mmAttack); Gender: cgFemale; + Gold: 100; Sound: ('hit', 'death', 'attack'); Gender: cgFemale; AttackEnum: atPoisonousBreath; AbilityEnum: abNone; Rating: 40;), {$ENDREGION UndeadHordes} // Legions Of The Damned @@ -584,7 +585,7 @@ implementation 'never leaving it undefended.'); HitPoints: 900; Initiative: 90; ChancesToHit: 95; Leadership: 5; Level: 1; Damage: 250; Armor: 50; Heal: 0; SourceEnum: seLife; ReachEnum: reAll; Gold: 0; - Sound: (mmHit, mmDeath, mmAttack); Gender: cgMale; AttackEnum: atMagic; + Sound: ('hit', 'death', 'attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 0;), // Duke (Ident: 'none'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -593,7 +594,7 @@ implementation 'в битву, сжимая меч в окровавленных', 'руках.'); HitPoints: 150; Initiative: 50; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 50; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atPhoenixSword; AbilityEnum: abFlying; Rating: 0;), // Counselor (Ident: 'none'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -602,7 +603,7 @@ implementation 'Он путешествует по землям Невендаара', 'с высокой скоростью.'); HitPoints: 90; Initiative: 40; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 40; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; - Gold: 0; Sound: (mmHumHit, mmHumDeath, mmBowAttack); Gender: cgMale; + Gold: 0; Sound: ('hum_hit', 'hum_death', 'bow_attack'); Gender: cgMale; AttackEnum: atCrossbow; AbilityEnum: abTravelLore; Rating: 0;), // Arch-Devil (Ident: 'none'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -611,7 +612,7 @@ implementation 'он обладает глубокими знаниями', 'о посохах и свитках.'); HitPoints: 65; Initiative: 40; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 30; Armor: 0; Heal: 0; SourceEnum: seFire; ReachEnum: reAll; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmStaffAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'staff_attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abUseStaffsAndScrolls; Rating: 0;), // Ripper (Ident: 'none'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -620,7 +621,7 @@ implementation 'медленном и мастерском извлечении', 'правды из его жертв.'); HitPoints: 90; Initiative: 60; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 35; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmDaggerAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atFlameDagger; AbilityEnum: abStealth; Rating: 0;), // Chieftain (Ident: 'none'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -629,7 +630,7 @@ implementation 'отрядов демонов и ведут адские', 'когорты в бой.'); HitPoints: 110; Initiative: 50; ChancesToHit: 80; Leadership: 1; Level: 1; Damage: 45; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 0; - Sound: (mmHumHit, mmHumDeath, mmClubAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'club_attack'); Gender: cgMale; AttackEnum: atFireHammer; AbilityEnum: abTemplar; Rating: 0;), // Possessed (Ident: 'possessed'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -639,7 +640,7 @@ implementation 'бы они сражались в адских сражениях.'); HitPoints: 120; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 50; - Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atLongSword; AbilityEnum: abNone; Rating: 30;), // Gargoyle (Ident: 'gargoyle'; Faction: faLegionsOfTheDamned; SubRace: reGargoyle; @@ -648,7 +649,7 @@ implementation 'часть получаемого урона, делая', 'из них прекрасных защитных воинов.'); HitPoints: 75; Initiative: 60; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 25; Armor: 15; Heal: 0; SourceEnum: seEarth; ReachEnum: reAny; - Gold: 90; Sound: (mmHit, mmDeath, mmAttack); Gender: cgFemale; + Gold: 90; Sound: ('hit', 'death', 'attack'); Gender: cgFemale; AttackEnum: atStones; AbilityEnum: abNone; Rating: 30;), // Cultist (Ident: 'cultist'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -657,7 +658,7 @@ implementation 'адским силам, дабы призвать огонь', 'на всех своих врагов в битве.'); HitPoints: 45; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 15; Armor: 0; Heal: 0; SourceEnum: seFire; ReachEnum: reAll; - Gold: 60; Sound: (mmHumHit, mmHumDeath, mmStaffAttack); Gender: cgMale; + Gold: 60; Sound: ('hum_hit', 'hum_death', 'staff_attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 20;), // Devil (Ident: 'devil'; Faction: faLegionsOfTheDamned; SubRace: reHeretic; @@ -666,7 +667,7 @@ implementation 'Тёмного Повелителя Бетрезена.'); HitPoints: 120; Initiative: 35; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 40; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 100; - Sound: (mmHit, mmDeath, mmAttack); Gender: cgMale; AttackEnum: atClaws; + Sound: ('hit', 'death', 'attack'); Gender: cgMale; AttackEnum: atClaws; AbilityEnum: abNone; Rating: 35;), {$ENDREGION Legions Of The Damned} // Neutral Green Skins @@ -678,7 +679,7 @@ implementation 'They are not as strong,', 'but they are cunning and agile.'); HitPoints: 50; Initiative: 30; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 15; Armor: 0; Heal: 0; SourceEnum: seLife; ReachEnum: reAdj; - Gold: 50; Sound: (mmGoblinHit, mmGoblinDeath, mmSpearAttack); + Gold: 50; Sound: ('goblin_hit', 'goblin_death', 'spear_attack'); Gender: cgMale; AttackEnum: atSpear; AbilityEnum: abNone; Rating: 25;), // Goblin Rider (Ident: 'goblin-rider'; Faction: faNeutrals; SubRace: reGreenSkin; @@ -688,7 +689,7 @@ implementation 'wargs and use them in battle', 'as a means of transportation.'); HitPoints: 75; Initiative: 35; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seLife; ReachEnum: reAdj; - Gold: 150; Sound: (mmGoblinHit, mmGoblinDeath, mmDaggerAttack); + Gold: 150; Sound: ('goblin_hit', 'goblin_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atDagger; AbilityEnum: abNone; Rating: 35;), // Goblin Archer (Ident: 'goblin-archer'; Faction: faNeutrals; SubRace: reGreenSkin; @@ -698,7 +699,7 @@ implementation 'in ambushes and raids,', 'using crude arrows.'); HitPoints: 40; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 15; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; Gold: 75; - Sound: (mmGoblinHit, mmGoblinDeath, mmBowAttack); Gender: cgMale; + Sound: ('goblin_hit', 'goblin_death', 'bow_attack'); Gender: cgMale; AttackEnum: atBow; AbilityEnum: abNone; Rating: 20;), // Goblin Elder (Ident: 'goblin-elder'; Faction: faNeutrals; SubRace: reGreenSkin; @@ -708,7 +709,7 @@ implementation 'to practice the art of magic,', 'but from time to time elders do emerge.'); HitPoints: 35; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 10; Armor: 0; Heal: 0; SourceEnum: seFire; ReachEnum: reAll; - Gold: 100; Sound: (mmGoblinHit, mmGoblinDeath, mmStaffAttack); + Gold: 100; Sound: ('goblin_hit', 'goblin_death', 'staff_attack'); Gender: cgMale; AttackEnum: atMagic; AbilityEnum: abNone; Rating: 10;), // Black Goblin (Ident: 'black-goblin'; Faction: faNeutrals; SubRace: reGreenSkin; @@ -718,7 +719,7 @@ implementation 'to master the art of killing,', 'but those who do become assassins.'); HitPoints: 60; Initiative: 35; ChancesToHit: 75; Leadership: 0; Level: 1; Damage: 20; Armor: 0; Heal: 0; SourceEnum: seLife; ReachEnum: reAny; - Gold: 65; Sound: (mmGoblinHit, mmGoblinDeath, mmDaggerAttack); + Gold: 65; Sound: ('goblin_hit', 'goblin_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atDagger; AbilityEnum: abNone; Rating: 30;), // Orc @@ -728,7 +729,7 @@ implementation 'front lines in battles, because they', 'have a sturdy build.'); HitPoints: 200; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 55; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 200; Sound: (mmOrcHit, mmOrcDeath, mmAxeAttack); Gender: cgMale; + Gold: 200; Sound: ('orc_hit', 'orc_death', 'axe_attack'); Gender: cgMale; AttackEnum: atBattleAxe; AbilityEnum: abNone; Rating: 40;), // Trog @@ -737,7 +738,7 @@ implementation Description: ('Trogs are savage creatures,', ' driven only by brute ', 'force.'); HitPoints: 250; Initiative: 30; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 110; Armor: 0; Heal: 0; SourceEnum: seWeapon; - ReachEnum: reAdj; Gold: 270; Sound: (mmOrcHit, mmOrcDeath, mmClubAttack); + ReachEnum: reAdj; Gold: 270; Sound: ('orc_hit', 'orc_death', 'club_attack'); Gender: cgMale; AttackEnum: atClaws; AbilityEnum: abNone; Rating: 50;), // Troll (Ident: 'troll'; Faction: faNeutrals; SubRace: reGreenSkin; @@ -746,7 +747,7 @@ implementation 'slow but incredibly strong,', 'thriving in caves and ruins.'); HitPoints: 300; Initiative: 25; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 120; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 300; Sound: (mmOrcHit, mmOrcDeath, mmClubAttack); Gender: cgMale; + Gold: 300; Sound: ('orc_hit', 'orc_death', 'club_attack'); Gender: cgMale; AttackEnum: atClub; AbilityEnum: abNone; Rating: 60;), // Ogre (Ident: 'ogre'; Faction: faNeutrals; SubRace: reGreenSkin; ResEnum: mrOgre; @@ -755,7 +756,7 @@ implementation 'tactics or strategy.'); HitPoints: 350; Initiative: 20; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 130; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 350; - Sound: (mmOrcHit, mmOrcDeath, mmClubAttack); Gender: cgMale; + Sound: ('orc_hit', 'orc_death', 'club_attack'); Gender: cgMale; AttackEnum: atClub; AbilityEnum: abNone; Rating: 70;), {$ENDREGION Green Skins} // @@ -766,7 +767,7 @@ implementation 'silent and deadly, striking', 'from the swamps and marshes'); HitPoints: 250; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 60; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; - Gold: 250; Sound: (mmLizardmanHit, mmLizardmanDeath, mmBowAttack); + Gold: 250; Sound: ('lizardman_hit', 'lizardman_death', 'bow_attack'); Gender: cgMale; AttackEnum: atBow; AbilityEnum: abNone; Rating: 45;), // Neutral Humans @@ -778,7 +779,7 @@ implementation 'they call their home.'); HitPoints: 40; Initiative: 30; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 15; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 50; - Sound: (mmHumHit, mmHumDeath, mmSpearAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'spear_attack'); Gender: cgMale; AttackEnum: atSpear; AbilityEnum: abNone; Rating: 10;), // Man at Arms (Ident: 'man-at-arms'; Faction: faNeutrals; SubRace: reHuman; @@ -787,7 +788,7 @@ implementation 'services to anyone who pays', 'a gold coin.'); HitPoints: 95; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 40; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 100; - Sound: (mmHumHit, mmHumDeath, mmSwordAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'sword_attack'); Gender: cgMale; AttackEnum: atLongSword; AbilityEnum: abNone; Rating: 30;), // Rogue (Ident: 'rogue'; Faction: faNeutrals; SubRace: reHuman; ResEnum: mrRogue; @@ -796,7 +797,7 @@ implementation 'and attack defenseless travelers', 'along roads and forest paths.'); HitPoints: 75; Initiative: 65; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 80; Sound: (mmHumHit, mmHumDeath, mmDaggerAttack); Gender: cgMale; + Gold: 80; Sound: ('hum_hit', 'hum_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atDagger; AbilityEnum: abNone; Rating: 20;), {$ENDREGION Humans} // Neutral Undeads @@ -808,7 +809,7 @@ implementation 'capable of affecting the mind', 'of their victims.'); HitPoints: 150; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 35; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 125; - Sound: (mmGhoulHit, mmGhoulDeath, mmGhoulAttack); Gender: cgMale; + Sound: ('ghoul_hit', 'ghoul_death', 'ghoul_attack'); Gender: cgMale; AttackEnum: atClaws; AbilityEnum: abNone; Rating: 40;), // Dark Elf Gast (Ident: 'dark-elf-gast'; Faction: faNeutrals; SubRace: reDarkElf; @@ -818,7 +819,7 @@ implementation 'Death twisted them into undead abominations.'); HitPoints: 110; Initiative: 40; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 40; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAny; Gold: 125; - Sound: (mmHumHit, mmHumDeath, mmDaggerAttack); Gender: cgMale; + Sound: ('hum_hit', 'hum_death', 'dagger_attack'); Gender: cgMale; AttackEnum: atDaggerOfShadows; AbilityEnum: abNone; Rating: 45;), // Skeleton Warrior (Ident: 'skeleton-warrior'; Faction: faNeutrals; SubRace: reUndead; @@ -828,7 +829,7 @@ implementation 'warriors raised by dark forces', 'to fight without fear.'); HitPoints: 100; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 25; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 95; - Sound: (mmSkeletonHit, mmSkeletonDeath, mmSwordAttack); Gender: cgMale; + Sound: ('skeleton_hit', 'skeleton_death', 'sword_attack'); Gender: cgMale; AttackEnum: atSlayerSword; AbilityEnum: abNone; Rating: 30;), // Zombie (Ident: 'zombie'; Faction: faNeutrals; SubRace: reUndead; ResEnum: mrZombie; @@ -837,7 +838,7 @@ implementation 'acting consciously, but each of ', 'them remains a deadly threat.'); HitPoints: 200; Initiative: 45; ChancesToHit: 65; Leadership: 0; Level: 1; Damage: 50; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 275; Sound: (mmZombieHit, mmZombieDeath, mmZombieAttack); + Gold: 275; Sound: ('zombie_hit', 'zombie_death', 'zombie_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 60;), // Reaper (Ident: 'reaper'; Faction: faNeutrals; SubRace: reUndead; ResEnum: mrReaper; @@ -846,8 +847,8 @@ implementation 'of absolute Void and are capable', 'of affecting the mind.'); HitPoints: 250; Initiative: 55; ChancesToHit: 80; Leadership: 0; Level: 4; Damage: 75; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 325; Sound: (mmGhoulHit, mmGhoulDeath, mmGhoulAttack); Gender: cgMale; - AttackEnum: atScythe; AbilityEnum: abNone; Rating: 70;), + Gold: 325; Sound: ('ghoul_hit', 'ghoul_death', 'ghoul_attack'); + Gender: cgMale; AttackEnum: atScythe; AbilityEnum: abNone; Rating: 70;), {$ENDREGION Undeads} // Neutral Heretics {$REGION Heretics} @@ -858,7 +859,7 @@ implementation 'and dangerous in close combat.'); HitPoints: 75; Initiative: 45; ChancesToHit: 75; Leadership: 0; Level: 1; Damage: 20; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 75; - Sound: (mmImpHit, mmImpDeath, mmSwordAttack); Gender: cgMale; + Sound: ('imp_hit', 'imp_death', 'sword_attack'); Gender: cgMale; AttackEnum: atShortSword; AbilityEnum: abNone; Rating: 35;), {$ENDREGION Heretics} // Neutral Animals @@ -870,7 +871,7 @@ implementation 'spider completely paralyzes the', 'victim, preventing escape.'); HitPoints: 420; Initiative: 35; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 130; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; - Gold: 400; Sound: (mmSpiderHit, mmSpiderDeath, mmSpiderAttack); + Gold: 400; Sound: ('spider_hit', 'spider_death', 'spider_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 80;), // Wolf @@ -881,7 +882,7 @@ implementation 'the warriors who cross their path.'); HitPoints: 180; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 55; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 200; - Sound: (mmWolfHit, mmWolfDeath, mmWolfAttack); Gender: cgMale; + Sound: ('wolf_hit', 'wolf_death', 'wolf_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 70;), // Dire Wolf (Ident: 'dire-wolf'; Faction: faNeutrals; SubRace: reAnimal; @@ -891,7 +892,7 @@ implementation 'Few survive an encounter with one.'); HitPoints: 200; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 60; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 220; - Sound: (mmWolfHit, mmWolfDeath, mmWolfAttack); Gender: cgMale; + Sound: ('wolf_hit', 'wolf_death', 'wolf_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 80;), // Spirit Wolf (Ident: 'spirit-wolf'; Faction: faNeutrals; SubRace: reAnimal; @@ -901,7 +902,7 @@ implementation 'Few survive an encounter with one.'); HitPoints: 250; Initiative: 50; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 65; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 250; - Sound: (mmWolfHit, mmWolfDeath, mmWolfAttack); Gender: cgMale; + Sound: ('wolf_hit', 'wolf_death', 'wolf_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 90;), // Polar Bear @@ -912,7 +913,7 @@ implementation 'They strike without warning when threatened.'); HitPoints: 320; Initiative: 70; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 85; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 700; - Sound: (mmBearHit, mmBearDeath, mmBearAttack); Gender: cgMale; + Sound: ('bear_hit', 'bear_death', 'bear_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 60;), // Brown Bear (Ident: 'brown-bear'; Faction: faNeutrals; SubRace: reAnimal; @@ -922,7 +923,7 @@ implementation 'Disturbing one is often fatal.'); HitPoints: 300; Initiative: 70; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 80; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 600; - Sound: (mmBearHit, mmBearDeath, mmBearAttack); Gender: cgMale; + Sound: ('bear_hit', 'bear_death', 'bear_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 55;), // Black Bear (Ident: 'black-bear'; Faction: faNeutrals; SubRace: reAnimal; @@ -932,7 +933,7 @@ implementation 'A cornered black bear is a fierce opponent.'); HitPoints: 280; Initiative: 70; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 75; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 500; - Sound: (mmBearHit, mmBearDeath, mmBearAttack); Gender: cgMale; + Sound: ('bear_hit', 'bear_death', 'bear_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 50;), {$ENDREGION Animals} // Golems @@ -943,7 +944,7 @@ implementation Description: ('', '', ''); HitPoints: 240; Initiative: 40; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 50; Armor: 5; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 700; - Sound: (mmBearHit, mmBearDeath, mmBearAttack); Gender: cgMale; + Sound: ('bear_hit', 'bear_death', 'bear_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 50;), // Stone Golem (Ident: 'stone-golem'; Faction: faNeutrals; SubRace: reGolem; @@ -951,7 +952,7 @@ implementation Description: ('', '', ''); HitPoints: 210; Initiative: 40; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 55; Armor: 5; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 650; - Sound: (mmBearHit, mmBearDeath, mmBearAttack); Gender: cgMale; + Sound: ('bear_hit', 'bear_death', 'bear_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 45;), // Fire Golem (Ident: 'fire-golem'; Faction: faNeutrals; SubRace: reGolem; @@ -959,7 +960,7 @@ implementation Description: ('', '', ''); HitPoints: 220; Initiative: 40; ChancesToHit: 70; Leadership: 0; Level: 1; Damage: 55; Armor: 5; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAdj; Gold: 675; - Sound: (mmBearHit, mmBearDeath, mmBearAttack); Gender: cgMale; + Sound: ('bear_hit', 'bear_death', 'bear_attack'); Gender: cgMale; AttackEnum: atBites; AbilityEnum: abNone; Rating: 45;), {$ENDREGION Golems} // Dragons @@ -971,7 +972,7 @@ implementation 'dragon melts flesh and armor,', 'making escape impossible.'); HitPoints: 800; Initiative: 40; ChancesToHit: 75; Leadership: 0; Level: 1; Damage: 125; Armor: 0; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAll; - Gold: 2000; Sound: (mmSpiderHit, mmSpiderDeath, mmSpiderAttack); + Gold: 2000; Sound: ('spider_hit', 'spider_death', 'spider_attack'); Gender: cgMale; AttackEnum: atFireBreath; AbilityEnum: abNone; Rating: 350;), // White Dragon @@ -981,7 +982,7 @@ implementation 'dragon locks the victim in ice,', 'leaving no chance to flee.'); HitPoints: 900; Initiative: 40; ChancesToHit: 80; Leadership: 0; Level: 1; Damage: 120; Armor: 10; Heal: 0; SourceEnum: seWeapon; ReachEnum: reAll; - Gold: 2500; Sound: (mmSpiderHit, mmSpiderDeath, mmSpiderAttack); + Gold: 2500; Sound: ('spider_hit', 'spider_death', 'spider_attack'); Gender: cgMale; AttackEnum: atIceBreath; AbilityEnum: abNone; Rating: 400;) {$ENDREGION Dragons} // diff --git a/sources/Game/Elinor.MediaPlayer.pas b/sources/Game/Elinor.MediaPlayer.pas index c0db2a0..b3a19cc 100644 --- a/sources/Game/Elinor.MediaPlayer.pas +++ b/sources/Game/Elinor.MediaPlayer.pas @@ -32,12 +32,10 @@ TMediaPlayer = class(TObject) property SoundVolume: ShortInt read GetSoundVolume write SetSoundVolume; property MusicVolume: ShortInt read GetMusicVolume write SetMusicVolume; property CurrentChannel: Integer read FCurrentChannel write FCurrentChannel; - function PlaySound(const FileName: string; F: Boolean = False) - : Boolean; overload; - function PlaySound(const MusicEnum: TMusicEnum; F: Boolean = False) - : Boolean; overload; - function PlayMusic(const AKey: string; F: Boolean = True) + function PlaySound(const AKey: string; F: Boolean = False) : Boolean; overload; + function PlayMusic(const AKey: string; F: Boolean = True): Boolean; + overload; procedure StopSound; procedure StopMusic; end; @@ -94,19 +92,13 @@ function TMediaPlayer.PlayMusic(const AKey: string; F: Boolean): Boolean; begin StopMusic; CurrentChannel := MusicChannel; - Play(R.Musics[AKey + '.mp3'], F, mtMusic); + Play(R.Musics[AKey], F, mtMusic); CurrentChannel := SoundChannel; end; -function TMediaPlayer.PlaySound(const MusicEnum: TMusicEnum; - F: Boolean): Boolean; -begin - PlaySound(ResMusicPath[MusicEnum], F); -end; - -function TMediaPlayer.PlaySound(const FileName: string; F: Boolean): Boolean; +function TMediaPlayer.PlaySound(const AKey: string; F: Boolean): Boolean; begin - Play(FileName, F, mtSound); + Play(R.Sounds[AKey], F, mtSound); end; function TMediaPlayer.Play(const FileName: string; F: Boolean; diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index d18e306..69fc6c9 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -53,7 +53,8 @@ TValuePathResourceLoader = class(TInterfacedObject, IResourceLoader) FBasePath: string; function Get(const Key: string): string; public - constructor Create(AParent: IResourceLoader; const ABasePath: string); + constructor Create(AParent: IResourceLoader; + const ABasePath: string); property Items[const Key: string]: string read Get; default; function GetKeys(const prefix: string = ''): TArray; end; @@ -63,7 +64,8 @@ TValuePathResourceLoader = class(TInterfacedObject, IResourceLoader) procedure LoadAll(); end; - TCachedResourceLoader = class(TInterfacedObject, IResourceLoader, IResourceCache) + TCachedResourceLoader = class(TInterfacedObject, IResourceLoader, + IResourceCache) private FParent: IResourceLoader; FCache: TDictionary; @@ -136,7 +138,8 @@ constructor TCachedResourceLoader.Create(AParent: IResourceLoader); FCache := TDictionary.Create; end; -function TCachedResourceLoader.GetKeys(const prefix: string = ''): TArray; +function TCachedResourceLoader.GetKeys(const prefix: string = '') + : TArray; begin Result := FParent.GetKeys(prefix); end; @@ -144,20 +147,21 @@ function TCachedResourceLoader.GetKeys(const prefix: string = ''): TArray.LoadAll; var keys: TArray; - key: string; + Key: string; begin keys := FParent.GetKeys(''); - for key in keys do - FParent[key]; + for Key in keys do + FParent[Key]; end; destructor TCachedResourceLoader.Destroy; begin - FCache.Free; + FreeAndNil(FCache); inherited; end; -constructor TPrefixedResourceLoader.Create(AParent: IResourceLoader; const APrefix: string); +constructor TPrefixedResourceLoader.Create(AParent: IResourceLoader; + const APrefix: string); begin inherited Create; if not Assigned(AParent) then @@ -172,14 +176,16 @@ function TPrefixedResourceLoader.Get(const Key: string): T; Result := FParent.Get(FPrefix + Key); end; -function TPrefixedResourceLoader.GetKeys(const prefix: string = ''): TArray; +function TPrefixedResourceLoader.GetKeys(const prefix: string = '') + : TArray; var LSearchRec: TSearchRec; LFiles: TList; begin LFiles := TList.Create; try - if FindFirst(IncludeTrailingPathDelimiter(FPrefix) + prefix + '*.*', faAnyFile, LSearchRec) = 0 then + if FindFirst(IncludeTrailingPathDelimiter(FPrefix) + prefix + '*.*', + faAnyFile, LSearchRec) = 0 then begin repeat if (LSearchRec.Attr and faDirectory) = 0 then @@ -193,7 +199,8 @@ function TPrefixedResourceLoader.GetKeys(const prefix: string = ''): TArray; end; end; -constructor TValuePathResourceLoader.Create(AParent: IResourceLoader; const ABasePath: string); +constructor TValuePathResourceLoader.Create(AParent: IResourceLoader; + const ABasePath: string); begin inherited Create; if not Assigned(AParent) then @@ -256,7 +264,8 @@ function TValuePathResourceLoader.Get(const Key: string): string; Result := FBasePath + FParent.Get(Key); end; -function TValuePathResourceLoader.GetKeys(const prefix: string = ''): TArray; +function TValuePathResourceLoader.GetKeys(const prefix: string = '') + : TArray; begin Result := FParent.GetKeys(prefix); end; @@ -279,7 +288,8 @@ function TPNGImageLoader.GetKeys(const prefix: string = ''): TArray; begin LFiles := TList.Create; try - if FindFirst(IncludeTrailingPathDelimiter(prefix) + '*.*', faAnyFile, LSearchRec) = 0 then + if FindFirst(IncludeTrailingPathDelimiter(prefix) + '*.*', faAnyFile, + LSearchRec) = 0 then begin repeat if (LSearchRec.Attr and faDirectory) = 0 then @@ -299,7 +309,8 @@ constructor TResourceSchema.Create; png: TPNGImageLoader; cache: TCachedResourceLoader; begin - basePath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + 'resources'); + basePath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + + 'resources'); jsonPath := basePath + 'resources.json'; if not TFile.Exists(jsonPath) then @@ -310,26 +321,26 @@ constructor TResourceSchema.Create; if not Assigned(FJsonRoot) then raise Exception.CreateFmt('Failed to parse JSON: %s', [jsonPath]); - FMusics := TValuePathResourceLoader.Create( - TJsonResourceLoader.Create(FJsonRoot, 'music'), basePath + 'music\'); + FMusics := TValuePathResourceLoader.Create + (TJsonResourceLoader.Create(FJsonRoot, 'music'), basePath + 'music\'); - FSounds := TValuePathResourceLoader.Create( - TJsonResourceLoader.Create(FJsonRoot, 'sounds'), basePath + 'sounds\'); + FSounds := TValuePathResourceLoader.Create + (TJsonResourceLoader.Create(FJsonRoot, 'sounds'), basePath + 'sounds\'); png := TPNGImageLoader.Create; - cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'characters\')); + cache := TCachedResourceLoader.Create + (TPrefixedResourceLoader.Create(png, basePath + 'characters\')); FCharacters := cache; FCharactersCache := cache; - cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'items\')); + cache := TCachedResourceLoader.Create + (TPrefixedResourceLoader.Create(png, basePath + 'items\')); FItems := cache; FItemsCache := cache; - cache := TCachedResourceLoader.Create( - TPrefixedResourceLoader.Create(png, basePath + 'spells\')); + cache := TCachedResourceLoader.Create + (TPrefixedResourceLoader.Create(png, basePath + 'spells\')); FSpells := cache; FSpellsCache := cache; end; @@ -338,7 +349,7 @@ destructor TResourceSchema.Destroy; begin FMusics := nil; FSounds := nil; - FJsonRoot.Free; + FreeAndNil(FJsonRoot); inherited; end; @@ -350,10 +361,12 @@ procedure TResourceSchema.LoadAll; end; initialization - R := TResourceSchema.Create; - R.LoadAll; + +R := TResourceSchema.Create; +R.LoadAll; finalization - FreeAndNil(R); + +FreeAndNil(R); end. diff --git a/sources/Game/Elinor.Party.pas b/sources/Game/Elinor.Party.pas index ff48c8d..6dc5db8 100644 --- a/sources/Game/Elinor.Party.pas +++ b/sources/Game/Elinor.Party.pas @@ -737,7 +737,7 @@ procedure TParty.TakeDamage(const ADamage: Integer; const APosition: TPosition); if (LDamage > 0) then HitPoints.ModifyCurrValue(-LDamage) else - Game.MediaPlayer.PlaySound(mmBlock); + Game.MediaPlayer.PlaySound('block'); end; end; end; @@ -780,7 +780,7 @@ procedure TParty.UpdateLevel(const APosition: TPosition); if IsMaxLevel then Exit; Experience := 0; - Game.MediaPlayer.PlaySound(mmLevel); + Game.MediaPlayer.PlaySound('level'); LMaxHitPoints := EnsureRange(HitPoints.GetMaxValue + (HitPoints.GetMaxValue div 10), 25, 1000); @@ -901,48 +901,48 @@ procedure TLeaderParty.Quaff(const AItemIndex: Integer; procedure HealCreature(const Amount: Integer); begin - Game.MediaPlayer.PlaySound(mmDrink); - Game.MediaPlayer.PlaySound(mmHeal); + Game.MediaPlayer.PlaySound('drink'); + Game.MediaPlayer.PlaySound('heal'); TLeaderParty.Leader.Heal(APosition, Amount); Inventory.Clear(AItemIndex); end; procedure ReviveCreature; begin - Game.MediaPlayer.PlaySound(mmDrink); - Game.MediaPlayer.PlaySound(mmRevive); + Game.MediaPlayer.PlaySound('drink'); + Game.MediaPlayer.PlaySound('revive'); TLeaderParty.Leader.Revive(APosition); Inventory.Clear(AItemIndex); end; procedure IncreaseDamageTemp(const APercent: Integer); begin - Game.MediaPlayer.PlaySound(mmDrink); - Game.MediaPlayer.PlaySound(mmBoost); + Game.MediaPlayer.PlaySound('drink'); + Game.MediaPlayer.PlaySound('boost'); TLeaderParty.Leader.IncreaseDamageTemp(APercent, APosition); Inventory.Clear(AItemIndex); end; procedure IncreaseChancesToHitTemp(const APercent: Integer); begin - Game.MediaPlayer.PlaySound(mmDrink); - Game.MediaPlayer.PlaySound(mmBoost); + Game.MediaPlayer.PlaySound('drink'); + Game.MediaPlayer.PlaySound('boost'); TLeaderParty.Leader.IncreaseChancesToHitTemp(APercent, APosition); Inventory.Clear(AItemIndex); end; procedure IncreaseHitPointsPermanently; begin - Game.MediaPlayer.PlaySound(mmDrink); - Game.MediaPlayer.PlaySound(mmBoost); + Game.MediaPlayer.PlaySound('drink'); + Game.MediaPlayer.PlaySound('boost'); TLeaderParty.Leader.IncreaseHitPointsPermanently(APosition); Inventory.Clear(AItemIndex); end; procedure IncreaseChancesToHitPermanently; begin - Game.MediaPlayer.PlaySound(mmDrink); - Game.MediaPlayer.PlaySound(mmBoost); + Game.MediaPlayer.PlaySound('drink'); + Game.MediaPlayer.PlaySound('boost'); TLeaderParty.Leader.IncreaseChancesToHitPermanently(APosition); Inventory.Clear(AItemIndex); end; @@ -1219,7 +1219,7 @@ class procedure TLeaderParty.MoveUnit(AParty: TParty); begin PartyList.Party[TLeaderParty.LeaderPartyIndex].ChPosition(AParty, ActivePartyPosition, CurrentPartyPosition); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; end; @@ -1270,7 +1270,7 @@ class procedure TLeaderParty.PutAt(const AX, AY: ShortInt; begin Leader.SetLocation(AX, AY); Game.Statistics.IncValue(stTilesMoved); - Game.MediaPlayer.PlaySound(mmStep); + Game.MediaPlayer.PlaySound('step'); with TLeaderParty.Leader do begin SetLocation(AX, AY); @@ -1307,26 +1307,26 @@ class procedure TLeaderParty.PutAt(const AX, AY: ShortInt; end; reSTower: begin - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); Game.Map.UpdateRadius(Leader.X, Leader.Y, 3); F := False; end; reMageTower: begin Game.MediaPlayer.PlayMusic('magic'); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); TSceneMageTower.ShowScene; F := False; end; reMerchantPotions: begin - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); TSceneMerchant.ShowScene(TLeaderParty.Leader, mtPotions, scMap); F := False; end; reMerchantArtifacts: begin - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); TSceneMerchant.ShowScene(TLeaderParty.Leader, mtArtifacts, scMap); F := False; end; @@ -1343,14 +1343,14 @@ class procedure TLeaderParty.PutAt(const AX, AY: ShortInt; if Game.Map.LeaderTile in Capitals then begin Game.MediaPlayer.PlayMusic('game'); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); TSceneSettlement.ShowScene(stCapital); F := False; end; if Game.Map.LeaderTile in Cities then begin Game.MediaPlayer.PlayMusic('game'); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); TSceneSettlement.ShowScene(stCity); F := False; end; diff --git a/sources/Game/Elinor.Resources.pas b/sources/Game/Elinor.Resources.pas index eecea45..0350106 100644 --- a/sources/Game/Elinor.Resources.pas +++ b/sources/Game/Elinor.Resources.pas @@ -1049,179 +1049,12 @@ TResBase = record // ); -type - TMusicEnum = (mmClick, mmStep, mmWinBattle, mmDay, mmSettlement, mmLoot, - mmLevel, mmWar, mmExit, mmSwordAttack, mmAxeAttack, mmStaffAttack, - mmBowAttack, mmSpearAttack, mmDaggerAttack, mmClubAttack, mmBlock, mmMiss, - mmNosferatAttack, mmLichQueenAttack, mmHumHit, mmHumDeath, mmGoblinHit, - mmGoblinDeath, mmSkeletonHit, mmSkeletonDeath, mmOrcHit, mmOrcDeath, - mmWolfHit, mmWolfDeath, mmWolfAttack, mmBearHit, mmBearDeath, mmBearAttack, - mmSpiderHit, mmSpiderDeath, mmSpiderAttack, mmGhostHit, mmGhostDeath, - mmGhostAttack, mmGhoulAttack, mmGhoulHit, mmGhoulDeath, mmHit, mmDeath, - mmAttack, mmGold, mmSpellbook, mmDismiss, mmPrepareMagic, mmDispell, mmHeal, - mmPlague, mmInvisibility, mmRevive, mmMana, mmSpeed, mmLearn, mmDrink, - mmUseOrb, mmImpHit, mmImpDeath, mmZombieHit, mmZombieDeath, mmZombieAttack, - mmLizardmanHit, mmLizardmanDeath, mmRaiseDead, mmRust, mmFlaskShatter, - mmExplosion, mmBoost, mmCriticalAttack); - var ResImage: array [TResEnum] of TPNGImage; CreatureResImage: array [TCreatureResEnum] of TPNGImage; SpellResImage: array [TSpellResEnum] of TPNGImage; ItemResImage: array [TItemResEnum] of TPNGImage; AbilityResImage: array [TAbilityResEnum] of TPNGImage; - ResMusicPath: array [TMusicEnum] of string; - -const - MusicBase: array [TMusicEnum] of TResBase = ( - // Click - (FileName: 'click.wav'; ResType: teSound;), - // Step - (FileName: 'step.wav'; ResType: teSound;), - // Win in battle - (FileName: 'himwar.wav'; ResType: teSound;), - // New Day - (FileName: 'day.ogg'; ResType: teSound;), - // Settlement - (FileName: 'settlement.wav'; ResType: teSound;), - // Loot - (FileName: 'loot.wav'; ResType: teSound;), - // New level - (FileName: 'level.wav'; ResType: teSound;), - // Round in battle - (FileName: 'war.wav'; ResType: teSound;), - // Exit - (FileName: 'exit.wav'; ResType: teSound;), - // Sword attack - (FileName: 'sword_attack.wav'; ResType: teSound;), - // Axe attack - (FileName: 'axe_attack.wav'; ResType: teSound;), - // Staff attack - (FileName: 'staff_attack.wav'; ResType: teSound;), - // Bow attack - (FileName: 'bow_attack.wav'; ResType: teSound;), - // Spear attack - (FileName: 'spear_attack.wav'; ResType: teSound;), - // Dagger attack - (FileName: 'dagger_attack.wav'; ResType: teSound;), - // Club attack - (FileName: 'club_attack.wav'; ResType: teSound;), - // Block - (FileName: 'block.wav'; ResType: teSound;), - // Miss - (FileName: 'miss.ogg'; ResType: teSound;), - // Nosferat Attack - (FileName: 'nosferat_attack.mp3'; ResType: teSound;), - // Lich Queen Attack - (FileName: 'lich_queen_attack.mp3'; ResType: teSound;), - // Humanoid Hit - (FileName: 'hum_hit.wav'; ResType: teSound;), - // Humanoid Death - (FileName: 'hum_death.ogg'; ResType: teSound;), - // Goblin Hit - (FileName: 'goblin_hit.wav'; ResType: teSound;), - // Goblin Death - (FileName: 'goblin_death.wav'; ResType: teSound;), - // Skeleton Hit - (FileName: 'skeleton_hit.wav'; ResType: teSound;), - // Skeleton Death - (FileName: 'skeleton_death.wav'; ResType: teSound;), - // Orc Hit - (FileName: 'orc_hit.ogg'; ResType: teSound;), - // Orc Death - (FileName: 'orc_death.ogg'; ResType: teSound;), - // Wolf Hit - (FileName: 'wolf_hit.wav'; ResType: teSound;), - // Wolf Death - (FileName: 'wolf_death.wav'; ResType: teSound;), - // Wolf Attack - (FileName: 'wolf_attack.wav'; ResType: teSound;), - // Bear Hit - (FileName: 'bear_hit.wav'; ResType: teSound;), - // Bear Death - (FileName: 'bear_death.wav'; ResType: teSound;), - // Bear Attack - (FileName: 'bear_attack.wav'; ResType: teSound;), - // Spider Hit - (FileName: 'spider_hit.wav'; ResType: teSound;), - // Spider Death - (FileName: 'spider_death.wav'; ResType: teSound;), - // Spider Attack - (FileName: 'spider_attack.wav'; ResType: teSound;), - // Ghost Hit - (FileName: 'spider_hit.wav'; ResType: teSound;), - // Ghost Death - (FileName: 'spider_death.wav'; ResType: teSound;), - // Ghost Attack - (FileName: 'spider_attack.wav'; ResType: teSound;), - // Ghoul Attack - (FileName: 'ghoul_attack.ogg'; ResType: teSound;), - // Ghoul Hit - (FileName: 'ghoul_hit.ogg'; ResType: teSound;), - // Ghoul Death - (FileName: 'ghoul_death.ogg'; ResType: teSound;), - // Hit - (FileName: 'step.wav'; ResType: teSound;), - // Death - (FileName: 'step.wav'; ResType: teSound;), - // Attack - (FileName: 'step.wav'; ResType: teSound;), - // Gold Coins - (FileName: 'coin.wav'; ResType: teSound;), - // Spellbook - (FileName: 'spellbook.mp3'; ResType: teSound;), - // Dismiss - (FileName: 'dismiss.wav'; ResType: teSound;), - // Prepare Magic - (FileName: 'prepare_magic.wav'; ResType: teSound;), - // Dispell - (FileName: 'dispell.wav'; ResType: teSound;), - // Heal - (FileName: 'heal.wav'; ResType: teSound;), - // Plague - (FileName: 'plague.wav'; ResType: teSound;), - // Invisibility - (FileName: 'invisibility.wav'; ResType: teSound;), - // Revive - (FileName: 'revive.wav'; ResType: teSound;), - // Mana - (FileName: 'mana.wav'; ResType: teSound;), - // Speed - (FileName: 'speed.wav'; ResType: teSound;), - // Learn - (FileName: 'learn.wav'; ResType: teSound;), - // Drink - (FileName: 'use_elixir.ogg'; ResType: teSound;), - // Use Orb or Talisman - (FileName: 'use_orb.ogg'; ResType: teSound;), - // Imp Hit - (FileName: 'imp_hit.ogg'; ResType: teSound;), - // Imp Death - (FileName: 'imp_death.wav'; ResType: teSound;), - // Zombie Hit - (FileName: 'zombie_hit.ogg'; ResType: teSound;), - // Zombie Death - (FileName: 'zombie_death.ogg'; ResType: teSound;), - // Zombie Attack - (FileName: 'zombie_attack.ogg'; ResType: teSound;), - // Lizardman Hit - (FileName: 'lizardman_hit.wav'; ResType: teSound;), - // Lizardman Death - (FileName: 'lizardman_death.wav'; ResType: teSound;), - // Raise Dead - (FileName: 'raise_dead.wav'; ResType: teSound;), - // Rust - (FileName: 'rust.wav'; ResType: teSound;), - // Flask Shatter - (FileName: 'flask_shatter.wav'; ResType: teSound;), - // Explosion - (FileName: 'explosion.wav'; ResType: teSound;), - // Boost - (FileName: 'boost.wav'; ResType: teSound;), - // Critical damage - (FileName: 'critical_attack.wav'; ResType: teSound;) - // - ); type TResources = class(TObject) @@ -1449,7 +1282,6 @@ class procedure TResources.ReadSections(const FileName: string; procedure Init; var LResEnum: TResEnum; - LMusicEnum: TMusicEnum; LPartyLevel: Integer; LCreatureResEnum: TCreatureResEnum; LItemResEnum: TItemResEnum; @@ -1463,17 +1295,6 @@ procedure Init; ResImage[LResEnum].LoadFromFile(TResources.GetPath('resources') + ResBase[LResEnum].FileName); end; - for LMusicEnum := Low(TMusicEnum) to High(TMusicEnum) do - begin - case MusicBase[LMusicEnum].ResType of - teSound: - ResMusicPath[LMusicEnum] := TResources.GetPath('resources\sounds') + - MusicBase[LMusicEnum].FileName; - teMusic: - ResMusicPath[LMusicEnum] := TResources.GetPath('resources\music') + - MusicBase[LMusicEnum].FileName; - end; - end; for LPartyLevel := 1 to 9 do TResources.LoadParties(Format('parties.level%d', [LPartyLevel])); for LSpellResEnum := Low(TSpellResEnum) to High(TSpellResEnum) do diff --git a/sources/Game/Elinor.Spells.Types.pas b/sources/Game/Elinor.Spells.Types.pas index 54e38d1..5206bc0 100644 --- a/sources/Game/Elinor.Spells.Types.pas +++ b/sources/Game/Elinor.Spells.Types.pas @@ -16,7 +16,7 @@ TSpellBase = record Level: Integer; Mana: Byte; RequireAbility: TAbilityEnum; - SoundEnum: TMusicEnum; + SoundEnum: string; ResEnum: TSpellResEnum; Faction: TFactionEnum; SpellTarget: TSpellTarget; diff --git a/sources/Game/Elinor.Spells.pas b/sources/Game/Elinor.Spells.pas index 9f7dc31..27269e3 100644 --- a/sources/Game/Elinor.Spells.pas +++ b/sources/Game/Elinor.Spells.pas @@ -217,77 +217,77 @@ implementation const SpellBase: TSpellBaseArray = ( // None - (Name: ''; Level: 0; Mana: 0; RequireAbility: abNone; SoundEnum: mmBlock; + (Name: ''; Level: 0; Mana: 0; RequireAbility: abNone; SoundEnum: 'block'; ResEnum: srNone; Faction: faNeutrals; SpellTarget: stNone; Description: '';), // The Empire // True Healing (Name: 'True Healing'; Level: 1; Mana: 15; RequireAbility: abNone; - SoundEnum: mmHeal; ResEnum: srTrueHealing; Faction: faTheEmpire; + SoundEnum: 'heal'; ResEnum: srTrueHealing; Faction: faTheEmpire; SpellTarget: stLeader; Description: 'Replenishes lost HP';), // Speed (Name: 'Speed'; Level: 1; Mana: 25; RequireAbility: abNone; - SoundEnum: mmHeal; ResEnum: srSpeed; Faction: faTheEmpire; + SoundEnum: 'heal'; ResEnum: srSpeed; Faction: faTheEmpire; SpellTarget: stLeader; Description: '';), // Bless (Name: 'Bless'; Level: 1; Mana: 5; RequireAbility: abNone; - SoundEnum: mmHeal; ResEnum: srBless; Faction: faTheEmpire; + SoundEnum: 'heal'; ResEnum: srBless; Faction: faTheEmpire; SpellTarget: stLeader; Description: '';), // Summon: Living Armor (Name: 'Summon: Living Armor'; Level: 1; Mana: 25; RequireAbility: abNone; - SoundEnum: mmAttack; ResEnum: srLivingArmor; Faction: faTheEmpire; + SoundEnum: 'attack'; ResEnum: srLivingArmor; Faction: faTheEmpire; SpellTarget: stEnemy; Description: 'Summons a Living Armor';), // Summon: Stone Golem (Name: 'Summon: Stone Golem'; Level: 1; Mana: 40; - RequireAbility: abGolemMastery; SoundEnum: mmRaiseDead; + RequireAbility: abGolemMastery; SoundEnum: 'raise_dead'; ResEnum: srStoneGolem; Faction: faTheEmpire; SpellTarget: stEnemy; Description: 'Summons a Stone Golem';), // Eagle Eye (Name: 'Eagle Eye'; Level: 1; Mana: 5; RequireAbility: abNone; - SoundEnum: mmHeal; ResEnum: srEagleEye; Faction: faTheEmpire; + SoundEnum: 'heal'; ResEnum: srEagleEye; Faction: faTheEmpire; SpellTarget: stLeader; Description: 'Allows the leader to see further';), // Strength (Name: 'Strength'; Level: 1; Mana: 5; RequireAbility: abNone; - SoundEnum: mmHeal; ResEnum: srStrength; Faction: faTheEmpire; + SoundEnum: 'heal'; ResEnum: srStrength; Faction: faTheEmpire; SpellTarget: stLeader; Description: 'Increases damage by 20%';), // Undead Hordes // Plague (Name: 'Plague'; Level: 1; Mana: 20; RequireAbility: abNone; - SoundEnum: mmPlague; ResEnum: srPlague; Faction: faUndeadHordes; + SoundEnum: 'plague'; ResEnum: srPlague; Faction: faUndeadHordes; SpellTarget: stEnemy; Description: '';), // Curse (Name: 'Curse'; Level: 1; Mana: 5; RequireAbility: abNone; - SoundEnum: mmPlague; ResEnum: srCurse; Faction: faUndeadHordes; + SoundEnum: 'plague'; ResEnum: srCurse; Faction: faUndeadHordes; SpellTarget: stEnemy; Description: '';), // Summon: Skeleton Warrior (Name: 'Summon: Skeleton Warrior'; Level: 1; Mana: 25; - RequireAbility: abNone; SoundEnum: mmRaiseDead; ResEnum: srSkeletion; + RequireAbility: abNone; SoundEnum: 'raise_dead'; ResEnum: srSkeletion; Faction: faUndeadHordes; SpellTarget: stEnemy; Description: 'Summons a Skeleton';), // Summon: Bone Golem (Name: 'Summon: Bone Golem'; Level: 1; Mana: 45; - RequireAbility: abGolemMastery; SoundEnum: mmRaiseDead; + RequireAbility: abGolemMastery; SoundEnum: 'raise_dead'; ResEnum: srBoneGolem; Faction: faUndeadHordes; SpellTarget: stEnemy; Description: 'Summons a Bone Golem';), // Legions of the Damned // Concealment (Name: 'Concealment'; Level: 1; Mana: 20; RequireAbility: abNone; - SoundEnum: mmInvisibility; ResEnum: srConcealment; + SoundEnum: 'invisibility'; ResEnum: srConcealment; Faction: faLegionsOfTheDamned; SpellTarget: stLeader; Description: '';), // Chains Of Dread (Name: 'Chains Of Dread'; Level: 1; Mana: 2; RequireAbility: abNone; - SoundEnum: mmInvisibility; ResEnum: srChainsOfDread; + SoundEnum: 'invisibility'; ResEnum: srChainsOfDread; Faction: faLegionsOfTheDamned; SpellTarget: stEnemy; Description: '';), // Weaken (Name: 'Weaken'; Level: 1; Mana: 2; RequireAbility: abNone; - SoundEnum: mmInvisibility; ResEnum: srWeaken; Faction: faLegionsOfTheDamned; + SoundEnum:'invisibility'; ResEnum: srWeaken; Faction: faLegionsOfTheDamned; SpellTarget: stEnemy; Description: '';), // Summon: Fire Golem (Name: 'Summon: Fire Golem'; Level: 1; Mana: 42; - RequireAbility: abGolemMastery; SoundEnum: mmRaiseDead; + RequireAbility: abGolemMastery; SoundEnum: 'raise_dead'; ResEnum: srFireGolem; Faction: faLegionsOfTheDamned; SpellTarget: stEnemy; Description: 'Summons a Fire Golem';) // @@ -349,7 +349,7 @@ procedure TSpell.PlaySpellEffects; procedure TActiveSpell.Clear; begin - Game.MediaPlayer.PlaySound(mmDispell); + Game.MediaPlayer.PlaySound('dispell'); FSpellEnum := spNone; end; @@ -415,7 +415,7 @@ procedure TSpells.Learn(const ASpellEnum: TSpellEnum); if not FLearned[ASpellEnum] then begin FLearned[ASpellEnum] := True; - Game.MediaPlayer.PlaySound(mmDispell); + Game.MediaPlayer.PlaySound('dispell'); end end; diff --git a/sources/Scenes/DisciplesRL.Scene.Hire.pas b/sources/Scenes/DisciplesRL.Scene.Hire.pas index e6ddd04..3b20955 100644 --- a/sources/Scenes/DisciplesRL.Scene.Hire.pas +++ b/sources/Scenes/DisciplesRL.Scene.Hire.pas @@ -139,7 +139,7 @@ class function TSceneHire.HireIndex: Integer; procedure TSceneHire.Back; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); case SubScene of stSpy, stWar: Game.Show(scMap); @@ -196,7 +196,7 @@ procedure TSceneHire.Ok; end; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); case SubScene of stSpy: begin diff --git a/sources/Scenes/Elinor.Scene.Abilities.pas b/sources/Scenes/Elinor.Scene.Abilities.pas index e356320..fe91fc7 100644 --- a/sources/Scenes/Elinor.Scene.Abilities.pas +++ b/sources/Scenes/Elinor.Scene.Abilities.pas @@ -77,8 +77,8 @@ destructor TSceneAbilities.Destroy; class procedure TSceneAbilities.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(CloseSceneEnum); end; @@ -172,7 +172,7 @@ procedure TSceneAbilities.Render; class procedure TSceneAbilities.ShowScene(const ACloseSceneEnum: TSceneEnum); begin CloseSceneEnum := ACloseSceneEnum; - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(scAbilities); ActivePartyPosition := TLeaderParty.GetPosition; end; diff --git a/sources/Scenes/Elinor.Scene.Barracks.pas b/sources/Scenes/Elinor.Scene.Barracks.pas index 19be93e..b65518d 100644 --- a/sources/Scenes/Elinor.Scene.Barracks.pas +++ b/sources/Scenes/Elinor.Scene.Barracks.pas @@ -72,13 +72,13 @@ class procedure TSceneBarracks.ShowScene(AParty: TParty); else ActivePartyPosition := AParty.GetRandomPosition; Game.Show(scBarracks); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; class procedure TSceneBarracks.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(scSettlement); end; @@ -140,7 +140,7 @@ procedure TSceneBarracks.ShowRecruitScene; end; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); RecruitIt(CurrentParty, ActivePartyPosition); end; @@ -178,7 +178,7 @@ procedure TSceneBarracks.MouseMove(Shift: TShiftState; X, Y: Integer); procedure TSceneBarracks.ShowPartyScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneParty2.ShowScene(CurrentParty, scBarracks); end; @@ -246,14 +246,14 @@ procedure TSceneBarracks.Dismiss; end; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); DismissIt(CurrentParty, ActivePartyPosition); end; procedure TSceneBarracks.DismissCreature; begin if ConfirmParty.Dismiss(ConfirmPartyPosition) then - Game.MediaPlayer.PlaySound(mmDismiss); + Game.MediaPlayer.PlaySound('dismiss'); end; procedure TSceneBarracks.Timer; diff --git a/sources/Scenes/Elinor.Scene.Base.Party.pas b/sources/Scenes/Elinor.Scene.Base.Party.pas index 02b2a13..29283df 100644 --- a/sources/Scenes/Elinor.Scene.Base.Party.pas +++ b/sources/Scenes/Elinor.Scene.Base.Party.pas @@ -53,7 +53,7 @@ procedure TSceneBaseParty.MoveCursor(const AArrowKeyDirectionEnum begin ActivePartyPosition := PositionTransitions[AArrowKeyDirectionEnum, ActivePartyPosition]; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Render; end; diff --git a/sources/Scenes/Elinor.Scene.Battle2.pas b/sources/Scenes/Elinor.Scene.Battle2.pas index 79243b5..4f753b2 100644 --- a/sources/Scenes/Elinor.Scene.Battle2.pas +++ b/sources/Scenes/Elinor.Scene.Battle2.pas @@ -230,7 +230,7 @@ procedure TSceneBattle2.ChCond; begin FBattle.BattleLog.WinInBattle; ChExperience; - Game.MediaPlayer.PlaySound(mmWinBattle); + Game.MediaPlayer.PlaySound('battle_win'); Game.MediaPlayer.PlayMusic('battle_win'); end; if LeaderParty.IsClear then @@ -389,7 +389,7 @@ procedure TSceneBattle2.StartBattle; ActivePartyPosition := PartyList.Party[TLeaderParty.LeaderPartyIndex] .GetRandomPosition; CurrentPartyPosition := ActivePartyPosition; - Game.MediaPlayer.PlaySound(mmWar); + Game.MediaPlayer.PlaySound('battle_round'); StartRound; except on E: Exception do @@ -440,7 +440,7 @@ procedure TSceneBattle2.Turn(const ATurnType: TTurnType; begin FBattle.BattleLog.Miss(AAtkParty.Creature[AAtkPos].Name[0], ADefParty.Creature[ADefPos].Name[1]); - Game.MediaPlayer.PlaySound(mmMiss); + Game.MediaPlayer.PlaySound('miss'); Sleep(200); NextTurn; Exit; @@ -604,7 +604,7 @@ procedure TSceneBattle2.Heal(AParty: TParty; AAtkPos, ADefPos: TPosition); if Alive and (HitPoints.GetCurrValue < HitPoints.GetMaxValue) then begin - Game.MediaPlayer.PlaySound(mmHeal); + Game.MediaPlayer.PlaySound('heal'); AParty.Heal(LPosition, AParty.Creature[AAtkPos].Heal); FBattle.BattleLog.Heal(AParty.Creature[AAtkPos].Name[0], AParty.Creature[LPosition].Name[1], @@ -631,7 +631,7 @@ procedure TSceneBattle2.Heal(AParty: TParty; AAtkPos, ADefPos: TPosition); procedure TSceneBattle2.HideBattleLog; begin FIsShowBattleLog := False; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; class procedure TSceneBattle2.HideScene; @@ -1044,7 +1044,7 @@ procedure TSceneBattle2.Show(const ASceneEnum: TSceneEnum); procedure TSceneBattle2.ShowBattleLog; begin FIsShowBattleLog := True; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; class procedure TSceneBattle2.ShowScene; @@ -1154,7 +1154,7 @@ procedure TSceneBattle2.UseLHandItem; case LItem.Enum of iTalismanOfRestoration: begin - Game.MediaPlayer.PlaySound(mmHeal); + Game.MediaPlayer.PlaySound('heal'); LeaderParty.Heal(LLeaderPosition, 55); FBattle.BattleLog.Log.Add (LStr + ' The Talisman heals the Leader.'); @@ -1164,7 +1164,7 @@ procedure TSceneBattle2.UseLHandItem; end; iTalismanOfVigor: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); LDamage := LeaderParty.Creature[LLeaderPosition] .Damage.GetFullValue; LDamage := EnsureRange(LDamage div 4, 1, 75); @@ -1177,7 +1177,7 @@ procedure TSceneBattle2.UseLHandItem; end; iTalismanOfProtection: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); LArmor := LeaderParty.Creature[LLeaderPosition] .Armor.GetFullValue; LArmor := EnsureRange(LArmor div 10, 1, 100); @@ -1190,7 +1190,7 @@ procedure TSceneBattle2.UseLHandItem; end; iTalismanOfCelerity: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); LInitiative := LeaderParty.Creature[LLeaderPosition] .Initiative.GetFullValue; LInitiative := EnsureRange(LInitiative div 5, 1, 80); @@ -1204,14 +1204,14 @@ procedure TSceneBattle2.UseLHandItem; iTalismanOfNosferat, iTalismanOfFear, iOrbOfWitches, iAcidFlask, iFlaskOfOil: begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneSelectUnit.ShowScene(EnemyParty); Exit; end; iTalismanOfRage, iGoblinOrb, iOrbOfHealing, iImpOrb, iSkeletonOrb, iOrbOfRestoration, iZombieOrb, iOrbOfLife, iLizardmanOrb: begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneSelectUnit.ShowScene(LeaderParty); Exit; end; diff --git a/sources/Scenes/Elinor.Scene.Battle3.pas b/sources/Scenes/Elinor.Scene.Battle3.pas index a266092..6a67c4d 100644 --- a/sources/Scenes/Elinor.Scene.Battle3.pas +++ b/sources/Scenes/Elinor.Scene.Battle3.pas @@ -41,7 +41,7 @@ implementation procedure TSceneBattle3.Start; begin - Game.MediaPlayer.PlaySound(mmWar); + Game.MediaPlayer.PlaySound('battle_round'); end; procedure TSceneBattle3.Finish; diff --git a/sources/Scenes/Elinor.Scene.Defeat.pas b/sources/Scenes/Elinor.Scene.Defeat.pas index 3e6041f..85a5439 100644 --- a/sources/Scenes/Elinor.Scene.Defeat.pas +++ b/sources/Scenes/Elinor.Scene.Defeat.pas @@ -56,7 +56,7 @@ class procedure TSceneDefeat.ShowScene; class procedure TSceneDefeat.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.MediaPlayer.PlayMusic('menu'); Game.IsGame := False; Game.LeaderRecordsTable.AddRecord(TCreature.GetName, diff --git a/sources/Scenes/Elinor.Scene.Difficulty.pas b/sources/Scenes/Elinor.Scene.Difficulty.pas index 1d36452..b0b1832 100644 --- a/sources/Scenes/Elinor.Scene.Difficulty.pas +++ b/sources/Scenes/Elinor.Scene.Difficulty.pas @@ -110,7 +110,7 @@ procedure TSceneDifficulty.Render; class procedure TSceneDifficulty.Show; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scDifficulty); end; diff --git a/sources/Scenes/Elinor.Scene.Faction.pas b/sources/Scenes/Elinor.Scene.Faction.pas index 6b31306..be5b63a 100644 --- a/sources/Scenes/Elinor.Scene.Faction.pas +++ b/sources/Scenes/Elinor.Scene.Faction.pas @@ -91,7 +91,7 @@ procedure TSceneRace.Render; class procedure TSceneRace.ShowScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scRace); end; diff --git a/sources/Scenes/Elinor.Scene.Inventory.pas b/sources/Scenes/Elinor.Scene.Inventory.pas index 87d83ed..672c45f 100644 --- a/sources/Scenes/Elinor.Scene.Inventory.pas +++ b/sources/Scenes/Elinor.Scene.Inventory.pas @@ -106,13 +106,13 @@ class procedure TSceneInventory.ShowScene(AParty: TParty; ActivePartyPosition := AParty.GetRandomPosition; ActiveSection := isParty; Game.Show(scInventory); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; class procedure TSceneInventory.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(CloseSceneEnum); end; diff --git a/sources/Scenes/Elinor.Scene.Leader.pas b/sources/Scenes/Elinor.Scene.Leader.pas index 5f39fe8..408e860 100644 --- a/sources/Scenes/Elinor.Scene.Leader.pas +++ b/sources/Scenes/Elinor.Scene.Leader.pas @@ -55,7 +55,7 @@ procedure TSceneLeader.Continue; inherited; if CurrentIndex > 4 then Exit; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneHire.CurCrAbilityEnum := TCreature.Character(CurCrEnum).AbilityEnum; Game.Clear; PartyList.Party[TLeaderParty.LeaderPartyIndex].Owner := Game.Scenario.Faction; @@ -129,7 +129,7 @@ procedure TSceneLeader.Render; class procedure TSceneLeader.Show; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scLeader); end; diff --git a/sources/Scenes/Elinor.Scene.Loot2.pas b/sources/Scenes/Elinor.Scene.Loot2.pas index dd8d5aa..c9f79b0 100644 --- a/sources/Scenes/Elinor.Scene.Loot2.pas +++ b/sources/Scenes/Elinor.Scene.Loot2.pas @@ -99,19 +99,19 @@ procedure TSceneLoot2.PickupItem; case LLootItem.LootType of ltGold: begin - Game.MediaPlayer.PlaySound(mmGold); + Game.MediaPlayer.PlaySound('gold'); Game.Gold.Modify(LLootItem.Amount); Loot.Clear(LItemIndex); end; ltMana: begin - Game.MediaPlayer.PlaySound(mmMana); + Game.MediaPlayer.PlaySound('mana'); Game.Mana.Modify(LLootItem.Amount); Loot.Clear(LItemIndex); end; ltStoneTab: begin - Game.MediaPlayer.PlaySound(mmLoot); + Game.MediaPlayer.PlaySound('loot'); Inc(Game.Scenario.StoneTab); Loot.Clear(LItemIndex); InformDialog(Game.Scenario.ScenarioAncientKnowledgeState); @@ -123,7 +123,7 @@ procedure TSceneLoot2.PickupItem; InformDialog(CNoFreeSpace); Exit; end; - Game.MediaPlayer.PlaySound(mmLoot); + Game.MediaPlayer.PlaySound('loot'); TLeaderParty.Leader.Inventory.Add(LLootItem.ItemEnum); Game.Statistics.IncValue(stItemsFound); Loot.Clear(LItemIndex); @@ -155,8 +155,8 @@ class procedure TSceneLoot2.HideScene; Exit; end; Game.Show(scMap); - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmLoot); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('loot'); end; constructor TSceneLoot2.Create; @@ -333,7 +333,7 @@ procedure TSceneLoot2.Render; class procedure TSceneLoot2.ShowScene; begin ActiveSection := lsLoot; - Game.MediaPlayer.PlaySound(mmLoot); + Game.MediaPlayer.PlaySound('loot'); Game.Show(scLoot); end; diff --git a/sources/Scenes/Elinor.Scene.MageTower.pas b/sources/Scenes/Elinor.Scene.MageTower.pas index 1884985..87a828a 100644 --- a/sources/Scenes/Elinor.Scene.MageTower.pas +++ b/sources/Scenes/Elinor.Scene.MageTower.pas @@ -77,17 +77,17 @@ procedure TSceneMageTower.TryLearnSpell; LGold := 0; if LGold > Game.Gold.Value then begin - Game.MediaPlayer.PlaySound(mmSpellbook); + Game.MediaPlayer.PlaySound('spellbook'); InformDialog(CNotEnoughGoldToLearn); Exit; end; if LMana > Game.Mana.Value then begin - Game.MediaPlayer.PlaySound(mmSpellbook); + Game.MediaPlayer.PlaySound('spellbook'); InformDialog(CNotEnoughManaToLearn); Exit; end; - Game.MediaPlayer.PlaySound(mmLearn); + Game.MediaPlayer.PlaySound('learn'); Game.Gold.Modify(-LGold); Game.Mana.Modify(-LMana); Spells.Learn(LSpellEnum); @@ -99,7 +99,7 @@ class procedure TSceneMageTower.HideScene; begin Game.MediaPlayer.PlayMusic('map'); Game.Show(scMap); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; constructor TSceneMageTower.Create; @@ -232,7 +232,7 @@ procedure TSceneMageTower.Render; class procedure TSceneMageTower.ShowScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scMageTower); end; diff --git a/sources/Scenes/Elinor.Scene.Map.pas b/sources/Scenes/Elinor.Scene.Map.pas index 684a23d..dcd9b48 100644 --- a/sources/Scenes/Elinor.Scene.Map.pas +++ b/sources/Scenes/Elinor.Scene.Map.pas @@ -75,8 +75,8 @@ procedure TSceneMap.Escape; Exit; end; Game.MediaPlayer.PlayMusic('menu'); - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); TSceneMenu3(Game.GetScene(scMenu)).CurrentIndex := 1; Game.Show(scMenu); end; @@ -311,7 +311,7 @@ procedure TSceneMap.Render; procedure TSceneMap.Show(const S: TSceneEnum); begin inherited Show(S); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; procedure TSceneMap.Timer; diff --git a/sources/Scenes/Elinor.Scene.Menu.Simple.pas b/sources/Scenes/Elinor.Scene.Menu.Simple.pas index dfc7264..ce33022 100644 --- a/sources/Scenes/Elinor.Scene.Menu.Simple.pas +++ b/sources/Scenes/Elinor.Scene.Menu.Simple.pas @@ -126,7 +126,7 @@ procedure TSceneSimpleMenu.MouseDown(AButton: TMouseButton; Shift: TShiftState; if MouseOver(TFrame.Col(1), TFrame.Row(I), X, Y) and not IsBlockFrames then begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); CurrentIndex := I; Break; end; @@ -191,7 +191,7 @@ procedure TSceneSimpleMenu.UpdateEnum(AKey: Word); Basic(AKey); if not(AKey in [K_UP, K_Down]) then Exit; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); LCycler := TEnumCycler.Create(CurrentIndex); CurrentIndex := LCycler.Modify(AKey = K_Down); end; diff --git a/sources/Scenes/Elinor.Scene.Menu.Wide.pas b/sources/Scenes/Elinor.Scene.Menu.Wide.pas index c904cf4..e8fa7d7 100644 --- a/sources/Scenes/Elinor.Scene.Menu.Wide.pas +++ b/sources/Scenes/Elinor.Scene.Menu.Wide.pas @@ -63,7 +63,7 @@ procedure TSceneWideMenu.MoveCursor(const AArrowKeyDirectionEnum : TArrowKeyDirectionEnum); begin CurrentIndex := PositionTransitions[AArrowKeyDirectionEnum, CurrentIndex]; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Render; end; @@ -146,7 +146,7 @@ procedure TSceneWideMenu.MouseDown(AButton: TMouseButton; Shift: TShiftState; if not IsBlockFrames then begin CurrentIndex := LPartyPosition; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Exit; end; end; diff --git a/sources/Scenes/Elinor.Scene.Menu3.pas b/sources/Scenes/Elinor.Scene.Menu3.pas index 5182124..b025a19 100644 --- a/sources/Scenes/Elinor.Scene.Menu3.pas +++ b/sources/Scenes/Elinor.Scene.Menu3.pas @@ -174,7 +174,7 @@ procedure TSceneMenu3.MouseDown(AButton: TMouseButton; Shift: TShiftState; 0 .. 5: begin CurrentIndex := LPartyPosition; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Exit; end; end; diff --git a/sources/Scenes/Elinor.Scene.Merchant.pas b/sources/Scenes/Elinor.Scene.Merchant.pas index bf13c0e..dc6a923 100644 --- a/sources/Scenes/Elinor.Scene.Merchant.pas +++ b/sources/Scenes/Elinor.Scene.Merchant.pas @@ -79,13 +79,13 @@ class procedure TSceneMerchant.ShowScene(AParty: TParty; ActiveSection := isMerchant; GetMerchantItemPrice; Game.Show(scMerchant); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; class procedure TSceneMerchant.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(CloseSceneEnum); end; @@ -113,7 +113,7 @@ procedure TSceneMerchant.BuyItem; TLeaderParty.Leader.Inventory.Add(LItem); Merchants.GetMerchant(CurrentMerchantType) .Inventory.Clear(MerchantSelItemIndex); - Game.MediaPlayer.PlaySound(mmGold); + Game.MediaPlayer.PlaySound('gold'); Render; end; @@ -134,7 +134,7 @@ procedure TSceneMerchant.SellItem; Game.Gold.Modify(LPrice); Merchants.GetMerchant(CurrentMerchantType).ModifyGold(-LPrice); TLeaderParty.Leader.Inventory.Clear(InventorySelItemIndex); - Game.MediaPlayer.PlaySound(mmGold); + Game.MediaPlayer.PlaySound('gold'); Render; end; diff --git a/sources/Scenes/Elinor.Scene.Name.pas b/sources/Scenes/Elinor.Scene.Name.pas index 816bb67..def6ced 100644 --- a/sources/Scenes/Elinor.Scene.Name.pas +++ b/sources/Scenes/Elinor.Scene.Name.pas @@ -228,7 +228,7 @@ procedure TSceneName.GenerateRandomName; FNewName := GetRandomNameForFaction(AllFactionNames, GetLeaderFaction, GetLeaderGender); CursorPosition := Length(FNewName); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; function TSceneName.GetLeaderFaction: TFactionEnum; @@ -244,15 +244,15 @@ function TSceneName.GetLeaderGender: TCreatureGender; class procedure TSceneName.ShowScene; begin TSceneName(Game.GetScene(scName)).GenerateRandomName; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scName); end; class procedure TSceneName.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.MediaPlayer.PlayMusic('game'); - Game.MediaPlayer.PlaySound(mmExit); + Game.MediaPlayer.PlaySound('exit'); TSceneSettlement.ShowScene(stCapital); end; diff --git a/sources/Scenes/Elinor.Scene.NewAbility.pas b/sources/Scenes/Elinor.Scene.NewAbility.pas index 7774824..0829afd 100644 --- a/sources/Scenes/Elinor.Scene.NewAbility.pas +++ b/sources/Scenes/Elinor.Scene.NewAbility.pas @@ -78,7 +78,7 @@ destructor TSceneNewAbility.Destroy; class procedure TSceneNewAbility.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneBattle2.AfterVictory; end; @@ -193,7 +193,7 @@ procedure TSceneNewAbility.Render; class procedure TSceneNewAbility.ShowScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scNewAbility); end; diff --git a/sources/Scenes/Elinor.Scene.Party2.pas b/sources/Scenes/Elinor.Scene.Party2.pas index 4f761f1..af457c8 100644 --- a/sources/Scenes/Elinor.Scene.Party2.pas +++ b/sources/Scenes/Elinor.Scene.Party2.pas @@ -71,7 +71,7 @@ class procedure TSceneParty2.Show(Party: TParty; CloseScene: TSceneEnum); BackScene := CloseScene; ActivePartyPosition := Party.GetRandomPosition; Game.Show(scParty); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; procedure TSceneParty2.ShowAbilitiesScene; @@ -224,7 +224,7 @@ class procedure TSceneParty2.ShowScene(AParty: TParty; else ActivePartyPosition := AParty.GetRandomPosition; Game.Show(scParty); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; procedure TSceneParty2.ShowSpellbookScene; @@ -235,8 +235,8 @@ procedure TSceneParty2.ShowSpellbookScene; class procedure TSceneParty2.HideScene; begin Game.Show(CloseScene); - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); end; procedure TSceneParty2.Timer; diff --git a/sources/Scenes/Elinor.Scene.Records.pas b/sources/Scenes/Elinor.Scene.Records.pas index 8cd01e8..d5fbb36 100644 --- a/sources/Scenes/Elinor.Scene.Records.pas +++ b/sources/Scenes/Elinor.Scene.Records.pas @@ -59,7 +59,7 @@ procedure TSceneRecords.MoveCursor(const AArrowKeyDirectionEnum : TArrowKeyDirectionEnum); begin CurrentIndex := PositionTransitions[AArrowKeyDirectionEnum, CurrentIndex]; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Render; end; @@ -104,7 +104,7 @@ procedure TSceneRecords.FilterByFaction; class procedure TSceneRecords.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scMenu); end; @@ -122,7 +122,7 @@ procedure TSceneRecords.MouseDown(AButton: TMouseButton; Shift: TShiftState; 0 .. 5: begin CurrentIndex := LPartyPosition; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Exit; end; end; @@ -270,7 +270,7 @@ procedure TSceneRecords.Render; class procedure TSceneRecords.ShowScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scRecords); end; diff --git a/sources/Scenes/Elinor.Scene.Recruit.pas b/sources/Scenes/Elinor.Scene.Recruit.pas index 126e9b8..5f61ea7 100644 --- a/sources/Scenes/Elinor.Scene.Recruit.pas +++ b/sources/Scenes/Elinor.Scene.Recruit.pas @@ -79,8 +79,8 @@ destructor TSceneRecruit.Destroy; class procedure TSceneRecruit.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(scBarracks); end; @@ -94,7 +94,7 @@ procedure TSceneRecruit.Recruit; Exit; if HireParty.Hire(LCreatureEnum, HirePosition) then begin - Game.MediaPlayer.PlaySound(mmGold); + Game.MediaPlayer.PlaySound('gold'); Game.Show(scBarracks); end else diff --git a/sources/Scenes/Elinor.Scene.Scenario.pas b/sources/Scenes/Elinor.Scene.Scenario.pas index 24b63ab..607eec6 100644 --- a/sources/Scenes/Elinor.Scene.Scenario.pas +++ b/sources/Scenes/Elinor.Scene.Scenario.pas @@ -125,7 +125,7 @@ procedure TSceneScenario.Render; class procedure TSceneScenario.Show; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Show(scScenario); end; diff --git a/sources/Scenes/Elinor.Scene.SelectUnit.pas b/sources/Scenes/Elinor.Scene.SelectUnit.pas index 73303ad..fdee8f6 100644 --- a/sources/Scenes/Elinor.Scene.SelectUnit.pas +++ b/sources/Scenes/Elinor.Scene.SelectUnit.pas @@ -67,7 +67,7 @@ class procedure TSceneSelectUnit.ShowScene(AParty: TParty); class procedure TSceneSelectUnit.HideScene; begin ActivePartyPosition := LastActivePartyPosition; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.BackToScene(scBattle); end; @@ -200,7 +200,7 @@ procedure TSceneSelectUnit.SelectUnit; case LItem.Enum of iTalismanOfNosferat: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); CurrentParty.TakeDamage(25, ActivePartyPosition); TLeaderParty.Leader.UpdateHP(25, TLeaderParty.GetPosition); PendingItemLogString := Format(CYouUsedTheItem, @@ -209,7 +209,7 @@ procedure TSceneSelectUnit.SelectUnit; end; iTalismanOfFear: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); CurrentParty.Paralyze(ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + Format(' Paralyzes the %s.', @@ -217,40 +217,40 @@ procedure TSceneSelectUnit.SelectUnit; end; iTalismanOfRage: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + ' Gives an extra attack!'; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneBattle2(Game.GetScene(scBattle)).ContinueBattle(False); Game.BackToScene(scBattle); Exit; end; iOrbOfHealing: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); CurrentParty.UpdateHP(50, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + ' Healed for 50 hp.'; end; iOrbOfRestoration: begin - Game.MediaPlayer.PlaySound(mmUseOrb); + Game.MediaPlayer.PlaySound('use_orb'); CurrentParty.UpdateHP(100, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + ' Healed for 100 hp.'; end; iOrbOfLife: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmRevive); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('revive'); CurrentParty.Revive(ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + ' You resurrected the creature.'; end; iGoblinOrb: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmGoblinHit); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('goblin_hit'); CurrentParty.AddCreature(crGoblin, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + @@ -258,8 +258,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iImpOrb: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmImpHit); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('imp_hit'); CurrentParty.AddCreature(crImp, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + @@ -267,8 +267,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iSkeletonOrb: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmRaiseDead); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('raise_dead'); CurrentParty.AddCreature(crSkeletonWarrior, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + @@ -276,8 +276,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iZombieOrb: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmZombieHit); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('zombie_hit'); CurrentParty.AddCreature(crZombie, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + @@ -285,8 +285,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iLizardmanOrb: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmLizardmanHit); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('lizardman_hit'); CurrentParty.AddCreature(crLizardman, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, [TItemBase.Item(LItem.Enum).Name]) + @@ -294,8 +294,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iOrbOfWitches: begin - Game.MediaPlayer.PlaySound(mmUseOrb); - Game.MediaPlayer.PlaySound(mmImpHit); + Game.MediaPlayer.PlaySound('use_orb'); + Game.MediaPlayer.PlaySound('imp_hit'); CurrentParty.Dismiss(ActivePartyPosition); CurrentParty.AddCreature(crImp, ActivePartyPosition); PendingItemLogString := Format(CYouUsedTheItem, @@ -304,8 +304,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iAcidFlask: begin - Game.MediaPlayer.PlaySound(mmFlaskShatter); - Game.MediaPlayer.PlaySound(mmRust); + Game.MediaPlayer.PlaySound('flask_shatter'); + Game.MediaPlayer.PlaySound('rust'); CurrentParty.ReduceArmor(50, ActivePartyPosition); PendingItemLogString := Format(CYouThrewTheItem, [TItemBase.Item(LItem.Enum).Name]) + @@ -313,8 +313,8 @@ procedure TSceneSelectUnit.SelectUnit; end; iFlaskOfOil: begin - Game.MediaPlayer.PlaySound(mmFlaskShatter); - Game.MediaPlayer.PlaySound(mmExplosion); + Game.MediaPlayer.PlaySound('flask_shatter'); + Game.MediaPlayer.PlaySound('explosion'); CurrentParty.Explosion(25, ActivePartyPosition); LLogStr := ''; with TCreature.Character(CurrentParty.Creature @@ -338,7 +338,7 @@ procedure TSceneSelectUnit.SelectUnit; end; end; ActivePartyPosition := LastActivePartyPosition; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneBattle2(Game.GetScene(scBattle)).ContinueBattle(True); Game.BackToScene(scBattle); end; diff --git a/sources/Scenes/Elinor.Scene.Settlement.pas b/sources/Scenes/Elinor.Scene.Settlement.pas index eb527a6..4289c94 100644 --- a/sources/Scenes/Elinor.Scene.Settlement.pas +++ b/sources/Scenes/Elinor.Scene.Settlement.pas @@ -86,7 +86,7 @@ procedure TSceneSettlement.MoveCursor(const AArrowKeyDirectionEnum begin ActivePartyPosition := PositionTransitions[AArrowKeyDirectionEnum, ActivePartyPosition]; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.Render; end; @@ -110,7 +110,7 @@ class procedure TSceneSettlement.HideScene; end; Game.MediaPlayer.PlayMusic('map'); Game.Show(scMap); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.NewDay; end; @@ -185,7 +185,7 @@ procedure TSceneSettlement.MouseDown(AButton: TMouseButton; Shift: TShiftState; ActivePartyPosition := CurrentPartyPosition; end; end; - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; end; end; @@ -269,13 +269,13 @@ procedure TSceneSettlement.ShowTempleScene; 0 .. 5: begin TSceneTemple.ShowScene(TLeaderParty.Leader); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end else if not SettlementParty.IsClear then begin TSceneTemple.ShowScene(SettlementParty); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; end; end; @@ -286,13 +286,13 @@ procedure TSceneSettlement.ShowBarracksScene; 0 .. 5: begin TSceneBarracks.ShowScene(TLeaderParty.Leader); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end else if not SettlementParty.IsClear then begin TSceneBarracks.ShowScene(SettlementParty); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; end; @@ -305,13 +305,13 @@ procedure TSceneSettlement.ShowPartyScene; begin TSceneParty2.ShowScene(PartyList.Party[TLeaderParty.LeaderPartyIndex], scSettlement); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end else if not SettlementParty.IsClear then begin TSceneParty2.ShowScene(SettlementParty, scSettlement); - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); end; end; end; diff --git a/sources/Scenes/Elinor.Scene.Spellbook.pas b/sources/Scenes/Elinor.Scene.Spellbook.pas index 461cdd5..5171be9 100644 --- a/sources/Scenes/Elinor.Scene.Spellbook.pas +++ b/sources/Scenes/Elinor.Scene.Spellbook.pas @@ -71,8 +71,8 @@ procedure TSceneSpellbook.CastSpell; end; Spells.ActiveSpell.SetActiveSpell(LSpellEnum); Game.Mana.Modify(-LMana); - Game.MediaPlayer.PlaySound(mmSpellbook); - Game.MediaPlayer.PlaySound(mmPrepareMagic); + Game.MediaPlayer.PlaySound('spellbook'); + Game.MediaPlayer.PlaySound('prepare_magic'); Game.Show(scMap); end; end; @@ -80,8 +80,8 @@ procedure TSceneSpellbook.CastSpell; class procedure TSceneSpellbook.HideScene; begin Game.Show(CloseSceneEnum); - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSpellbook); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('spellbook'); end; constructor TSceneSpellbook.Create; @@ -210,7 +210,7 @@ procedure TSceneSpellbook.Render; class procedure TSceneSpellbook.ShowScene(const ACloseSceneEnum: TSceneEnum); begin CloseSceneEnum := ACloseSceneEnum; - Game.MediaPlayer.PlaySound(mmSpellbook); + Game.MediaPlayer.PlaySound('spellbook'); Game.Show(scSpellbook); end; diff --git a/sources/Scenes/Elinor.Scene.Temple.pas b/sources/Scenes/Elinor.Scene.Temple.pas index 90e131b..723ea32 100644 --- a/sources/Scenes/Elinor.Scene.Temple.pas +++ b/sources/Scenes/Elinor.Scene.Temple.pas @@ -72,13 +72,13 @@ class procedure TSceneTemple.ShowScene(AParty: TParty); else ActivePartyPosition := AParty.GetRandomPosition; Game.Show(scTemple); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('settlement'); end; class procedure TSceneTemple.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); - Game.MediaPlayer.PlaySound(mmSettlement); + Game.MediaPlayer.PlaySound('click'); + Game.MediaPlayer.PlaySound('settlement'); Game.Show(scSettlement); end; @@ -144,7 +144,7 @@ procedure TSceneTemple.Heal; end; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); HealIt(CurrentParty, ActivePartyPosition); end; @@ -152,7 +152,7 @@ procedure TSceneTemple.HealCreature; begin Game.Gold.Modify(-ConfirmGold); ConfirmParty.Heal(ConfirmPartyPosition); - Game.MediaPlayer.PlaySound(mmHeal); + Game.MediaPlayer.PlaySound('heal'); end; procedure TSceneTemple.MouseDown(AButton: TMouseButton; Shift: TShiftState; @@ -189,7 +189,7 @@ procedure TSceneTemple.MouseMove(Shift: TShiftState; X, Y: Integer); procedure TSceneTemple.ShowPartyScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); TSceneParty2.ShowScene(CurrentParty, scTemple); end; @@ -265,7 +265,7 @@ procedure TSceneTemple.Revive; end; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); ReviveIt(CurrentParty, ActivePartyPosition); end; @@ -273,7 +273,7 @@ procedure TSceneTemple.ReviveCreature; begin Game.Gold.Modify(-ConfirmGold); ConfirmParty.Revive(ConfirmPartyPosition); - Game.MediaPlayer.PlaySound(mmRevive); + Game.MediaPlayer.PlaySound('revive'); end; procedure TSceneTemple.Timer; diff --git a/sources/Scenes/Elinor.Scene.Victory.pas b/sources/Scenes/Elinor.Scene.Victory.pas index a89419a..e3129d3 100644 --- a/sources/Scenes/Elinor.Scene.Victory.pas +++ b/sources/Scenes/Elinor.Scene.Victory.pas @@ -57,7 +57,7 @@ class procedure TSceneVictory.ShowScene; class procedure TSceneVictory.HideScene; begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.MediaPlayer.PlayMusic('menu'); Game.IsGame := False; Game.LeaderRecordsTable.AddRecord diff --git a/sources/Scenes/Elinor.Scenes.pas b/sources/Scenes/Elinor.Scenes.pas index a030501..0bd4810 100644 --- a/sources/Scenes/Elinor.Scenes.pas +++ b/sources/Scenes/Elinor.Scenes.pas @@ -405,7 +405,7 @@ procedure TGame.NewDay; ShowNewDayMessageTime := 20; if (RandomRange(0, 100) <= 5) then Merchants.Clear; - MediaPlayer.PlaySound(mmDay); + MediaPlayer.PlaySound('new_day'); IsNewDay := False; if (Game.Day > TScenario.GetDayLimit(Difficulty.Level, Game.Scenario.CurrentScenario, True)) then @@ -534,7 +534,7 @@ procedure TScene.AddTextLine(const AMessage: string; const V, M: Integer); procedure TScene.ConfirmDialog(const AMessage: string; OnYes: TConfirmMethod); begin - Game.MediaPlayer.PlaySound(mmExit); + Game.MediaPlayer.PlaySound('exit'); Game.InformMsg := AMessage; Game.IsShowConfirm := True; ConfirmHandler := OnYes; @@ -542,14 +542,14 @@ procedure TScene.ConfirmDialog(const AMessage: string; OnYes: TConfirmMethod); procedure TScene.InformDialog(const AMessage: string); begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.InformMsg := AMessage; Game.IsShowInform := idtMessage; end; procedure TScene.ItemInformDialog(const AItemEnum: TItemEnum); begin - Game.MediaPlayer.PlaySound(mmClick); + Game.MediaPlayer.PlaySound('click'); Game.InformSL.Clear; Game.InformImage := reNone; Game.InformItemImage := TItemBase.Item(AItemEnum).ItRes; From 77bfe8a9e99848c9b5ef8d9c0d63a3fa50809cca Mon Sep 17 00:00:00 2001 From: devapromix Date: Tue, 14 Jul 2026 23:26:34 +0300 Subject: [PATCH 7/7] refact --- sources/Game/Elinor.NewResources.pas | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/sources/Game/Elinor.NewResources.pas b/sources/Game/Elinor.NewResources.pas index 69fc6c9..e986616 100644 --- a/sources/Game/Elinor.NewResources.pas +++ b/sources/Game/Elinor.NewResources.pas @@ -299,15 +299,15 @@ function TPNGImageLoader.GetKeys(const prefix: string = ''): TArray; FindClose(LSearchRec); Result := LFiles.ToArray; finally - LFiles.Free; + FreeAndNil(LFiles); end; end; constructor TResourceSchema.Create; var basePath, jsonPath, jsonText: string; - png: TPNGImageLoader; - cache: TCachedResourceLoader; + LPNG: TPNGImageLoader; + LCache: TCachedResourceLoader; begin basePath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)) + 'resources'); @@ -327,22 +327,22 @@ constructor TResourceSchema.Create; FSounds := TValuePathResourceLoader.Create (TJsonResourceLoader.Create(FJsonRoot, 'sounds'), basePath + 'sounds\'); - png := TPNGImageLoader.Create; + LPNG := TPNGImageLoader.Create; - cache := TCachedResourceLoader.Create - (TPrefixedResourceLoader.Create(png, basePath + 'characters\')); - FCharacters := cache; - FCharactersCache := cache; + LCache := TCachedResourceLoader.Create + (TPrefixedResourceLoader.Create(LPNG, basePath + 'characters\')); + FCharacters := LCache; + FCharactersCache := LCache; - cache := TCachedResourceLoader.Create - (TPrefixedResourceLoader.Create(png, basePath + 'items\')); - FItems := cache; - FItemsCache := cache; + LCache := TCachedResourceLoader.Create + (TPrefixedResourceLoader.Create(LPNG, basePath + 'items\')); + FItems := LCache; + FItemsCache := LCache; - cache := TCachedResourceLoader.Create - (TPrefixedResourceLoader.Create(png, basePath + 'spells\')); - FSpells := cache; - FSpellsCache := cache; + LCache := TCachedResourceLoader.Create + (TPrefixedResourceLoader.Create(LPNG, basePath + 'spells\')); + FSpells := LCache; + FSpellsCache := LCache; end; destructor TResourceSchema.Destroy; @@ -357,7 +357,7 @@ procedure TResourceSchema.LoadAll; begin FCharactersCache.LoadAll; FItemsCache.LoadAll; - //FSpellsCache.LoadAll; + FSpellsCache.LoadAll; end; initialization