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

Some work on artifact assembly.

This commit is contained in:
OnionKnight 2010-02-16 14:39:56 +00:00
parent a6aa36c5a9
commit ab75f4b1f8
10 changed files with 190 additions and 4 deletions

View File

@ -433,6 +433,24 @@ bool CCallback::swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGH
return true;
}
/**
* Assembles or disassembles a combination artifact.
* @param hero Hero holding the artifact(s).
* @param artifactSlot The worn slot ID of the combination- or constituent artifact.
* @param assemble True for assembly operation, false for disassembly.
* @param assembleTo If assemble is true, this represents the artifact ID of the combination
* artifact to assemble to. Otherwise it's not used.
*/
bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo)
{
if (player != hero->tempOwner)
return false;
AssembleArtifacts aa(hero->id, artifactSlot, assemble, assembleTo);
sendRequest(&aa);
return true;
}
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
{
CGTownInstance * t = const_cast<CGTownInstance *>(town);

View File

@ -89,6 +89,7 @@ public:
virtual int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//joins first stack tothe second (creatures must be same type)
virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack
virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
virtual bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo)=0;
virtual bool dismissCreature(const CArmedInstance *obj, int stackPos)=0;
virtual void endTurn()=0;
virtual void buyArtifact(const CGHeroInstance *hero, int aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith)
@ -207,7 +208,7 @@ public:
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val);
bool dismissHero(const CGHeroInstance * hero);
bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
bool setArtifact(const CGHeroInstance * hero, ui16 pos, int artID);
bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo);
bool buildBuilding(const CGTownInstance *town, si32 buildingID);
void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount);
bool dismissCreature(const CArmedInstance *obj, int stackPos);

View File

@ -27,6 +27,7 @@
#include "../lib/map.h"
#include "../mapHandler.h"
#include "../timeHandler.h"
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
@ -3689,8 +3690,23 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
void CArtPlace::clickRight(tribool down, bool previousState)
{
if(!locked() && text.size()) //if there is no description or it's a lock, do nothing ;]
if(ourArt && !locked() && text.size()) { //if there is no description or it's a lock, do nothing ;]
LRClickableAreaWTextComp::clickRight(down, previousState);
/*if (ourArt->constituentOf != NULL) {
BOOST_FOREACH(ui32 combination, *ourArt->constituentOf) {
if (ourArt->canBeAssembledTo(ourOwner->curHero->artifWorn, combination)) {
LOCPLINT->cb->assembleArtifacts(ourOwner->curHero, slotID, true, combination);
return;
}
}
}
if (ourArt->constituents != NULL) {
LOCPLINT->cb->assembleArtifacts(ourOwner->curHero, slotID, false, 0);
return;
}*/
}
}
/**

View File

@ -100,6 +100,29 @@ bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) cons
return true;
}
bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 artifactID) const
{
if (constituentOf == NULL || !vstd::contains(*constituentOf, artifactID))
return false;
const CArtifact &artifact = VLC->arth->artifacts[artifactID];
assert(artifact.constituents);
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
bool found = false;
for (std::map<ui16, ui32>::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it) {
if (it->second == constituentID) {
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
CArtHandler::CArtHandler()
{
VLC->arth = this;
@ -108,6 +131,15 @@ CArtHandler::CArtHandler()
for (ui32 i = 3; i <= 6; i++)
bigArtifacts.insert(i);
}
CArtHandler::~CArtHandler()
{
for (std::vector<CArtifact>::iterator it = artifacts.begin(); it != artifacts.end(); ++it) {
delete it->constituents;
delete it->constituentOf;
}
}
void CArtHandler::loadArtifacts(bool onlyTxt)
{
std::vector<ui16> slots;
@ -145,6 +177,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
desc = desc.substr(1,desc.size()-2);
// Fill in information about combined artifacts. Should perhaps be moved to a config file?
nart.constituentOf = NULL;
switch (nart.id) {
case 129: // Angelic Alliance
nart.constituents = new std::vector<ui32>();
@ -219,6 +252,17 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
sortArts();
if(!onlyTxt)
addBonuses();
// Populate reverse mappings of combinational artifacts.
BOOST_FOREACH(CArtifact artifact, artifacts) {
if (artifact.constituents != NULL) {
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
if (artifacts[constituentID].constituentOf == NULL)
artifacts[constituentID].constituentOf = new std::vector<ui32>();
artifacts[constituentID].constituentOf->push_back(artifact.id);
}
}
}
}
int CArtHandler::convertMachineID(int id, bool creToArt )
@ -507,6 +551,7 @@ void CArtHandler::addBonuses()
giveArtBonus(134, HeroBonus::LEVEL_SPELL_IMMUNITY, 4);
//Titan's Thunder
// should also add a permanent spell book, somehow.
ART_ATTACK_AND_DEFENSE(135, +9);
ART_POWER_AND_KNOWLEDGE(135, +8);
giveArtBonus(135, HeroBonus::SPELL, 3, 57);
@ -612,7 +657,6 @@ void CArtHandler::unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID)
}
}
}
}
}
}

View File

@ -27,17 +27,19 @@ public:
const std::string &Description() const; //getter
bool isBig () const;
bool fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slot) const;
bool canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 artifactID) const;
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
std::vector<ui32> * constituentOf; // Reverse map of constituents.
EartClass aClass;
ui32 id;
std::list<HeroBonus> bonuses; //bonuses given by artifact
template <typename Handler> void serialize(Handler &h, const int version)
{
h & name & description & price & possibleSlots & constituents & aClass & id & bonuses;
h & name & description & price & possibleSlots & constituents & constituentOf & aClass & id & bonuses;
}
};
@ -58,6 +60,7 @@ public:
void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID);
static int convertMachineID(int id, bool creToArt);
CArtHandler();
~CArtHandler();
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -1284,6 +1284,23 @@ struct ExchangeArtifacts : public CPackForServer
}
};
struct AssembleArtifacts : public CPackForServer
{
AssembleArtifacts(){};
AssembleArtifacts(si32 _heroID, ui16 _artifactSlot, bool _assemble, ui32 _assembleTo)
: heroID(_heroID), artifactSlot(_artifactSlot), assemble(_assemble), assembleTo(_assembleTo){};
si32 heroID;
ui16 artifactSlot;
bool assemble; // True to assemble artifact, false to disassemble.
ui32 assembleTo; // Artifact to assemble into.
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & heroID & artifactSlot & assemble & assembleTo;
}
};
struct BuyArtifact : public CPackForServer
{
BuyArtifact(){};

View File

@ -143,6 +143,7 @@ void registerTypes3(Serializer &s)
s.template registerType<UpgradeCreature>();
s.template registerType<GarrisonHeroSwap>();
s.template registerType<ExchangeArtifacts>();
s.template registerType<AssembleArtifacts>();
s.template registerType<BuyArtifact>();
s.template registerType<TradeOnMarketplace>();
s.template registerType<SetFormation>();

View File

@ -2625,6 +2625,85 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot,
return true;
}
/**
* Assembles or disassembles a combination artifact.
* @param heroID ID of hero holding the artifact(s).
* @param artifactSlot The worn slot ID of the combination- or constituent artifact.
* @param assemble True for assembly operation, false for disassembly.
* @param assembleTo If assemble is true, this represents the artifact ID of the combination
* artifact to assemble to. Otherwise it's not used.
*/
bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assemble, ui32 assembleTo)
{
if (artifactSlot < 0 || artifactSlot > 18) {
complain("Illegal artifact slot.");
return false;
}
CGHeroInstance *hero = gs->getHero(heroID);
const CArtifact *destArtifact = hero->getArt(artifactSlot);
SetHeroArtifacts sha;
sha.hid = heroID;
sha.artifacts = hero->artifacts;
sha.artifWorn = hero->artifWorn;
if (assemble) {
if (VLC->arth->artifacts.size() >= assembleTo) {
complain("Illegal artifact to assemble to.");
return false;
}
if (!destArtifact->canBeAssembledTo(hero->artifWorn, assembleTo)) {
complain("Artifact cannot be assembled.");
return false;
}
const CArtifact &artifact = VLC->arth->artifacts[assembleTo];
if (artifact.constituents == NULL) {
complain("Not a combinational artifact.");
return false;
}
bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
bool found = false;
for (std::map<ui16, ui32>::iterator it = sha.artifWorn.begin(); it != sha.artifWorn.end(); ++it) {
if (it->second == constituentID) {
if (!destConsumed && vstd::contains(artifact.possibleSlots, it->first)) {
it->second = assembleTo;
destConsumed = true;
} else {
it->second = 145;
}
found = true;
break;
}
}
if (!found) {
complain("Constituent missing.");
return false;
}
}
} else {
BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) {
const CArtifact &constituent = VLC->arth->artifacts[constituentID];
BOOST_REVERSE_FOREACH(ui16 slotID, constituent.possibleSlots) {
if (sha.artifWorn.find(slotID) != sha.artifWorn.end()) {
if (sha.artifWorn[slotID] == 145 || slotID == artifactSlot)
sha.artifWorn[slotID] = constituentID;
}
}
}
}
sendAndApply(&sha);
return true;
}
bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
{
CGHeroInstance *hero = gs->getHero(hid);

View File

@ -163,6 +163,7 @@ public:
bool buildBoat( ui32 objid );
bool setFormation( si32 hid, ui8 formation );
bool tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 );
bool assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assemble, ui32 assembleTo);
bool buyArtifact( ui32 hid, si32 aid );
bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
bool garrisonSwap(si32 tid);

View File

@ -98,6 +98,12 @@ bool ExchangeArtifacts::applyGh( CGameHandler *gh )
return gh->swapArtifacts(hid1,hid2,slot1,slot2);
}
bool AssembleArtifacts::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(heroID);
return gh->assembleArtifacts(heroID, artifactSlot, assemble, assembleTo);
}
bool BuyArtifact::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid);