1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Merge pull request #4275 from IvanSavenko/music_modding

Additional options for music modding
This commit is contained in:
Ivan Savenko
2024-07-18 21:28:04 +03:00
committed by GitHub
25 changed files with 120 additions and 43 deletions

View File

@@ -35,6 +35,7 @@
#include "../adventureMap/AdventureMapInterface.h"
#include "../../CCallback.h"
#include "../../lib/BattleFieldHandler.h"
#include "../../lib/CStack.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CGeneralTextHandler.h"
@@ -113,6 +114,9 @@ void BattleInterface::playIntroSoundAndUnlockInterface()
onIntroSoundPlayed();
};
auto bfieldType = getBattle()->battleGetBattlefieldType();
const auto & battlefieldSound = bfieldType.getInfo()->musicFilename;
std::vector<soundBase::soundID> battleIntroSounds =
{
soundBase::battle00, soundBase::battle01,
@@ -120,7 +124,13 @@ void BattleInterface::playIntroSoundAndUnlockInterface()
soundBase::battle05, soundBase::battle06, soundBase::battle07
};
int battleIntroSoundChannel = CCS->soundh->playSoundFromSet(battleIntroSounds);
int battleIntroSoundChannel = -1;
if (!battlefieldSound.empty())
battleIntroSoundChannel = CCS->soundh->playSound(battlefieldSound);
else
battleIntroSoundChannel = CCS->soundh->playSoundFromSet(battleIntroSounds);
if (battleIntroSoundChannel != -1)
{
CCS->soundh->setCallback(battleIntroSoundChannel, onIntroPlayed);
@@ -144,7 +154,13 @@ void BattleInterface::onIntroSoundPlayed()
if (openingPlaying())
openingEnd();
CCS->musich->playMusicFromSet("battle", true, true);
auto bfieldType = getBattle()->battleGetBattlefieldType();
const auto & battlefieldMusic = bfieldType.getInfo()->musicFilename;
if (!battlefieldMusic.empty())
CCS->musich->playMusic(battlefieldMusic, true, true);
else
CCS->musich->playMusicFromSet("battle", true, true);
}
void BattleInterface::openingEnd()

View File

@@ -16,6 +16,7 @@
#include "../renderSDL/SDLRWwrapper.h"
#include "../../lib/CRandomGenerator.h"
#include "../../lib/CTownHandler.h"
#include "../../lib/TerrainHandler.h"
#include "../../lib/filesystem/Filesystem.h"
@@ -64,7 +65,17 @@ void CMusicHandler::loadTerrainMusicThemes()
{
for(const auto & terrain : CGI->terrainTypeHandler->objects)
{
addEntryToSet("terrain_" + terrain->getJsonKey(), terrain->musicFilename);
for(const auto & filename : terrain->musicFilename)
addEntryToSet("terrain_" + terrain->getJsonKey(), filename);
}
for(const auto & faction : CGI->townh->objects)
{
if (!faction || !faction->hasTown())
continue;
for(const auto & filename : faction->town->clientInfo.musicTheme)
addEntryToSet("faction_" + faction->getJsonKey(), filename);
}
}

View File

@@ -1283,7 +1283,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
recreateIcons();
if (!from)
adventureInt->onAudioPaused();
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false);
CCS->musich->playMusicFromSet("faction", town->town->faction->getJsonKey(), true, false);
}
CCastleInterface::~CCastleInterface()

View File

@@ -119,7 +119,7 @@
"dwellingUpLvl7": { "animation" : "TBCSUP_6.def", "x" : 303, "y" : 0, "z" : -1, "border" : "TOCSANG2.bmp", "area" : "TZCSANG2.bmp" }
},
"musicTheme" : "music/CstleTown",
"musicTheme" : [ "music/CstleTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -123,7 +123,7 @@
"dwellingUpLvl7": { "animation" : "TBELUP_6.def", "x" : 43, "y" : 0, "z" : -2, "border" : "TOELUP_6.bmp", "area" : "TZELUP_6.bmp" }
},
"musicTheme" : "music/ElemTown",
"musicTheme" : [ "music/ElemTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -119,7 +119,7 @@
"dwellingUpLvl7": { "animation" : "TBDNUP_6.def", "x" : 550, "y" : 0, "z" : -1, "border" : "TODDRA2A.bmp", "area" : "TZDDRA2A.bmp" }
},
"musicTheme" : "music/Dungeon",
"musicTheme" : [ "music/Dungeon" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -119,7 +119,7 @@
"dwellingUpLvl7": { "animation" : "TBFRUP_6.def", "x" : 587, "y" : 263, "z" : 5, "border" : "TOFHYD2A.bmp", "area" : "TZFHYD2A.bmp" }
},
"musicTheme" : "music/FortressTown",
"musicTheme" : [ "music/FortressTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -120,7 +120,7 @@
"dwellingUpLvl7": { "animation" : "TBINUP_6.def", "x" : 420, "y" : 105, "z" : -1, "border" : "TOIDVL2.bmp", "area" : "TZIDVL2.bmp" }
},
"musicTheme" : "music/InfernoTown",
"musicTheme" : [ "music/InfernoTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -124,7 +124,7 @@
"dwellingUpLvl7": { "animation" : "TBNCUP_6.def", "x" : 662, "y" : 23, "border" : "TONBON2.bmp", "area" : "TZNBON2.bmp" }
},
"musicTheme" : "music/NecroTown",
"musicTheme" : [ "music/NecroTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -123,7 +123,7 @@
"dwellingUpLvl7": { "animation" : "TBRMUP_6.def", "x" : 502, "y" : 5, "z" : -5, "border" : "TORDR2AA.bmp", "area" : "TZRDR2AA.bmp" }
},
"musicTheme" : "music/Rampart",
"musicTheme" : [ "music/Rampart" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -117,7 +117,7 @@
"dwellingUpLvl7": { "animation" : "TBSTUP_6.def", "x" : 604, "y" : 0, "border" : "TOSBEH2A.bmp", "area" : "TZSBEH2A.bmp" }
},
"musicTheme" : "music/Stronghold",
"musicTheme" : [ "music/Stronghold" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -118,7 +118,7 @@
"dwellingUpLvl7": { "animation" : "TBTWUP_6.def", "x" : 75, "y" : 91, "z" : -1, "border" : "TOTTIT2.bmp", "area" : "TZTTIT2.bmp" }
},
"musicTheme" : "music/TowerTown",
"musicTheme" : [ "music/TowerTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",

View File

@@ -24,6 +24,18 @@
"format" : "imageFile",
"description" : "Background image for this battlefield"
},
"music" :
{
"description" : "Optional, filename for custom music to play during combat on this terrain",
"type" : "string",
"format" : "musicFile"
},
"openingSound" :
{
"description" : "Optional, filename for custom sound to play during combat opening on this terrain",
"type" : "string",
"format" : "musicFile"
},
"impassableHexes" : {
"type" : "array",
"description" : "List of battle hexes that will be always blocked on this battlefield (e.g. ship to ship battles)",

View File

@@ -151,9 +151,13 @@
"$ref" : "townSiege.json"
},
"musicTheme" : {
"type" : "string",
"description" : "Path to town music theme",
"format" : "musicFile"
"type" : "array",
"description" : "Path to town music themes",
"minItems" : 1,
"items" : {
"type" : "string",
"format" : "musicFile"
}
},
"tavernVideo" : {
"type" : "string",

View File

@@ -97,9 +97,13 @@
},
"music" :
{
"type" : "string",
"description" : "Music filename to play on this terrain on adventure map",
"format" : "musicFile"
"description" : "Music filenames to play on this terrain on adventure map",
"type" : "array",
"minItems" : 1,
"items" : {
"type" : "string",
"format" : "musicFile"
}
},
"sounds" :
{

View File

@@ -5,7 +5,7 @@
"moveCost" : 100,
"minimapUnblocked" : [ 82, 56, 8 ],
"minimapBlocked" : [ 57, 40, 8 ],
"music" : "Dirt.mp3",
"music" : [ "Dirt.mp3" ],
"tiles" : "DIRTTL",
"type" : ["SURFACE"],
"shortIdentifier" : "dt",
@@ -21,7 +21,7 @@
"moveCost" : 150,
"minimapUnblocked" : [ 222, 207, 140 ],
"minimapBlocked" : [ 165, 158, 107 ],
"music" : "Sand.mp3",
"music" : [ "Sand.mp3" ],
"tiles" : "SANDTL",
"type" : ["SURFACE"],
"shortIdentifier" : "sa",
@@ -38,7 +38,7 @@
"moveCost" : 100,
"minimapUnblocked" : [ 0, 65, 0 ],
"minimapBlocked" : [ 0, 48, 0 ],
"music" : "Grass.mp3",
"music" : [ "Grass.mp3" ],
"tiles" : "GRASTL",
"type" : ["SURFACE"],
"shortIdentifier" : "gr",
@@ -53,7 +53,7 @@
"moveCost" : 150,
"minimapUnblocked" : [ 181, 199, 198 ],
"minimapBlocked" : [ 140, 158, 156 ],
"music" : "Snow.mp3",
"music" : [ "Snow.mp3" ],
"tiles" : "SNOWTL",
"type" : ["SURFACE"],
"shortIdentifier" : "sn",
@@ -68,7 +68,7 @@
"moveCost" : 175,
"minimapUnblocked" : [ 74, 134, 107 ],
"minimapBlocked" : [ 33, 89, 66 ],
"music" : "Swamp.mp3",
"music" : [ "Swamp.mp3" ],
"tiles" : "SWMPTL",
"type" : ["SURFACE"],
"shortIdentifier" : "sw",
@@ -83,7 +83,7 @@
"moveCost" : 125,
"minimapUnblocked" : [ 132, 113, 49 ],
"minimapBlocked" : [ 99, 81, 33 ],
"music" : "Rough.mp3",
"music" : [ "Rough.mp3" ],
"tiles" : "ROUGTL",
"type" : ["SURFACE"],
"shortIdentifier" : "rg",
@@ -98,7 +98,7 @@
"moveCost" : 100,
"minimapUnblocked" : [ 132, 48, 0 ],
"minimapBlocked" : [ 90, 8, 0 ],
"music" : "Underground.mp3",
"music" : [ "Underground.mp3" ],
"tiles" : "SUBBTL",
"type" : [ "SUB" ],
"shortIdentifier" : "sb",
@@ -114,7 +114,7 @@
"moveCost" : 100,
"minimapUnblocked" : [ 74, 73, 74 ],
"minimapBlocked" : [ 41, 40, 41 ],
"music" : "Lava.mp3",
"music" : [ "Lava.mp3" ],
"tiles" : "LAVATL",
"type" : ["SUB", "SURFACE"],
"shortIdentifier" : "lv",
@@ -133,7 +133,7 @@
"moveCost" : 100,
"minimapUnblocked" : [ 8, 81, 148 ],
"minimapBlocked" : [ 8, 81, 148 ],
"music" : "Water.mp3",
"music" : [ "Water.mp3" ],
"tiles" : "WATRTL",
"type" : [ "WATER" ],
"shortIdentifier" : "wt",
@@ -156,7 +156,7 @@
"moveCost" : -1,
"minimapUnblocked" : [ 0, 0, 0 ],
"minimapBlocked" : [ 0, 0, 0 ],
"music" : "Underground.mp3", // Impossible in H3
"music" : [ "Underground.mp3" ], // Impossible in H3
"tiles" : "ROCKTL",
"type" : [ "ROCK" ],
"shortIdentifier" : "rc",

View File

@@ -2,18 +2,24 @@
```jsonc
// Human-readable name of the battlefield
"name" : ""
"name" : "",
// If set to true, obstacles will be taken from "specialBattlefields" property of an obstacle
// If set to false, obstacles will be taken from "allowedTerrains" instead
"isSpecial" : false
"isSpecial" : false,
// List of bonuses that will affect all battles on this battlefield
"bonuses" : { BONUS_FORMAT }
"bonuses" : { BONUS_FORMAT },
// Background image for this battlefield
"graphics" : ""
"graphics" : "",
// Optional, filename for custom music to play during combat on this terrain
"music" : "",
// Optional, filename for custom sound to play during combat opening on this terrain
"openingSound" : "",
// List of battle hexes that will be always blocked on this battlefield (e.g. ship to ship battles)
"impassableHexes" : [ 10, 20, 50 ]
"impassableHexes" : [ 10, 20, 50 ],
```

View File

@@ -32,7 +32,7 @@ In order to make functional town you also need:
### Music
- Town theme music track (1 music file)
- Town theme music track (at least 1 music file)
### Buildings
@@ -152,8 +152,9 @@ Each town requires a set of buildings (Around 30-45 buildings)
}
}
},
// Path to town music theme, e.g. "music/castleTheme"
"musicTheme" : "",
// List of town music themes, e.g. [ "music/castleTheme" ]
// At least one music file is required
"musicTheme" : [ "" ],
// List of structures which represents visible graphical objects on town screen.
// See detailed description below

View File

@@ -50,8 +50,8 @@
// Color of terrain on minimap with unpassable objects. RGB triplet, 0-255 range
"minimapBlocked" : [ 150, 100, 50 ],
// Music filename to play on this terrain on adventure map
"music" : "",
// List of music files to play on this terrain on adventure map. At least one file is required
"music" : [ "" ],
"sounds" : {
// List of ambient sounds for this terrain

View File

@@ -40,6 +40,9 @@ std::shared_ptr<BattleFieldInfo> BattleFieldHandler::loadFromJson(const std::str
for(auto node : json["impassableHexes"].Vector())
info->impassableHexes.emplace_back(node.Integer());
info->openingSoundFilename = AudioPath::fromJson(json["openingSound"]);
info->musicFilename = AudioPath::fromJson(json["music"]);
return info;
}

View File

@@ -32,6 +32,8 @@ public:
std::string icon;
si32 iconIndex;
std::vector<BattleHex> impassableHexes;
AudioPath openingSoundFilename;
AudioPath musicFilename;
BattleFieldInfo()
: BattleFieldInfo(BattleField::NONE, "")

View File

@@ -902,8 +902,17 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source) const
readIcon(source["icons"]["fort"]["normal"], info.iconSmall[1][0], info.iconLarge[1][0]);
readIcon(source["icons"]["fort"]["built"], info.iconSmall[1][1], info.iconLarge[1][1]);
if (source["musicTheme"].isVector())
{
for (auto const & entry : source["musicTheme"].Vector())
info.musicTheme.push_back(AudioPath::fromJson(entry));
}
else
{
info.musicTheme.push_back(AudioPath::fromJson(source["musicTheme"]));
}
info.hallBackground = ImagePath::fromJson(source["hallBackground"]);
info.musicTheme = AudioPath::fromJson(source["musicTheme"]);
info.townBackground = ImagePath::fromJson(source["townBackground"]);
info.guildWindow = ImagePath::fromJson(source["guildWindow"]);
info.buildingsIcons = AnimationPath::fromJson(source["buildingsIcons"]);

View File

@@ -253,7 +253,7 @@ public:
std::string iconSmall[2][2]; /// icon names used during loading
std::string iconLarge[2][2];
VideoPath tavernVideo;
AudioPath musicTheme;
std::vector<AudioPath> musicTheme;
ImagePath townBackground;
ImagePath guildBackground;
ImagePath guildWindow;

View File

@@ -28,7 +28,16 @@ std::shared_ptr<TerrainType> TerrainTypeHandler::loadFromJson( const std::string
info->identifier = identifier;
info->modScope = scope;
info->moveCost = static_cast<int>(json["moveCost"].Integer());
info->musicFilename = AudioPath::fromJson(json["music"]);
if (json["music"].isVector())
{
for (auto const & entry : json["music"].Vector())
info->musicFilename.push_back(AudioPath::fromJson(entry));
}
else
{
info->musicFilename.push_back(AudioPath::fromJson(json["music"]));
}
info->tilesFilename = AnimationPath::fromJson(json["tiles"]);
info->horseSound = AudioPath::fromJson(json["horseSound"]);
info->horseSoundPenalty = AudioPath::fromJson(json["horseSoundPenalty"]);

View File

@@ -67,7 +67,7 @@ public:
ColorRGBA minimapBlocked;
ColorRGBA minimapUnblocked;
std::string shortIdentifier;
AudioPath musicFilename;
std::vector<AudioPath> musicFilename;
AnimationPath tilesFilename;
std::string terrainViewPatterns;
AudioPath horseSound;