1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00
This commit is contained in:
Laserlicht 2024-09-27 22:47:22 +02:00
parent efcac3b933
commit a9327b3fa3
17 changed files with 121 additions and 8 deletions

View File

@ -249,6 +249,12 @@ int CBattleCallback::sendRequest(const CPackForServer * request)
return requestID;
}
void CCallback::spellResearch( const CGTownInstance *town )
{
SpellResearch pack(town->id);
sendRequest(&pack);
}
void CCallback::swapGarrisonHero( const CGTownInstance *town )
{
if(town->tempOwner == *player || (town->garrisonHero && town->garrisonHero->tempOwner == *player ))

View File

@ -78,6 +78,7 @@ public:
virtual bool visitTownBuilding(const CGTownInstance *town, BuildingID buildingID)=0;
virtual void recruitCreatures(const CGDwelling *obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1)=0;
virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
virtual void spellResearch(const CGTownInstance *town)=0;
virtual void swapGarrisonHero(const CGTownInstance *town)=0;
virtual void trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
@ -187,6 +188,7 @@ public:
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE) override;
void endTurn() override;
void spellResearch(const CGTownInstance *town) override;
void swapGarrisonHero(const CGTownInstance *town) override;
void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override;
void trade(const ObjectInstanceID marketId, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;

View File

@ -159,6 +159,7 @@ public:
friend class CBattleCallback; //handling players actions
void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> & spells) override {};
void setTownSpells(const CGTownInstance * town, int level, const std::vector<SpellID> spells) override {};
bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override {return false;};
void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) override {};
void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {};

View File

@ -1966,7 +1966,7 @@ void CFortScreen::RecruitArea::showPopupWindow(const Point & cursorPosition)
}
CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner, const ImagePath & imagename)
: CWindowObject(BORDERED, imagename)
: CWindowObject(BORDERED, imagename), town(owner->town)
{
OBJECT_CONSTRUCTION;
@ -1997,15 +1997,15 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner, const ImagePath & i
for(size_t j=0; j<spellCount; j++)
{
if(i<owner->town->mageGuildLevel() && owner->town->spells[i].size()>j)
spells.push_back(std::make_shared<Scroll>(positions[i][j], owner->town->spells[i][j].toSpell()));
spells.push_back(std::make_shared<Scroll>(positions[i][j], owner->town->spells[i][j].toSpell(), town));
else
emptyScrolls.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("TPMAGES.DEF"), 1, 0, positions[i][j].x, positions[i][j].y));
}
}
}
CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell)
: spell(Spell)
CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell, const CGTownInstance *town)
: spell(Spell), town(town)
{
OBJECT_CONSTRUCTION;
@ -2017,6 +2017,9 @@ CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell)
void CMageGuildScreen::Scroll::clickPressed(const Point & cursorPosition)
{
if(LOCPLINT->cb->getSettings().getBoolean(EGameSettings::TOWNS_SPELL_RESEARCH))
LOCPLINT->cb->spellResearch(town);
else
LOCPLINT->showInfoDialog(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(ComponentType::SPELL, spell->id));
}

View File

@ -379,9 +379,10 @@ class CMageGuildScreen : public CStatusbarWindow
{
const CSpell * spell;
std::shared_ptr<CAnimImage> image;
const CGTownInstance *town;
public:
Scroll(Point position, const CSpell *Spell);
Scroll(Point position, const CSpell *Spell, const CGTownInstance *town);
void clickPressed(const Point & cursorPosition) override;
void showPopupWindow(const Point & cursorPosition) override;
void hover(bool on) override;
@ -393,6 +394,8 @@ class CMageGuildScreen : public CStatusbarWindow
std::shared_ptr<CMinorResDataBar> resdatabar;
const CGTownInstance *town;
public:
CMageGuildScreen(CCastleInterface * owner, const ImagePath & image);
};

View File

@ -313,7 +313,7 @@
// Chances for a town with default buildings to receive corresponding dwelling level built in start
"startingDwellingChances": [100, 50],
// Enable spell research in mage guild
"spellResearch": false
"spellResearch": true
},
"combat":

View File

@ -94,6 +94,7 @@ public:
virtual void showInfoDialog(InfoWindow * iw) = 0;
virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells)=0;
virtual void setTownSpells(const CGTownInstance * town, int level, const std::vector<SpellID> spells)=0;
virtual bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) = 0;
virtual void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) = 0;
virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0;

View File

@ -915,7 +915,7 @@ void CGameState::initTowns()
vti->spells[s->getLevel()-1].push_back(s->id);
vti->possibleSpells -= s->id;
}
vti->possibleSpells.clear();
vti->possibleSpells.clear(); //SR
}
}

View File

@ -42,6 +42,7 @@ public:
virtual void visitSetSecSkill(SetSecSkill & pack) {}
virtual void visitHeroVisitCastle(HeroVisitCastle & pack) {}
virtual void visitChangeSpells(ChangeSpells & pack) {}
virtual void visitSetTownSpells(SetTownSpells & pack) {}
virtual void visitSetMana(SetMana & pack) {}
virtual void visitSetMovePoints(SetMovePoints & pack) {}
virtual void visitFoWChange(FoWChange & pack) {}
@ -128,6 +129,7 @@ public:
virtual void visitBuildStructure(BuildStructure & pack) {}
virtual void visitVisitTownBuilding(VisitTownBuilding & pack) {}
virtual void visitRazeStructure(RazeStructure & pack) {}
virtual void visitSpellResearch(SpellResearch & pack) {}
virtual void visitRecruitCreatures(RecruitCreatures & pack) {}
virtual void visitUpgradeCreature(UpgradeCreature & pack) {}
virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) {}

View File

@ -162,6 +162,10 @@ void ChangeSpells::visitTyped(ICPackVisitor & visitor)
visitor.visitChangeSpells(*this);
}
void SetTownSpells::visitTyped(ICPackVisitor & visitor)
{
visitor.visitSetTownSpells(*this);
}
void SetMana::visitTyped(ICPackVisitor & visitor)
{
visitor.visitSetMana(*this);
@ -592,6 +596,11 @@ void RazeStructure::visitTyped(ICPackVisitor & visitor)
visitor.visitRazeStructure(*this);
}
void SpellResearch::visitTyped(ICPackVisitor & visitor)
{
visitor.visitSpellResearch(*this);
}
void RecruitCreatures::visitTyped(ICPackVisitor & visitor)
{
visitor.visitRecruitCreatures(*this);
@ -930,6 +939,13 @@ void ChangeSpells::applyGs(CGameState *gs)
hero->removeSpellFromSpellbook(sid);
}
void SetTownSpells::applyGs(CGameState *gs)
{
CGTownInstance *town = gs->getTown(tid);
town->spells[level] = spells;
}
void SetMana::applyGs(CGameState *gs)
{
CGHeroInstance * hero = gs->getHero(hid);

View File

@ -288,6 +288,24 @@ struct DLL_LINKAGE ChangeSpells : public CPackForClient
}
};
struct DLL_LINKAGE SetTownSpells : public CPackForClient
{
void applyGs(CGameState * gs) override;
void visitTyped(ICPackVisitor & visitor) override;
ui8 level = 0;
ObjectInstanceID tid;
std::vector<SpellID> spells;
template <typename Handler> void serialize(Handler & h)
{
h & level;
h & tid;
h & spells;
}
};
struct DLL_LINKAGE SetMana : public CPackForClient
{
void applyGs(CGameState * gs) override;

View File

@ -306,6 +306,24 @@ struct DLL_LINKAGE RazeStructure : public BuildStructure
void visitTyped(ICPackVisitor & visitor) override;
};
struct DLL_LINKAGE SpellResearch : public CPackForServer
{
SpellResearch() = default;
SpellResearch(const ObjectInstanceID & TID)
: tid(TID)
{
}
ObjectInstanceID tid;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & static_cast<CPackForServer &>(*this);
h & tid;
}
};
struct DLL_LINKAGE RecruitCreatures : public CPackForServer
{
RecruitCreatures() = default;

View File

@ -288,6 +288,8 @@ void registerTypes(Serializer &s)
s.template registerType<LobbySetDifficulty>(238);
s.template registerType<LobbyForceSetPlayer>(239);
s.template registerType<LobbySetExtraOptions>(240);
s.template registerType<SpellResearch>(241);
s.template registerType<SetTownSpells>(242);
}
VCMI_LIB_NAMESPACE_END

View File

@ -1235,6 +1235,15 @@ void CGameHandler::changeSpells(const CGHeroInstance * hero, bool give, const st
sendAndApply(&cs);
}
void CGameHandler::setTownSpells(const CGTownInstance * town, int level, const std::vector<SpellID> spells)
{
SetTownSpells cs;
cs.tid = town->id;
cs.spells = spells;
cs.level = level;
sendAndApply(&cs);
}
void CGameHandler::giveHeroBonus(GiveBonus * bonus)
{
sendAndApply(bonus);
@ -2233,6 +2242,29 @@ bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
return true;
}
bool CGameHandler::spellResearch(ObjectInstanceID tid)
{
if(!getSettings().getBoolean(EGameSettings::TOWNS_SPELL_RESEARCH) && complain("Spell research not allowed!"))
return false;
CGTownInstance *t = gs->getTown(tid);
auto spells = t->spells.at(1);
auto spell = SpellID(SpellID::FLY);
spells.at(0) = spell;
setTownSpells(t, 1, spells);
spellResearchFinished(tid);
return true;
}
void CGameHandler::spellResearchFinished(ObjectInstanceID tid)
{
const CGTownInstance * t = getTown(tid);
if(t->visitingHero)
giveSpells(t, t->visitingHero);
if(t->garrisonHero)
giveSpells(t, t->garrisonHero);
}
bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dstid, CreatureID crid, ui32 cram, si32 fromLvl, PlayerColor player)
{
const CGDwelling * dwelling = dynamic_cast<const CGDwelling *>(getObj(objid));

View File

@ -107,6 +107,7 @@ public:
//from IGameCallback
//do sth
void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells) override;
void setTownSpells(const CGTownInstance * town, int level, const std::vector<SpellID> spells) override;
bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override;
void setOwner(const CGObjectInstance * obj, PlayerColor owner) override;
void giveExperience(const CGHeroInstance * hero, TExpType val) override;
@ -218,6 +219,8 @@ public:
bool buildStructure(ObjectInstanceID tid, BuildingID bid, bool force=false);//force - for events: no cost, no checkings
bool visitTownBuilding(ObjectInstanceID tid, BuildingID bid);
bool razeStructure(ObjectInstanceID tid, BuildingID bid);
bool spellResearch(ObjectInstanceID tid);
void spellResearchFinished(ObjectInstanceID tid);
bool disbandCreature( ObjectInstanceID id, SlotID pos );
bool arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, SlotID p1, SlotID p2, si32 val, PlayerColor player);
bool bulkMoveArmy(ObjectInstanceID srcArmy, ObjectInstanceID destArmy, SlotID srcSlot);

View File

@ -138,6 +138,11 @@ void ApplyGhNetPackVisitor::visitBuildStructure(BuildStructure & pack)
result = gh.buildStructure(pack.tid, pack.bid);
}
void ApplyGhNetPackVisitor::visitSpellResearch(SpellResearch & pack)
{
result = gh.spellResearch(pack.tid);
}
void ApplyGhNetPackVisitor::visitVisitTownBuilding(VisitTownBuilding & pack)
{
gh.throwIfWrongOwner(&pack, pack.tid);

View File

@ -41,6 +41,7 @@ public:
void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) override;
void visitDisbandCreature(DisbandCreature & pack) override;
void visitBuildStructure(BuildStructure & pack) override;
void visitSpellResearch(SpellResearch & pack) override;
void visitVisitTownBuilding(VisitTownBuilding & pack) override;
void visitRecruitCreatures(RecruitCreatures & pack) override;
void visitUpgradeCreature(UpgradeCreature & pack) override;