1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Merge pull request #5814 from Laserlicht/mage_guild

Mage guild configurable
This commit is contained in:
Ivan Savenko
2025-06-30 11:56:46 +03:00
committed by GitHub
14 changed files with 197 additions and 54 deletions

View File

@@ -1194,7 +1194,10 @@ void CCastleBuildings::enterTownHall()
void CCastleBuildings::openMagesGuild()
{
auto mageGuildBackground = GAME->interface()->castleInt->town->getTown()->clientInfo.guildBackground;
ENGINE->windows().createAndPushWindow<CMageGuildScreen>(GAME->interface()->castleInt, mageGuildBackground);
assert(mageGuildBackground.size() == 1 || mageGuildBackground.size() == GAME->interface()->castleInt->town->getTown()->mageLevel);
auto selectedMageGuildBackground = mageGuildBackground.size() == 1 ? mageGuildBackground[0] : mageGuildBackground[town->mageGuildLevel() - 1];
ENGINE->windows().createAndPushWindow<CMageGuildScreen>(GAME->interface()->castleInt, selectedMageGuildBackground);
}
void CCastleBuildings::openTownHall()
@@ -2114,7 +2117,14 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner, const ImagePath & i
{
OBJECT_CONSTRUCTION;
window = std::make_shared<CPicture>(owner->town->getTown()->clientInfo.guildWindow, 332, 76);
auto guildWindow = owner->town->getTown()->clientInfo.guildWindow;
assert(guildWindow.size() == 1 || guildWindow.size() == GAME->interface()->castleInt->town->getTown()->mageLevel);
auto selectedGuildWindow = guildWindow.size() == 1 ? guildWindow[0] : guildWindow[owner->town->mageGuildLevel() - 1];
auto windowPosition = owner->town->getTown()->clientInfo.guildWindowPosition;
if(windowPosition == Point(0, 0)) // TODO: remove legacy for compatibility
windowPosition = Point(332, 76);
window = std::make_shared<CPicture>(selectedGuildWindow, windowPosition.x, windowPosition.y);
resdatabar = std::make_shared<CMinorResDataBar>();
resdatabar->moveBy(pos.topLeft(), true);
@@ -2135,20 +2145,23 @@ void CMageGuildScreen::updateSpells(ObjectInstanceID tID)
return;
OBJECT_CONSTRUCTION;
static const std::vector<std::vector<Point> > positions =
{
{Point(222,445), Point(312,445), Point(402,445), Point(520,445), Point(610,445), Point(700,445)},
{Point(48,53), Point(48,147), Point(48,241), Point(48,335), Point(48,429)},
{Point(570,82), Point(672,82), Point(570,157), Point(672,157)},
{Point(183,42), Point(183,148), Point(183,253)},
{Point(491,325), Point(591,325)}
};
spells.clear();
emptyScrolls.clear();
const CGTownInstance * town = GAME->interface()->cb->getTown(townId);
auto positions = town->getTown()->clientInfo.guildSpellPositions;
if(!positions.size()) // TODO: remove legacy for compatibility
positions =
{
{Point(222,445), Point(312,445), Point(402,445), Point(520,445), Point(610,445), Point(700,445)},
{Point(48,53), Point(48,147), Point(48,241), Point(48,335), Point(48,429)},
{Point(570,82), Point(672,82), Point(570,157), Point(672,157)},
{Point(183,42), Point(183,148), Point(183,253)},
{Point(491,325), Point(591,325)}
};
for(uint32_t i=0; i<town->getTown()->mageLevel; i++)
{
uint32_t spellCount = town->spellsAtLevel(i+1,false); //spell at level with -1 hmmm?

View File

@@ -122,9 +122,9 @@
"musicTheme" : [ "music/CstleTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBCSBACK.bmp",
"guildWindow": "TPMAGECS.bmp",
"guildWindow": [ "TPMAGECS.bmp" ],
"buildingsIcons": "HALLCSTL.DEF",
"hallBackground": "TPTHBKCS.BMP",
"hallSlots":
@@ -147,6 +147,13 @@
],
"horde" : [ 2, -1 ],
"mageGuild" : 4,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"moatAbility" : "castleMoat",
// primaryResource not specified so town get both Wood and Ore for resource bonus

View File

@@ -126,9 +126,9 @@
"musicTheme" : [ "music/ElemTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBELBACK.bmp",
"guildWindow": "TPMAGEEL.bmp",
"guildWindow": [ "TPMAGEEL.bmp" ],
"buildingsIcons": "HALLELEM.DEF",
"hallBackground": "TPTHBKFR.BMP",
"hallSlots":
@@ -151,6 +151,14 @@
],
"horde" : [ 0, -1 ],
"mageGuild" : 5,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"primaryResource" : "mercury",
"moatAbility" : "castleMoat",

View File

@@ -122,9 +122,9 @@
"musicTheme" : [ "music/Dungeon" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBDNBACK.bmp",
"guildWindow": "TPMAGEDN.bmp",
"guildWindow": [ "TPMAGEDN.bmp" ],
"buildingsIcons": "HALLDUNG.DEF",
"hallBackground": "TPTHBKDG.BMP",
"hallSlots":
@@ -147,6 +147,14 @@
],
"horde" : [ 0, -1 ],
"mageGuild" : 5,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"primaryResource" : "sulfur",
"moatAbility" : "dungeonMoat",

View File

@@ -122,9 +122,9 @@
"musicTheme" : [ "music/FortressTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBFRBACK.bmp",
"guildWindow": "TPMAGEFR.bmp",
"guildWindow": [ "TPMAGEFR.bmp" ],
"buildingsIcons": "HALLFORT.DEF",
"hallBackground": "TPTHBKFR.BMP",
"hallSlots":
@@ -147,6 +147,12 @@
],
"horde" : [ 0, -1 ],
"mageGuild" : 3,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"moatAbility" : "fortressMoat",
// primaryResource not specified so town get both Wood and Ore for resource bonus

View File

@@ -123,9 +123,9 @@
"musicTheme" : [ "music/InfernoTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBINBACK.bmp",
"guildWindow": "TPMAGEIN.bmp",
"guildWindow": [ "TPMAGEIN.bmp" ],
"buildingsIcons": "HALLINFR.DEF",
"hallBackground": "TPTHBKIN.BMP",
"hallSlots":
@@ -148,6 +148,14 @@
],
"horde" : [ 0, 2 ],
"mageGuild" : 5,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"primaryResource" : "mercury",
"moatAbility" : "infernoMoat",

View File

@@ -127,9 +127,9 @@
"musicTheme" : [ "music/NecroTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBNCBACK.bmp",
"guildWindow": "TPMAGENC.bmp",
"guildWindow": [ "TPMAGENC.bmp" ],
"buildingsIcons": "HALLNECR.DEF",
"hallBackground": "TPTHBKNC.BMP",
"hallSlots":
@@ -152,6 +152,14 @@
],
"horde" : [ 0, -1 ],
"mageGuild" : 5,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"moatAbility" : "necropolisMoat",
// primaryResource not specified so town get both Wood and Ore for resource bonus

View File

@@ -126,9 +126,9 @@
"musicTheme" : [ "music/Rampart" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBRMBACK.bmp",
"guildWindow": "TPMAGERM.bmp",
"guildWindow": [ "TPMAGERM.bmp" ],
"buildingsIcons": "HALLRAMP.DEF",
"hallBackground": "TPTHBKRM.BMP",
"hallSlots":
@@ -151,6 +151,14 @@
],
"horde" : [ 1, 4 ],
"mageGuild" : 5,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"primaryResource" : "crystal",
"moatAbility" : "rampartMoat",

View File

@@ -120,9 +120,9 @@
"musicTheme" : [ "music/Stronghold" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBSTBACK.bmp",
"guildWindow": "TPMAGEST.bmp",
"guildWindow": [ "TPMAGEST.bmp" ],
"buildingsIcons": "HALLSTRN.DEF",
"hallBackground": "TPTHBKTW.BMP",
"hallSlots":
@@ -145,6 +145,12 @@
],
"horde" : [ 0, -1 ],
"mageGuild" : 3,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"moatAbility" : "strongholdMoat",
// primaryResource not specified so town get both Wood and Ore for resource bonus

View File

@@ -121,9 +121,9 @@
"musicTheme" : [ "music/TowerTown" ],
"defaultTavern" : 5,
"tavernVideo" : "TAVERN.BIK",
"guildBackground" : "TPMAGE.bmp",
"guildBackground" : [ "TPMAGE.bmp" ],
"townBackground": "TBTWBACK.bmp",
"guildWindow": "TPMAGETW.bmp",
"guildWindow": [ "TPMAGETW.bmp" ],
"buildingsIcons": "HALLTOWR.DEF",
"hallBackground": "TPTHBKTW.BMP",
"hallSlots":
@@ -147,6 +147,14 @@
"horde" : [ 1, -1 ],
"primaryResource" : "gems",
"mageGuild" : 5,
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
"guildWindowPosition": { "x": 332, "y": 76 },
"moatAbility" : "towerMoat",
"buildings" :

View File

@@ -166,13 +166,51 @@
"format" : "imageFile"
},
"guildWindow" : {
"type" : "string",
"description" : "Image with small view on town from mage guild"
"type" : "array",
"description" : "Image with small view on town from mage guild (each array element for different mage guild level; if one element only this will be always selected)",
"minItems" : 1,
"items" : {
"type" : "string",
"format" : "imageFile"
}
},
"guildBackground" : {
"type" : "string",
"description" : "Image with background of mage guild",
"format" : "imageFile"
"type" : "array",
"description" : "Image with background of mage guild (each array element for different mage guild level; if one element only this will be always selected)",
"minItems" : 1,
"items" : {
"type" : "string",
"format" : "imageFile"
}
},
"guildWindowPosition" : {
"type" : "array",
"items" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"x" : { "type" : "number", "description" : "X coordinate on screen" },
"y" : { "type" : "number", "description" : "Y coordinate on screen" }
}
}
},
"guildSpellPositions" : {
"type" : "array",
"description" : "Positions of spells in mage guild",
"items" : {
"type" : "array",
"items" : {
"type" : "array",
"items" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"x" : { "type" : "number", "description" : "X coordinate on screen" },
"y" : { "type" : "number", "description" : "Y coordinate on screen" }
}
}
}
}
},
"hallBackground" : {
"type" : "string",
@@ -259,7 +297,7 @@
"properties" : {
"index" : { "type" : "number", "description" : "Order in which images will be opened" },
"x" : { "type" : "number", "description" : "X coordinate on screen" },
"y" : { "type" : "number", "description" : "X coordinate on screen" }
"y" : { "type" : "number", "description" : "Y coordinate on screen" }
}
}
},

View File

@@ -177,11 +177,11 @@ Each town requires a set of buildings (Around 30-45 buildings)
// Background scenery for town screen, size must be 800x374
"townBackground": "",
// Small scenery for window in mage guild screen
"guildWindow": "",
// Small scenery for window in mage guild screen; each element of array is for seperate mage guild level image (if only one element, then this will always used)
"guildWindow": [""],
// Background image for window in mage guild screen
"guildBackground" : "",
// Background image for window in mage guild screen; each element of array is for seperate mage guild level image (if only one element, then this will always used)
"guildBackground" : [""],
// Video for tavern window
"tavernVideo" : "",
@@ -250,7 +250,19 @@ Each town requires a set of buildings (Around 30-45 buildings)
"primaryResource" : "gems",
// maximum level of mage guild
"mageGuild" : 4,
"mageGuild" : 5,
// Coordinates of spell images in mage guild screen. Should contain the maximum level of mage guild amount of elements. Example are HoMM3 defaults:
"guildSpellPositions" : [
[ { "x": 222, "y": 445 }, { "x": 312, "y": 445 }, { "x": 402, "y": 445 }, { "x": 520, "y": 445 }, { "x": 610, "y": 445 }, { "x": 700, "y": 445 } ],
[ { "x": 48, "y": 53 }, { "x": 48, "y": 147 }, { "x": 48, "y": 241 }, { "x": 48, "y": 335 }, { "x": 48, "y": 429 } ],
[ { "x": 570, "y": 82 }, { "x": 672, "y": 82 }, { "x": 570, "y": 157 }, { "x": 672, "y": 157 } ],
[ { "x": 183, "y": 42 }, { "x": 183, "y": 148 }, { "x": 183, "y": 253 } ],
[ { "x": 491, "y": 325 }, { "x": 591, "y": 325 } ]
],
// Coordinates of window image in mage guild screen. Example is HoMM3 default:
"guildWindowPosition": { "x": 332, "y": 76 },
// Identifier of spell that will create effects for town moat during siege
"moatAbility" : "castleMoat"

View File

@@ -89,8 +89,10 @@ public:
VideoPath tavernVideo;
std::vector<AudioPath> musicTheme;
ImagePath townBackground;
ImagePath guildBackground;
ImagePath guildWindow;
std::vector<ImagePath> guildBackground;
std::vector<ImagePath> guildWindow;
Point guildWindowPosition;
std::vector<std::vector<Point>> guildSpellPositions;
AnimationPath buildingsIcons;
ImagePath hallBackground;
/// vector[row][column] = list of buildings in this slot

View File

@@ -576,23 +576,34 @@ 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.townBackground = ImagePath::fromJson(source["townBackground"]);
info.guildWindow = ImagePath::fromJson(source["guildWindow"]);
info.buildingsIcons = AnimationPath::fromJson(source["buildingsIcons"]);
info.guildBackground = ImagePath::fromJson(source["guildBackground"]);
info.tavernVideo = VideoPath::fromJson(source["tavernVideo"]);
info.guildWindowPosition = Point(source["guildWindowPosition"]["x"].Integer(), source["guildWindowPosition"]["y"].Integer());
info.guildSpellPositions.clear();
for(auto & level : source["guildSpellPositions"].Vector())
{
std::vector<Point> points;
for(auto & item : level.Vector())
points.push_back(Point(item["x"].Integer(), item["y"].Integer()));
info.guildSpellPositions.push_back(points);
}
auto loadStringOrVector = [](auto & target, auto & node, auto fromJsonFunc){
if(node.isVector())
{
target.clear();
for(auto & background : node.Vector())
target.push_back(fromJsonFunc(background));
}
else
target = {fromJsonFunc(node)};
};
loadStringOrVector(info.musicTheme, source["musicTheme"], AudioPath::fromJson);
loadStringOrVector(info.guildBackground, source["guildBackground"], ImagePath::fromJson);
loadStringOrVector(info.guildWindow, source["guildWindow"], ImagePath::fromJson);
loadTownHall(town, source["hallSlots"]);
loadStructures(town, source["structures"]);