浏览代码

Fixed desync problem with Creature Banks and some other glitches.
The game is still unstable though. Please let me know if your game tends to crash when starting new map.

DjWarmonger 16 年之前
父节点
当前提交
af0cfe13a4
共有 4 个文件被更改,包括 61 次插入53 次删除
  1. 54 46
      hch/CObjectHandler.cpp
  2. 5 5
      hch/CObjectHandler.h
  3. 1 1
      int3.h
  4. 1 1
      server/CGameHandler.cpp

+ 54 - 46
hch/CObjectHandler.cpp

@@ -3718,7 +3718,6 @@ void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
 
 
 void CBank::initObj()
 void CBank::initObj()
 {
 {
-	index = 0;
 	switch (ID) //find apriopriate key
 	switch (ID) //find apriopriate key
 	{
 	{
 		case 16: //bank
 		case 16: //bank
@@ -3735,44 +3734,47 @@ void CBank::initObj()
 	bc = NULL;
 	bc = NULL;
 	daycounter = 0;
 	daycounter = 0;
 	multiplier = 1;
 	multiplier = 1;
-	//reset();
 }
 }
-void CBank::reset()
+void CBank::reset(ui16 var1, ui16 var2) //prevents desync
 {
 {
-	int val1 = ran()%100;
 	int chance = 0;
 	int chance = 0;
 	for (ui8 i = 0; i < VLC->objh->banksInfo[index].size(); i++)
 	for (ui8 i = 0; i < VLC->objh->banksInfo[index].size(); i++)
 	{	
 	{	
-		if (val1 < (chance += VLC->objh->banksInfo[index][i].chance))
+		if (var1 < (chance += VLC->objh->banksInfo[index][i].chance))
+		{
  			bc = &VLC->objh->banksInfo[index][i];
  			bc = &VLC->objh->banksInfo[index][i];
+			break;
+		}
 	}
 	}
 	artifacts.clear();
 	artifacts.clear();
-	std::vector<CArtifact*> arts; 
-	for (ui8 i = 1; i <= 4; i++)
+	for (ui8 i = 0; i <= 3; i++)
 	{	
 	{	
-		for (ui8 n = 1; n <= bc->artifacts[i - 1]; n++)
+		std::vector<CArtifact*> arts; //to avoid addition of different tiers
+		for (ui8 n = 0; n < bc->artifacts[i]; n++)
 		{
 		{
 			switch (i)
 			switch (i)
 			{
 			{
-				case 1:
+				case 0:
 					cb->getAllowed (arts, CArtifact::ART_TREASURE);
 					cb->getAllowed (arts, CArtifact::ART_TREASURE);
 					break;
 					break;
-				case 2:
+				case 1:
 					cb->getAllowed (arts, CArtifact::ART_MINOR);
 					cb->getAllowed (arts, CArtifact::ART_MINOR);
 					break;
 					break;
-				case 3:
+				case 2:
 					cb->getAllowed (arts, CArtifact::ART_MAJOR);
 					cb->getAllowed (arts, CArtifact::ART_MAJOR);
 					break;
 					break;
-				case 4:
+				case 3:
 					cb->getAllowed (arts, CArtifact::ART_RELIC);
 					cb->getAllowed (arts, CArtifact::ART_RELIC);
 					break;
 					break;
 			}
 			}
-			artifacts.push_back (arts[ran() % arts.size()]->id);
+			artifacts.push_back (arts[var2 % arts.size()]->id);
+			var2 *= (var1 + n * i); //almost like random
 		}
 		}
 	}
 	}
 
 
 }
 }
 void CBank::setPropertyDer (ui8 what, ui32 val)
 void CBank::setPropertyDer (ui8 what, ui32 val)
+/// random values are passed as arguments and processed identically on all clients
 {
 {
 	switch (what)
 	switch (what)
 	{
 	{
@@ -3782,14 +3784,14 @@ void CBank::setPropertyDer (ui8 what, ui32 val)
 			else
 			else
 				daycounter++;
 				daycounter++;
 			break;
 			break;
-		case 12: //multiplier
+		case 12: //multiplier, in percent
 			multiplier = ((float)val)/100;
 			multiplier = ((float)val)/100;
 			break;
 			break;
 		case 13: //bank preset
 		case 13: //bank preset
 			bc = &VLC->objh->banksInfo[index][val];
 			bc = &VLC->objh->banksInfo[index][val];
 			break;
 			break;
 		case 14:
 		case 14:
-			reset();
+			reset (val%100, val);
 			break;
 			break;
 		case 15:
 		case 15:
 			bc = NULL;
 			bc = NULL;
@@ -3797,6 +3799,31 @@ void CBank::setPropertyDer (ui8 what, ui32 val)
 		case 16:
 		case 16:
 			artifacts.clear();
 			artifacts.clear();
 			break;
 			break;
+		case 17: //set ArmedInstance army
+			int upgraded = 0;
+			if (val%100 < bc->upgradeChance) //once again anti-desync
+				upgraded = 1;
+			switch (bc->guards.size())
+			{
+				case 1:
+					for	(int i = 0; i <= 4; i++)
+						army.setCreature (i, bc->guards[0].first + upgraded, bc->guards[0].second  / 5 );
+					break;
+				case 4:
+				{
+					std::vector< std::pair <ui16, ui32> >::const_iterator it;
+					for (it = bc->guards.begin(); it != bc->guards.end(); it++)
+					{
+						int n = army.slots.size(); //debug
+						army.setCreature (n, it->first, it->second);
+					}
+				}
+					break;
+				default:
+					tlog1 << "Error: Unexpected army data: " << bc->guards.size() <<" items found";
+					return;
+			}
+			break;
 	}
 	}
 }
 }
 
 
@@ -3806,15 +3833,15 @@ void CBank::newTurn() const
 	{
 	{
 		if (daycounter >= 28 || cb->getDate(0) == 1)
 		if (daycounter >= 28 || cb->getDate(0) == 1)
 		{
 		{
-			cb->setObjProperty (id,11,0); //daycounter 0
-			cb->setObjProperty (id,14,0); //reset
+			cb->setObjProperty (id, 11, 0); //daycounter 0
+			cb->setObjProperty (id, 14, ran()); //reset
 			if (ID == 24 && cb->getDate(0) > 1)
 			if (ID == 24 && cb->getDate(0) > 1)
 			{
 			{
-				cb->setObjProperty (id,16,0);; //derelict ships are usable only once
+				cb->setObjProperty (id, 16, 0);; //derelict ships are usable only once
 			}
 			}
 		}
 		}
 		else
 		else
-			cb->setObjProperty (id,11,1); //daycounter++
+			cb->setObjProperty (id, 11, 1); //daycounter++
 	}
 	}
 }
 }
 void CBank::onHeroVisit (const CGHeroInstance * h) const
 void CBank::onHeroVisit (const CGHeroInstance * h) const
@@ -3876,27 +3903,8 @@ void CBank::fightGuards (const CGHeroInstance * h, ui32 accept) const
 {
 {
 	if (accept)
 	if (accept)
 	{
 	{
-		int upgraded = 0;
-		if (ran()%100 < bc->upgradeChance) upgraded = 1;
-		CCreatureSet ourArmy;
-		switch (bc->guards.size())
-		{
-			case 1:
-				for	(int i = 1; i <= 5; i++)
-					ourArmy.setCreature (i, bc->guards[0].first + upgraded, bc->guards[0].second  / 5 );
-				break;
-			case 4:
-			{
-				std::vector< std::pair <ui16, ui32> >::const_iterator it;
-				for (it = bc->guards.begin(); it != bc->guards.end(); it++)
-					ourArmy.setCreature (ourArmy.slots.size() + 1, it->first, it->second );
-			}
-				break;
-			default:
-				tlog1 << "Error: Unexpected army data: " << bc->guards.size() <<" items found";
-				return;
-		}
-	cb->startBattleI (h, this, true, boost::bind (&CBank::endBattle, this, h, _1));
+		cb->setObjProperty (id, 17, ran()); //get army
+		cb->startBattleI (h, this, true, boost::bind (&CBank::endBattle, this, h, _1));
 	}
 	}
 }
 }
 void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) const
 void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) const
@@ -3936,19 +3944,19 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 				break;
 				break;
 		}
 		}
 		iw.text.addTxt (MetaString::ADVOB_TXT, textID);
 		iw.text.addTxt (MetaString::ADVOB_TXT, textID);
-		iw.player = cb->getCurrentPlayer();
+		iw.player = h->getOwner();
 		//grant resources
 		//grant resources
-		for (int it = 0; it < bc->resources.size(); ++it)
+		for (int it = 0; it < bc->resources.size(); it++)
 		{					
 		{					
 			iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
 			iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
-			cb->giveResource (cb->getCurrentPlayer(), it, bc->resources[it]);
+			cb->giveResource (h->getOwner(), it, bc->resources[it]);
 		}
 		}
 		//grant artifacts
 		//grant artifacts
-		for (std::vector<si32>::const_iterator it = artifacts.begin(); it != artifacts.end(); it++)
+		for (std::vector<ui32>::const_iterator it = artifacts.begin(); it != artifacts.end(); it++)
 		{
 		{
 			iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 			iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
 			iw.text.addReplacement (MetaString::ART_NAMES, *it);
 			iw.text.addReplacement (MetaString::ART_NAMES, *it);
-			cb->giveHeroArtifact (*it, cb->getSelectedHero() ,-2);
+			cb->giveHeroArtifact (*it, h->id ,-2);
 		}
 		}
 		//grant creatures
 		//grant creatures
 		CCreatureSet ourArmy;
 		CCreatureSet ourArmy;
@@ -3961,7 +3969,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
 			cb->setObjProperty (id, 15, 0); //bc = NULL
 			cb->setObjProperty (id, 15, 0); //bc = NULL
 	}
 	}
 	else
 	else
-		cb->setObjProperty (id, 14, 0); //reset
+		cb->setObjProperty (id, 14, ran()); //reset
 }
 }
 
 
 void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8
 void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8

+ 5 - 5
hch/CObjectHandler.h

@@ -369,7 +369,7 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
 		h & static_cast<CGObjectInstance&>(*this);
 		h & static_cast<CGObjectInstance&>(*this);
-		h & visitors & town;
+		h & visitors;
 	}
 	}
 };
 };
 class DLL_EXPORT CGTownInstance : public CGDwelling, public IShipyard
 class DLL_EXPORT CGTownInstance : public CGDwelling, public IShipyard
@@ -872,13 +872,13 @@ class DLL_EXPORT CBank : public CArmedInstance
 	public:
 	public:
 	int index; //banks have unusal numbering - see ZCRBANK.txt and initObj()
 	int index; //banks have unusal numbering - see ZCRBANK.txt and initObj()
 	BankConfig *bc;
 	BankConfig *bc;
-	float multiplier; //for improved banks script, in percent
-	std::vector<si32> artifacts; //fixed and deterministic
+	float multiplier; //for improved banks script
+	std::vector<ui32> artifacts; //fixed and deterministic
 	ui32 daycounter;
 	ui32 daycounter;
 
 
 	void initObj();
 	void initObj();
 	void setPropertyDer (ui8 what, ui32 val);
 	void setPropertyDer (ui8 what, ui32 val);
-	void reset();
+	void reset(ui16 var1, ui16 var2);
 	void newTurn() const;
 	void newTurn() const;
 	void onHeroVisit (const CGHeroInstance * h) const;
 	void onHeroVisit (const CGHeroInstance * h) const;
 	void fightGuards (const CGHeroInstance *h, ui32 accept) const;
 	void fightGuards (const CGHeroInstance *h, ui32 accept) const;
@@ -935,7 +935,7 @@ struct BankConfig
 	ui8 level; //1 - 4, how hard the battle will be
 	ui8 level; //1 - 4, how hard the battle will be
 	ui8 chance; //chance for this level being chosen
 	ui8 chance; //chance for this level being chosen
 	ui8 upgradeChance; //chance for creatures to be in upgraded versions
 	ui8 upgradeChance; //chance for creatures to be in upgraded versions
-	std::vector< std::pair <ui16, ui32> > guards; //creature ID -> amount
+	std::vector< std::pair <ui16, ui32> > guards; //creature ID, amount
 	ui32 combatValue; //how hard are guards of this level
 	ui32 combatValue; //how hard are guards of this level
 	std::vector<si32> resources; //resources given in case of victory
 	std::vector<si32> resources; //resources given in case of victory
 	std::vector< std::pair <ui16, ui32> > creatures; //creatures granted in case of victory
 	std::vector< std::pair <ui16, ui32> > creatures; //creatures granted in case of victory

+ 1 - 1
int3.h

@@ -20,7 +20,7 @@ class CCreatureSet //seven combined creatures
 public:
 public:
 	std::map<si32, std::pair<ui32,si32> > slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
 	std::map<si32, std::pair<ui32,si32> > slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
 	bool formation; //false - wide, true - tight
 	bool formation; //false - wide, true - tight
-	bool setCreature (si32 slot, ui32 type, si32 quantity) //slots 1 to 7
+	bool setCreature (si32 slot, ui32 type, si32 quantity) //slots 0 to 6
 	{
 	{
 		slots[slot] = std::pair<ui32, si32>(type, quantity);  //brutal force
 		slots[slot] = std::pair<ui32, si32>(type, quantity);  //brutal force
 		if (slots.size() > 7) return false;
 		if (slots.size() > 7) return false;

+ 1 - 1
server/CGameHandler.cpp

@@ -938,7 +938,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
 	{
 	{
 		int pos;
 		int pos;
 		if(creatureBank)
 		if(creatureBank)
-			pos = defenderCreBank[army1.slots.size()-1][k];
+			pos = defenderCreBank[army2.slots.size()-1][k];
 		else if(army2.formation)
 		else if(army2.formation)
 			pos = defenderTight[army2.slots.size()-1][k];
 			pos = defenderTight[army2.slots.size()-1][k];
 		else
 		else