Bladeren bron

Artifacts, updated map loading.

Michał W. Urbańczyk 15 jaren geleden
bovenliggende
commit
ebb9c84da9
9 gewijzigde bestanden met toevoegingen van 110 en 108 verwijderingen
  1. 1 1
      global.h
  2. 7 1
      lib/CArtHandler.cpp
  3. 1 0
      lib/CArtHandler.h
  4. 30 11
      lib/CObjectHandler.cpp
  5. 3 0
      lib/CObjectHandler.h
  6. 2 1
      lib/NetPacksLib.cpp
  7. 61 93
      lib/map.cpp
  8. 4 0
      lib/map.h
  9. 1 1
      server/CGameHandler.cpp

+ 1 - 1
global.h

@@ -151,7 +151,7 @@ namespace Arts
 		AFTER_LAST
 	};
 	const ui16 BACKPACK_START = 19;
-	const int LOCK_ID = 145;
+	const int ID_CATAPULT = 3, ID_LOCK = 145;
 }
 
 enum EAlignment

+ 7 - 1
lib/CArtHandler.cpp

@@ -875,6 +875,12 @@ CArtifactInstance::CArtifactInstance( CArtifact *Art)
 
 }
 
+CArtifactInstance::CArtifactInstance(int aid)
+{
+	init();
+	setType(VLC->arth->artifacts[aid]);
+}
+
 void CArtifactInstance::setType( CArtifact *Art )
 {
 	artType = Art;
@@ -947,7 +953,7 @@ void CArtifactInstance::putAt(CGHeroInstance *h, ui16 slot)
 
 	ArtSlotInfo &asi = slot < Arts::BACKPACK_START 
 						? h->artifactsWorn[slot]
-						: *h->artifactsInBackpack.insert(h->artifactsInBackpack.begin() + slot - Arts::BACKPACK_START, ArtSlotInfo());
+						: *h->artifactsInBackpack.insert(h->artifactsInBackpack.begin() + (slot - Arts::BACKPACK_START), ArtSlotInfo());
 
 	asi.artifact = this;
 	asi.locked = false;

+ 1 - 0
lib/CArtHandler.h

@@ -69,6 +69,7 @@ public:
 
 	CArtifactInstance();
 	CArtifactInstance(CArtifact *Art);
+	CArtifactInstance(int aid);
 
 	std::string nodeName() const OVERRIDE;
 	void setType(CArtifact *Art);

+ 30 - 11
lib/CObjectHandler.cpp

@@ -790,12 +790,12 @@ void CGHeroInstance::initHero()
 	else //remove placeholder
 		spells -= 0xffffffff;
 
-	if(!vstd::contains(artifWorn, 16) && type->startingSpell >= 0) //no catapult means we haven't read pre-existant set
-	{
-		VLC->arth->equipArtifact(artifWorn, 17, VLC->arth->artifacts[0]); //give spellbook
-	}
-	VLC->arth->equipArtifact(artifWorn, 16, VLC->arth->artifacts[3]); //everyone has a catapult
+	if(!getArt(Arts::MACH4) && type->startingSpell >= 0) //no catapult means we haven't read pre-existant set -> use default rules for spellbook
+		putArtifact(Arts::SPELLBOOK, new CArtifactInstance(0));
 
+	if(!getArt(Arts::MACH4))
+		putArtifact(Arts::MACH4, new CArtifactInstance(3)); //everyone has a catapult
+	
 	if(portrait < 0 || portrait == 255)
 		portrait = subID;
 	if(!hasBonus(Selector::sourceType(Bonus::HERO_BASE_SKILL)))
@@ -861,18 +861,26 @@ void CGHeroInstance::initArmy(CCreatureSet *dst /*= NULL*/)
 		if(creID>=145 && creID<=149) //war machine
 		{
 			warMachinesGiven++;
+			if(dst != this)
+				continue;
+
+			int slot = -1, aid = -1;
 			switch (creID)
 			{
 			case 145: //catapult
-				VLC->arth->equipArtifact(artifWorn, 16, VLC->arth->artifacts[3]);
+				slot = Arts::MACH4;
+				aid = 3;
 				break;
 			default:
-				VLC->arth->equipArtifact(
-					artifWorn,
-					9+CArtHandler::convertMachineID(creID,true),
-					  VLC->arth->artifacts[CArtHandler::convertMachineID(creID,true)]);
+				aid = CArtHandler::convertMachineID(creID,true);
+				slot = 9 + aid;
 				break;
 			}
+
+			if(!getArt(slot))
+				putArtifact(slot, new CArtifactInstance(aid));
+			else
+				tlog3 << "Hero " << name << " already has artifact at " << slot << ", ommiting giving " << aid << std::endl;
 		}
 		else
 			dst->putStack(stackNo-warMachinesGiven, new CStackInstance(creID, count));
@@ -1542,6 +1550,17 @@ std::string CGHeroInstance::nodeName() const
 	return "Hero " + name;
 }
 
+void CGHeroInstance::putArtifact(ui16 pos, CArtifactInstance *art)
+{
+	assert(!getArt(pos));
+	art->putAt(this, pos);
+}
+
+void CGHeroInstance::putInBackpack(CArtifactInstance *art)
+{
+	putArtifact(art->firstBackpackSlot(this), art);
+}
+
 void CGDwelling::initObj()
 {
 	switch(ID)
@@ -6982,4 +7001,4 @@ si32 CArtifactSet::getArtTypeId(ui16 pos) const
 CArtifactSet::~CArtifactSet()
 {
 
-}
+}

+ 3 - 0
lib/CObjectHandler.h

@@ -272,6 +272,7 @@ public:
 	bool isPositionFree(ui16 pos) const;
 	si32 getArtTypeId(ui16 pos) const;
 
+
 	virtual ~CArtifactSet();
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -407,6 +408,8 @@ public:
 	void initHero(); 
 	void initHero(int SUBID); 
 
+	void putArtifact(ui16 pos, CArtifactInstance *art);
+	void putInBackpack(CArtifactInstance *art);
 	void initExp();
 	void initArmy(CCreatureSet *dst = NULL);
 	void giveArtifact (ui32 aid);

+ 2 - 1
lib/NetPacksLib.cpp

@@ -699,7 +699,8 @@ DLL_EXPORT void RebalanceStacks::applyGs( CGameState *gs )
 DLL_EXPORT void PutArtifact::applyGs( CGameState *gs )
 {
 	assert(art->canBePutAt(al));
-	art->putAt(al.hero, al.slot);
+	al.hero->putArtifact(al.slot, art);
+	//art->putAt(al.hero, al.slot);
 }
 
 DLL_EXPORT void EraseArtifact::applyGs( CGameState *gs )

+ 61 - 93
lib/map.cpp

@@ -848,52 +848,7 @@ CGObjectInstance * Mapa::loadHero(const unsigned char * bufor, int &i)
 		readCreatureSet(nhi, bufor, i, 7, version > RoE);
 
 	nhi->formation =bufor[i]; ++i; //formation
-	bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts)
-	int artmask = version == RoE ? 0xff : 0xffff;
-	int artidlen = version == RoE ? 1 : 2;
-	if(artSet)
-	{
-		for(int pom=0;pom<16;pom++)
-		{
-			int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-			if(id != artmask)
-				VLC->arth->equipArtifact(nhi->artifWorn, pom, VLC->arth->artifacts[id]);
-		}
-		//misc5 art //17
-		if(version>=SoD)
-		{
-			int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-			if(id!=artmask)
-				VLC->arth->equipArtifact(nhi->artifWorn, 16, VLC->arth->artifacts[id]);
-			else
-				VLC->arth->equipArtifact(nhi->artifWorn, 16, VLC->arth->artifacts[3]); //catapult by default
-		}
-		//spellbook
-		int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-		if(id!=artmask)
-			VLC->arth->equipArtifact(nhi->artifWorn, 17, VLC->arth->artifacts[id]);
-		//19 //???what is that? gap in file or what? - it's probably fifth slot..
-		if(version>RoE)
-		{
-			id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-			if(id!=artmask)
-				VLC->arth->equipArtifact(nhi->artifWorn, 18, VLC->arth->artifacts[id]);
-		}
-		else
-			i+=1;
-		//bag artifacts //20
-		int amount = readNormalNr(bufor,i, 2); i+=2; //number of artifacts in hero's bag
-		if(amount > 0)
-		{
-			for(int ss = 0; ss < amount; ++ss)
-			{
-				id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-				if(id != artmask)
-					nhi->giveArtifact(id);
-			}
-		}
-	} //artifacts
-
+	loadArtifactsOfHero(bufor, i, nhi);
 	nhi->patrol.patrolRadious = readNormalNr(bufor,i, 1); ++i;
 	if(nhi->patrol.patrolRadious == 0xff)
 		nhi->patrol.patrolling = false;
@@ -1089,50 +1044,9 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
 						cgh->secSkills[yy].second = readNormalNr(bufor,i, 1); ++i;
 					}
 				}
-				bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts)
-				int artmask = version == RoE ? 0xff : 0xffff;
-				int artidlen = version == RoE ? 1 : 2;
-				if(artSet)
-				{
-					for(int pom=0;pom<16;pom++)
-					{
-						int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-						if(id!=artmask)
-							VLC->arth->equipArtifact(cgh->artifWorn, pom, VLC->arth->artifacts[id]);
-					}
-					//misc5 art //17
-					if(version>=SoD)
-					{
-						i+=2;
-						//int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-						//if(id!=artmask)
-						//	spec->artifWorn[16] = id;
-					}
-					//spellbook
-					int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-					if(id!=artmask)
-						VLC->arth->equipArtifact(cgh->artifWorn, 17, VLC->arth->artifacts[id]);
-					//19 //???what is that? gap in file or what? - it's probably fifth slot..
-					if(version>RoE)
-					{
-						id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-						if(id!=artmask)
-							VLC->arth->equipArtifact(cgh->artifWorn, 18, VLC->arth->artifacts[id]);
-					}
-					else
-						i+=1;
-					//bag artifacts //20
-					int amount = readNormalNr(bufor,i, 2); i+=2; //number of artifacts in hero's bag
-					if(amount>0)
-					{
-						for(int ss=0; ss<amount; ++ss)
-						{
-							id = readNormalNr(bufor,i, artidlen); i+=artidlen;
-							if(id!=artmask)
-								cgh->giveArtifact(id);
-						}
-					}
-				} //artifacts
+
+				loadArtifactsOfHero(bufor, i, cgh);
+
 				if(readChar(bufor,i))//customBio
 					cgh->biography = readString(bufor,i);
 				int sex = bufor[i++]; // 0xFF is default, 00 male, 01 female    //FIXME:unused?
@@ -1578,14 +1492,13 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				}
 				else if(art->ID == 5) //specific artifact
 				{
-					innerArt = new CArtifactInstance(VLC->arth->artifacts[art->subID]);
+					innerArt = createArt(art->subID);
 				}
 				else
 				{
-					innerArt = new CArtifactInstance();
+					innerArt = createArt(-1);
 				}
 				art->storedArtifact = innerArt;
-				addNewArtifactInstance(innerArt);
 				break;
 			}
 		case 76: case 79: //random resource; resource
@@ -2116,6 +2029,61 @@ void Mapa::addNewArtifactInstance( CArtifactInstance *art )
 	artInstances.push_back(art);
 }
 
+bool Mapa::loadArtifactToSlot(CGHeroInstance *h, int slot, const unsigned char * bufor, int &i)
+{
+	const int artmask = version == RoE ? 0xff : 0xffff;
+	const int artidlen = version == RoE ? 1 : 2;
+
+	int aid = readNormalNr(bufor,i, artidlen); i+=artidlen;
+	bool isArt  =  aid != artmask;
+	if(isArt)
+		h->putArtifact(slot, createArt(aid));
+
+	return isArt;
+}
+
+void Mapa::loadArtifactsOfHero(const unsigned char * bufor, int & i, CGHeroInstance * nhi)
+{
+	bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts)
+	if(artSet)
+	{
+		for(int pom=0;pom<16;pom++)
+			loadArtifactToSlot(nhi, pom, bufor, i);
+
+		//misc5 art //17
+		if(version >= SoD)
+		{
+			if(!loadArtifactToSlot(nhi, Arts::MACH4, bufor, i))
+				nhi->putArtifact(Arts::MACH4, createArt(Arts::ID_CATAPULT)); //catapult by default
+		}
+
+		loadArtifactToSlot(nhi, Arts::SPELLBOOK, bufor, i);
+
+		//19 //???what is that? gap in file or what? - it's probably fifth slot..
+		if(version > RoE)
+			loadArtifactToSlot(nhi, Arts::MISC5, bufor, i);
+		else
+			i+=1;
+
+		//bag artifacts //20
+		int amount = readNormalNr(bufor,i, 2); i+=2; //number of artifacts in hero's bag
+		for(int ss = 0; ss < amount; ++ss)
+			loadArtifactToSlot(nhi, Arts::BACKPACK_START + ss, bufor, i);
+	} //artifacts
+}
+
+CArtifactInstance * Mapa::createArt(int aid)
+{
+	CArtifactInstance *a = NULL;
+	if(aid >= 0)
+		a = new CArtifactInstance(aid);
+	else
+		a = new CArtifactInstance();
+
+	this->addNewArtifactInstance(a);
+	return a;
+}
+
 LossCondition::LossCondition()
 {
 	obj = NULL;

+ 4 - 0
lib/map.h

@@ -297,9 +297,13 @@ struct DLL_EXPORT Mapa : public CMapHeader
 	void readHeader( const unsigned char * bufor, int &i);
 	void readRumors( const unsigned char * bufor, int &i);
 	CGObjectInstance *loadHero(const unsigned char * bufor, int &i);
+	void loadArtifactsOfHero(const unsigned char * bufor, int & i, CGHeroInstance * nhi);
+	bool loadArtifactToSlot(CGHeroInstance *h, int slot, const unsigned char * bufor, int &i);
 	void loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int &i, int subid);
 	int loadSeerHut( const unsigned char * bufor, int i, CGObjectInstance *& nobj);
 
+	CArtifactInstance *createArt(int aid);
+
 	void checkForObjectives();
 	void addNewArtifactInstance(CArtifactInstance *art);
 	void addBlockVisTiles(CGObjectInstance * obj);

+ 1 - 1
server/CGameHandler.cpp

@@ -2489,7 +2489,7 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
 		&& srcArtifact && !srcArtifact->canBePutAt(dst))
 		COMPLAIN_RET("Cannot swap artifacts!");
 
-	if ((srcArtifact && srcArtifact->artType->id == Arts::LOCK_ID) || (destArtifact && destArtifact->artType->id == Arts::LOCK_ID)) 
+	if ((srcArtifact && srcArtifact->artType->id == Arts::ID_LOCK) || (destArtifact && destArtifact->artType->id == Arts::ID_LOCK)) 
 		COMPLAIN_RET("Cannot move artifact locks.");
 
 	if (destSlot >= Arts::BACKPACK_START && srcArtifact->artType->isBig())