diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp new file mode 100644 index 000000000..dc00df71f --- /dev/null +++ b/lib/CCreatureSet.cpp @@ -0,0 +1,175 @@ +#define VCMI_DLL +#include "CCreatureSet.h" +#include "../hch/CCreatureHandler.h" +#include "VCMI_Lib.h" +#include + +const CStackInstance CCreatureSet::operator[](TSlot slot) const +{ + TSlots::const_iterator i = slots.find(slot); + if (i != slots.end()) + return i->second; + else + throw std::string("That slot is empty!"); +} + +const CCreature* CCreatureSet::getCreature(TSlot slot) const /*workaround of map issue */ +{ + TSlots::const_iterator i = slots.find(slot); + if (i != slots.end()) + return i->second.type; + else + return NULL; +} + +bool CCreatureSet::setCreature(TSlot slot, TCreature type, TQuantity quantity) /*slots 0 to 6 */ +{ + slots[slot] = CStackInstance(type, quantity); //brutal force + if (quantity == 0) + slots.erase(slot); + + if (slots.size() > 7) + return false; + else + return true; +} + +TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const /*returns -1 if no slot available */ +{ + for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) + { + if(i->second.type->idNumber == creature) + { + return i->first; //if there is already such creature we return its slot id + } + } + for(ui32 i=0; isecond.count; + else + return 0; //TODO? consider issuing a warning +} + +bool CCreatureSet::mergableStacks(std::pair &out, TSlot preferable /*= -1*/) /*looks for two same stacks, returns slot positions */ +{ + //try to match creature to our preferred stack + if(preferable >= 0 && vstd::contains(slots, preferable)) + { + const CCreature *cr = slots[preferable].type; + for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j) + { + if(cr == j->second.type && j->first != preferable) + { + out.first = preferable; + out.second = j->first; + return true; + } + } + } + + for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) + { + for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j) + { + if(i->second.type == j->second.type && i->first != j->first) + { + out.first = i->first; + out.second = j->first; + return true; + } + } + } + return false; +} + +void CCreatureSet::sweep() +{ + for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i) + { + if(!i->second.count) + { + slots.erase(i); + sweep(); + break; + } + } +} + +void CCreatureSet::addToSlot(TSlot slot, TCreature cre, TQuantity count) +{ + assert(slot >= 0); + const CCreature *c = &VLC->creh->creatures[cre]; + assert(!vstd::contains(slots, slot) || slots[slot].type == c); //that slot was empty or contained same type creature + slots[slot].type = c; + slots[slot].count += count; +} + +void CCreatureSet::addToSlot(TSlot slot, const CStackInstance &stack) +{ + addToSlot(slot, stack.type->idNumber, stack.count); +} + +bool CCreatureSet::validTypes(bool allowUnrandomized /*= false*/) const +{ + for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) + { + bool isRand = (i->second.idRand != -1); + if(!isRand) + { + assert(i->second.type); + assert(i->second.type == &VLC->creh->creatures[i->second.type->idNumber]); + } + else + assert(allowUnrandomized); + } + return true; +} + +CStackInstance::CStackInstance() +{ + init(); +} + +CStackInstance::CStackInstance(TCreature id, TQuantity Count) +{ + init(); + setType(id); + count = Count; +} + +CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count) +{ + init(); + type = cre; + count = Count; +} + +void CStackInstance::init() +{ + experience = 0; + count = 0; + type = NULL; + idRand = -1; +} + +int CStackInstance::getQuantityID() const +{ + return CCreature::getQuantityID(count); +} + +void CStackInstance::setType(int creID) +{ + type = &VLC->creh->creatures[creID]; +} \ No newline at end of file diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h new file mode 100644 index 000000000..6a37791f0 --- /dev/null +++ b/lib/CCreatureSet.h @@ -0,0 +1,70 @@ +#ifndef __CCREATURESET_H__ +#define __CCREATURESET_H__ + +#include "../global.h" +#include + +class CCreature; +class CGHeroInstance; + +//a few typedefs for CCreatureSet +typedef si32 TSlot; +typedef si32 TQuantity; +typedef ui32 TCreature; //creature id + + +class DLL_EXPORT CStackInstance +{ +public: + int idRand; //hlp variable used during loading game -> "id" placeholder for randomization + const CCreature *type; + TQuantity count; + ui32 experience; //TODO: handle + //TODO: stack artifacts + + template void serialize(Handler &h, const int version) + { + h/* & owner*/ & type & count & experience; + } + + int getQuantityID() const; + void init(); + CStackInstance(); + CStackInstance(TCreature id, TQuantity count); + CStackInstance(const CCreature *cre, TQuantity count); + void setType(int creID); +}; + + +typedef std::map TSlots; + +class DLL_EXPORT CCreatureSet //seven combined creatures +{ +public: + TSlots slots; //slots[slot_id]=> pair(creature_id,creature_quantity) + ui8 formation; //false - wide, true - tight + + const CStackInstance operator[](TSlot slot) const; + + void addToSlot(TSlot slot, TCreature cre, TQuantity count); //Adds stack to slot. Slot must be empty or with same type creature + void addToSlot(TSlot slot, const CStackInstance &stack); //Adds stack to slot. Slot must be empty or with same type creature + + const CCreature* getCreature(TSlot slot) const; //workaround of map issue; + int getAmount (TSlot slot) const; + bool setCreature (TSlot slot, TCreature type, TQuantity quantity); //slots 0 to 6 + TSlot getSlotFor(TCreature creature, ui32 slotsAmount=7) const; //returns -1 if no slot available + bool mergableStacks(std::pair &out, TSlot preferable = -1); //looks for two same stacks, returns slot positions; + bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly + + template void serialize(Handler &h, const int version) + { + h & slots & formation; + } + operator bool() const + { + return slots.size() > 0; + } + void sweep(); +}; + +#endif // __CCREATURESET_H__ diff --git a/lib/VCMI_lib.vcproj b/lib/VCMI_lib.vcproj index a43f69cfd..e44ed9e3e 100644 --- a/lib/VCMI_lib.vcproj +++ b/lib/VCMI_lib.vcproj @@ -376,6 +376,10 @@ RelativePath="..\hch\CCreatureHandler.h" > + + @@ -453,6 +457,10 @@ > + +