1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

Saving costume

This commit is contained in:
SoundSSGood 2024-03-30 17:18:50 +02:00
parent 90fa1718a5
commit 25dea7e364
19 changed files with 213 additions and 10 deletions

View File

@ -193,6 +193,14 @@ void CCallback::scrollBackpackArtifacts(ObjectInstanceID hero, bool left)
sendRequest(&mba);
}
void CCallback::manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume)
{
assert(costumeIndex < GameConstants::HERO_COSTUMES_ARTIFACTS);
ManageEquippedArtifacts mea(hero, costumeIndex, saveCostume);
sendRequest(&mea);
}
void CCallback::eraseArtifactByClient(const ArtifactLocation & al)
{
EraseArtifactByClient ea(al);

View File

@ -92,6 +92,7 @@ public:
//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
virtual void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) = 0;
virtual void manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) = 0;
virtual void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
virtual void eraseArtifactByClient(const ArtifactLocation & al)=0;
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
@ -178,6 +179,7 @@ public:
void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override;
void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) override;
void manageHeroCostume(ObjectInstanceID hero, size_t costumeIdx, bool saveCostume) override;
void eraseArtifactByClient(const ArtifactLocation & al) override;
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;

View File

@ -158,6 +158,16 @@ enum class EShortcut
HERO_TIGHT_FORMATION,
HERO_TOGGLE_TACTICS, // b
HERO_BACKPACK,
HERO_COSTUME_0,
HERO_COSTUME_1,
HERO_COSTUME_2,
HERO_COSTUME_3,
HERO_COSTUME_4,
HERO_COSTUME_5,
HERO_COSTUME_6,
HERO_COSTUME_7,
HERO_COSTUME_8,
HERO_COSTUME_9,
// Spellbook screen
SPELLBOOK_TAB_ADVENTURE,

View File

@ -180,6 +180,16 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const
{"heroLooseFormation", EShortcut::HERO_LOOSE_FORMATION },
{"heroTightFormation", EShortcut::HERO_TIGHT_FORMATION },
{"heroToggleTactics", EShortcut::HERO_TOGGLE_TACTICS },
{"heroCostume0", EShortcut::HERO_COSTUME_0 },
{"heroCostume1", EShortcut::HERO_COSTUME_1 },
{"heroCostume2", EShortcut::HERO_COSTUME_2 },
{"heroCostume3", EShortcut::HERO_COSTUME_3 },
{"heroCostume4", EShortcut::HERO_COSTUME_4 },
{"heroCostume5", EShortcut::HERO_COSTUME_5 },
{"heroCostume6", EShortcut::HERO_COSTUME_6 },
{"heroCostume7", EShortcut::HERO_COSTUME_7 },
{"heroCostume8", EShortcut::HERO_COSTUME_8 },
{"heroCostume9", EShortcut::HERO_COSTUME_9 },
{"spellbookTabAdventure", EShortcut::SPELLBOOK_TAB_ADVENTURE },
{"spellbookTabCombat", EShortcut::SPELLBOOK_TAB_COMBAT }
};

View File

@ -10,13 +10,15 @@
#include "StdInc.h"
#include "CArtifactsOfHeroMain.h"
#include "../gui/CGuiHandler.h"
#include "../CPlayerInterface.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../CCallback.h"
#include "../../lib/networkPacks/ArtifactLocation.h"
CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position)
CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position, bool costumesEnabled)
{
init(
std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2),
@ -24,9 +26,41 @@ CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position)
position,
std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
addGestureCallback(std::bind(&CArtifactsOfHeroBase::gestureArtPlace, this, _1, _2));
if(costumesEnabled)
{
size_t costumeIndex = 0;
for(const auto & hotkey : hotkeys)
{
auto keyProc = costumesSwitchers.emplace_back(std::make_shared<CKeyShortcutWrapper>(hotkey,
[this, hotkey, costumeIndex]()
{
CArtifactsOfHeroMain::onCostumeSelect(costumeIndex);
}));
keyProc->addUsedEvents(AEventsReceiver::KEYBOARD);
costumeIndex++;
}
}
}
CArtifactsOfHeroMain::~CArtifactsOfHeroMain()
{
CArtifactsOfHeroBase::putBackPickedArtifact();
}
void CArtifactsOfHeroMain::onCostumeSelect(const size_t costumeIndex)
{
LOCPLINT->cb->manageHeroCostume(getHero()->id, costumeIndex, GH.isKeyboardCtrlDown());
}
CArtifactsOfHeroMain::CKeyShortcutWrapper::CKeyShortcutWrapper(const EShortcut & key, const KeyPressedFunctor & onCostumeSelect)
: CKeyShortcut(key)
, onCostumeSelect(onCostumeSelect)
{
}
void CArtifactsOfHeroMain::CKeyShortcutWrapper::clickPressed(const Point & cursorPosition)
{
if(onCostumeSelect)
onCostumeSelect();
}

View File

@ -11,15 +11,42 @@
#include "CArtifactsOfHeroBase.h"
VCMI_LIB_NAMESPACE_BEGIN
struct ArtifactLocation;
VCMI_LIB_NAMESPACE_END
#include "../gui/Shortcut.h"
class CArtifactsOfHeroMain : public CArtifactsOfHeroBase
{
public:
CArtifactsOfHeroMain(const Point & position);
CArtifactsOfHeroMain(const Point & position, bool costumesEnabled = false);
~CArtifactsOfHeroMain() override;
private:
// TODO may be removed if CKeyShortcut supports callbacks
class CKeyShortcutWrapper : public CKeyShortcut
{
public:
using KeyPressedFunctor = std::function<void()>;
CKeyShortcutWrapper(const EShortcut & key, const KeyPressedFunctor & onCostumeSelect);
void clickPressed(const Point & cursorPosition) override;
private:
KeyPressedFunctor onCostumeSelect;
};
const std::array<EShortcut, GameConstants::HERO_COSTUMES_ARTIFACTS> hotkeys =
{
EShortcut::HERO_COSTUME_0,
EShortcut::HERO_COSTUME_1,
EShortcut::HERO_COSTUME_2,
EShortcut::HERO_COSTUME_3,
EShortcut::HERO_COSTUME_4,
EShortcut::HERO_COSTUME_5,
EShortcut::HERO_COSTUME_6,
EShortcut::HERO_COSTUME_7,
EShortcut::HERO_COSTUME_8,
EShortcut::HERO_COSTUME_9
};
std::vector<std::shared_ptr<CKeyShortcutWrapper>> costumesSwitchers;
void onCostumeSelect(const size_t costumeIndex);
};

View File

@ -218,7 +218,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
}
if(!arts)
{
arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8));
arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8), true);
arts->setHero(curHero);
addSetAndCallbacks(arts);
}

View File

@ -125,6 +125,16 @@
"heroTightFormation": "T",
"heroToggleTactics": "B",
"spellbookTabAdventure": "A",
"spellbookTabCombat": "C"
"spellbookTabCombat": "C",
"heroCostume0": "0",
"heroCostume1": "1",
"heroCostume2": "2",
"heroCostume3": "3",
"heroCostume4": "4",
"heroCostume5": "5",
"heroCostume6": "6",
"heroCostume7": "7",
"heroCostume8": "8",
"heroCostume9": "9"
}
}

View File

@ -63,6 +63,7 @@ public:
std::vector<ConstTransitivePtr<CGDwelling> > dwellings; //used for town growth
std::vector<QuestInfo> quests; //store info about all received quests
std::vector<Bonus> battleBonuses; //additional bonuses to be added during battle with neutrals
std::map<size_t, std::map<ArtifactPosition, ArtifactID>> costumesArtifacts;
bool cheated;
bool enteredWinningCheatCode, enteredLosingCheatCode; //if true, this player has entered cheat codes for loss / victory
@ -111,6 +112,7 @@ public:
h & daysWithoutCastle;
h & cheated;
h & battleBonuses;
h & costumesArtifacts;
h & enteredLosingCheatCode;
h & enteredWinningCheatCode;
h & static_cast<CBonusSystemNode&>(*this);

View File

@ -87,6 +87,7 @@ public:
virtual void visitInfoWindow(InfoWindow & pack) {}
virtual void visitSetObjectProperty(SetObjectProperty & pack) {}
virtual void visitChangeObjectVisitors(ChangeObjectVisitors & pack) {}
virtual void visitChangeArtifactsCostume(ChangeArtifactsCostume & pack) {}
virtual void visitHeroLevelUp(HeroLevelUp & pack) {}
virtual void visitCommanderLevelUp(CommanderLevelUp & pack) {}
virtual void visitBlockingDialog(BlockingDialog & pack) {}
@ -132,6 +133,7 @@ public:
virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) {}
virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) {}
virtual void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) {}
virtual void visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) {}
virtual void visitAssembleArtifacts(AssembleArtifacts & pack) {}
virtual void visitEraseArtifactByClient(EraseArtifactByClient & pack) {}
virtual void visitBuyArtifact(BuyArtifact & pack) {}

View File

@ -383,6 +383,11 @@ void ChangeObjectVisitors::visitTyped(ICPackVisitor & visitor)
visitor.visitChangeObjectVisitors(*this);
}
void ChangeArtifactsCostume::visitTyped(ICPackVisitor & visitor)
{
visitor.visitChangeArtifactsCostume(*this);
}
void HeroLevelUp::visitTyped(ICPackVisitor & visitor)
{
visitor.visitHeroLevelUp(*this);
@ -613,6 +618,11 @@ void ManageBackpackArtifacts::visitTyped(ICPackVisitor & visitor)
visitor.visitManageBackpackArtifacts(*this);
}
void ManageEquippedArtifacts::visitTyped(ICPackVisitor & visitor)
{
visitor.visitManageEquippedArtifacts(*this);
}
void AssembleArtifacts::visitTyped(ICPackVisitor & visitor)
{
visitor.visitAssembleArtifacts(*this);
@ -1062,6 +1072,15 @@ void ChangeObjectVisitors::applyGs(CGameState * gs) const
}
}
void ChangeArtifactsCostume::applyGs(CGameState * gs) const
{
auto & allCostumes = gs->getPlayerState(player)->costumesArtifacts;
if(auto & costume = allCostumes.find(costumeIdx); costume != allCostumes.end())
costume->second = costumeSet;
else
allCostumes.emplace(costumeIdx, costumeSet);
}
void PlayerEndsGame::applyGs(CGameState * gs) const
{
PlayerState *p = gs->getPlayerState(player);

View File

@ -1288,6 +1288,30 @@ struct DLL_LINKAGE ChangeObjectVisitors : public CPackForClient
}
};
struct DLL_LINKAGE ChangeArtifactsCostume : public CPackForClient
{
std::map<ArtifactPosition, ArtifactID> costumeSet;
size_t costumeIdx;
const PlayerColor player;
void applyGs(CGameState * gs) const;
void visitTyped(ICPackVisitor & visitor) override;
ChangeArtifactsCostume() = default;
ChangeArtifactsCostume(const PlayerColor & player, const size_t costumeIdx)
: costumeIdx(costumeIdx)
, player(player)
{
}
template <typename Handler> void serialize(Handler & h)
{
h & costumeSet;
h & costumeIdx;
h & player;
}
};
struct DLL_LINKAGE HeroLevelUp : public Query
{
PlayerColor player;

View File

@ -429,6 +429,31 @@ struct DLL_LINKAGE ManageBackpackArtifacts : public CPackForServer
}
};
struct DLL_LINKAGE ManageEquippedArtifacts : public CPackForServer
{
ManageEquippedArtifacts() = default;
ManageEquippedArtifacts(const ObjectInstanceID & artHolder, const size_t costumeIdx, bool saveCostume = false)
: artHolder(artHolder)
, costumeIdx(costumeIdx)
, saveCostume(saveCostume)
{
}
ObjectInstanceID artHolder;
size_t costumeIdx;
bool saveCostume;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & static_cast<CPackForServer&>(*this);
h & artHolder;
h & costumeIdx;
h & saveCostume;
}
};
struct DLL_LINKAGE AssembleArtifacts : public CPackForServer
{
AssembleArtifacts() = default;

View File

@ -67,6 +67,7 @@ void registerTypesClientPacks(Serializer &s)
s.template registerType<CPackForClient, HeroVisit>();
s.template registerType<CPackForClient, SetCommanderProperty>();
s.template registerType<CPackForClient, ChangeObjectVisitors>();
s.template registerType<CPackForClient, ChangeArtifactsCostume>();
s.template registerType<CPackForClient, ShowWorldViewEx>();
s.template registerType<CPackForClient, EntitiesChanged>();
s.template registerType<CPackForClient, BattleStart>();

View File

@ -50,6 +50,7 @@ void registerTypesServerPacks(Serializer &s)
s.template registerType<CPackForServer, BulkMoveArmy>();
s.template registerType<CPackForServer, BulkExchangeArtifacts>();
s.template registerType<CPackForServer, ManageBackpackArtifacts>();
s.template registerType<CPackForServer, ManageEquippedArtifacts>();
s.template registerType<CPackForServer, EraseArtifactByClient>();
s.template registerType<CPackForServer, GamePause>();
}

View File

@ -2892,6 +2892,24 @@ bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const Obj
return true;
}
bool CGameHandler::saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx)
{
auto artSet = getArtSet(heroID);
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "saveArtifactsCostume: wrong hero's ID");
COMPLAIN_RET_FALSE_IF(costumeIdx >= GameConstants::HERO_COSTUMES_ARTIFACTS, "saveArtifactsCostume: wrong costume index");
ChangeArtifactsCostume costume(player, costumeIdx);
for(const auto & slot : ArtifactUtils::constituentWornSlots())
{
if(const auto & slotInfo = artSet->getSlot(slot))
if(!slotInfo->locked)
costume.costumeSet.emplace(slot, slotInfo->getArt()->getTypeId());
}
sendAndApply(&costume);
return true;
}
/**
* Assembles or disassembles a combination artifact.
* @param heroID ID of hero holding the artifact(s).

View File

@ -130,6 +130,7 @@ public:
bool moveArtifact(const PlayerColor & player, const ArtifactLocation & src, const ArtifactLocation & dst) override;
bool bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack);
bool scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left);
bool saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx);
bool eraseArtifactByClient(const ArtifactLocation & al);
void synchronizeArtifactHandlerLists();

View File

@ -179,6 +179,14 @@ void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts
}
}
void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts & pack)
{
gh.throwIfWrongOwner(&pack, pack.artHolder);
if(pack.saveCostume)
gh.saveArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx);
result = true;
}
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
{
gh.throwIfWrongOwner(&pack, pack.heroID);

View File

@ -47,6 +47,7 @@ public:
void visitExchangeArtifacts(ExchangeArtifacts & pack) override;
void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) override;
void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) override;
void visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) override;
void visitAssembleArtifacts(AssembleArtifacts & pack) override;
void visitEraseArtifactByClient(EraseArtifactByClient & pack) override;
void visitBuyArtifact(BuyArtifact & pack) override;