Przeglądaj źródła

Fix regression for week-visitable objects

Piotr Wójcik 9 lat temu
rodzic
commit
bb890098df

+ 12 - 1
lib/NetPacksLib.cpp

@@ -323,7 +323,18 @@ DLL_LINKAGE void ChangeObjectVisitors::applyGs( CGameState *gs )
 			break;
 		case VISITOR_CLEAR:
 			for (CGHeroInstance * hero : gs->map->allHeroes)
-				hero->visitedObjects.erase(object); // remove visit info from all heroes, including those that are not present on map
+			{
+				if (hero)
+				{
+					hero->visitedObjects.erase(object); // remove visit info from all heroes, including those that are not present on map
+				}
+			}
+
+			for(auto &elem : gs->players)
+			{
+				elem.second.visitedObjects.erase(object);
+			}
+
 			break;
 		case VISITOR_REMOVE:
 			gs->getHero(hero)->visitedObjects.erase(object);

+ 49 - 25
lib/mapObjects/CRewardableObject.cpp

@@ -1039,44 +1039,28 @@ void CGVisitableOPH::initObj(CRandomGenerator & rand)
 CGVisitableOPW::CGVisitableOPW()
 {
 	visitMode = VISIT_ONCE;
-	selectMode = SELECT_RANDOM;
 	resetDuration = 7;
 }
 
 void CGVisitableOPW::initObj(CRandomGenerator & rand)
 {
+	setRandomReward(rand);
+
 	switch (ID)
 	{
 	case Obj::MYSTICAL_GARDEN:
 		soundID = soundBase::experience;
 		onEmpty.addTxt(MetaString::ADVOB_TXT, 93);
-		info.resize(2);
-		info[0].reward.resources[Res::GEMS] = 5;
-		info[1].reward.resources[Res::GOLD] = 500;
 		info[0].message.addTxt(MetaString::ADVOB_TXT, 92);
-		info[1].message.addTxt(MetaString::ADVOB_TXT, 92);
 		break;
 	case Obj::WINDMILL:
 		soundID = soundBase::GENIE;
 		onEmpty.addTxt(MetaString::ADVOB_TXT, 169);
-		// 3-6 of any resource but wood and gold
-		for (int resID = Res::MERCURY; resID < Res::GOLD; resID++)
-		{
-			for (int val = 3; val <=6; val++)
-			{
-				CVisitInfo visit;
-				visit.reward.resources[resID] = val;
-				visit.message.addTxt(MetaString::ADVOB_TXT, 92);
-				info.push_back(visit);
-			}
-		}
+		info[0].message.addTxt(MetaString::ADVOB_TXT, 92);
 		break;
 	case Obj::WATER_WHEEL:
 		soundID = soundBase::GENIE;
 		onEmpty.addTxt(MetaString::ADVOB_TXT, 165);
-
-		info.resize(1);
-		info[0].reward.resources[Res::GOLD] = 500;
 		info[0].message.addTxt(MetaString::ADVOB_TXT, 164);
 		break;
 	}
@@ -1084,19 +1068,59 @@ void CGVisitableOPW::initObj(CRandomGenerator & rand)
 
 void CGVisitableOPW::setPropertyDer(ui8 what, ui32 val)
 {
-	if(ID == Obj::WATER_WHEEL && what == ObjProperty::REWARD_RESET)
+	if(what == ObjProperty::REWARD_RESET)
 	{
-		auto& reward = info[0].reward.resources[Res::GOLD];
-		if(info[0].numOfGrants == 0)
+		setRandomReward(cb->gameState()->getRandomGenerator());
+
+		if (ID == Obj::WATER_WHEEL)
 		{
-			reward = 1000;
+			auto& reward = info[0].reward.resources[Res::GOLD];
+			if(info[0].numOfGrants == 0)
+			{
+				reward = 1000;
+			}
+			else
+			{
+				reward = 500;
+			}
+		}
+
+		ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_CLEAR, id);
+		cb->sendAndApply(&cov); // that cause server hang
+	}
+
+	CRewardableObject::setPropertyDer(what, val);
+}
+
+void CGVisitableOPW::setRandomReward(CRandomGenerator &rand)
+{
+	switch (ID)
+	{
+	case Obj::MYSTICAL_GARDEN:
+		info.resize(1);
+		if (rand.nextInt(1) == 0)
+		{
+			info[0].reward.resources[Res::GEMS] = 5;
+			info[0].limiter.numOfGrants = 1;
 		}
 		else
 		{
-			reward = 500;
+			info[0].reward.resources[Res::GOLD] = 500;
+			info[0].limiter.numOfGrants = 1;
 		}
+		break;
+	case Obj::WINDMILL:
+		info.resize(1);
+		// 3-6 of any resource but wood and gold
+		info[0].reward.resources[rand.nextInt(Res::MERCURY, Res::GEMS)] = rand.nextInt(3, 6);
+		info[0].limiter.numOfGrants = 1;
+		break;
+	case Obj::WATER_WHEEL:
+		info.resize(1);
+		info[0].reward.resources[Res::GOLD] = 500;
+		info[0].limiter.numOfGrants = 1;
+		break;
 	}
-	CRewardableObject::setPropertyDer(what, val);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////

+ 1 - 0
lib/mapObjects/CRewardableObject.h

@@ -321,6 +321,7 @@ public:
 	CGVisitableOPW();
 
 	void setPropertyDer(ui8 what, ui32 val) override;
+	void setRandomReward(CRandomGenerator & rand);
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{