2
0
DjWarmonger 12 жил өмнө
parent
commit
d06b02638b

+ 0 - 1
client/CPlayerInterface.cpp

@@ -712,7 +712,6 @@ void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr)
 	for(auto & elem : bsr.stackIDs) //for each removed stack
 	{
 		battleInt->stackRemoved(elem);
-		//battleInt->stackRemoved(LOCPLINT->cb->battleGetStackByID(*it));
 	}
 }
 

+ 1 - 0
client/battle/CBattleInterface.cpp

@@ -1010,6 +1010,7 @@ void CBattleInterface::stackRemoved(int stackID)
 	delete creAnims[stackID];
 	creAnims.erase(stackID);
 	creDir.erase(stackID);
+	//FIXME: what if currently removed stack is active one (Sacrifice)?
 
 	redrawBackgroundWithHexes(activeStack);
 	queue->update();

+ 1 - 1
client/battle/CBattleInterface.h

@@ -145,7 +145,7 @@ private:
 	const CStack * mouseHoveredStack; // stack below mouse pointer, used for border animation
 	const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; nullptr of none
 	const CStack * selectedStack; //for Teleport / Sacrifice
-	void activateStack(); //sets activeStack to stackToActivate etc.
+	void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
 	std::vector<BattleHex> occupyableHexes, //hexes available for active stack
 		attackableHexes; //hexes attackable by active stack
     bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back

+ 79 - 2
lib/CObjectHandler.cpp

@@ -5333,6 +5333,61 @@ void CGBonusingObject::initObj()
 	}
 }
 
+void CGMagicSpring::setPropertyDer(ui8 what, ui32 val)
+{
+	CGVisitableOPW::setPropertyDer (what, val); //set visitable if applicable
+	if (what == ObjProperty::LEFT_VISITED)
+	{
+		if (visitedTile == RIGHT)
+			visited = true; //both field were used, object is not available this week
+		else
+			visitedTile = LEFT;
+	}
+	else if (what == ObjProperty::RIGHT_VISITED)
+	{
+		if (visitedTile == LEFT)
+			visited = true;
+		else
+			visitedTile = RIGHT;
+	}
+	else if (what == ObjProperty::LEFTRIGHT_CLEAR)
+		visitedTile = CLEAR;
+}
+std::vector<int3> CGMagicSpring::getVisitableOffsets() const
+{
+	std::vector <int3> visitableTiles;
+
+	for(int y = 0; y < 6; y++)
+		for (int x = 0; x < 8; x++) //starting from left
+			if((defInfo->visitMap[5-y] >> x) & 1)
+				visitableTiles.push_back (int3(x, y , 0));
+
+	return visitableTiles;
+}
+
+int3 CGMagicSpring::getVisitableOffset() const
+{
+	//FIXME: this also shoudl stop AI from passing through already visited spring, is that ok?
+	auto visitableTiles = getVisitableOffsets();
+
+	if (visitableTiles.size() < 2)
+	{
+		logGlobal->warnStream() << "Warning: Magic Spring should have at least two visitable offsets!";
+		return int3(-1,-1,-1);
+	}
+    if (visited)
+		return int3(-1,-1,-1);
+	else
+	{
+		if (visitedTile == RIGHT)
+			return visitableTiles[0]; //visit teh other one now
+		else if (visitedTile == LEFT)
+			return visitableTiles[1];
+		else
+			return visitableTiles[0]; //only left one?
+	}
+}
+
 void CGMagicSpring::onHeroVisit(const CGHeroInstance * h) const
 {
 	int messageID;
@@ -5344,17 +5399,39 @@ void CGMagicSpring::onHeroVisit(const CGHeroInstance * h) const
 		else
 		{
 			messageID = 74;
-			cb->setManaPoints (h->id, 2 * h->manaLimit());
-			cb->setObjProperty (id, ObjProperty::VISITED, true);
+			cb->setManaPoints (h->id, 2 * h->manaLimit());//TODO: mark left or right tile visited
+			if (visitedTile) //visitng the second tile
+				cb->setObjProperty (id, ObjProperty::VISITED, true);
+			else
+			{
+				auto visitableTiles = getVisitableOffsets();
+				assert (visitableTiles.size() >= 2);
+				if (h->getPosition() == pos - visitableTiles[0])
+					cb->setObjProperty (id, ObjProperty::LEFT_VISITED, true);
+				else if (h->getPosition() == pos - visitableTiles[1])
+					cb->setObjProperty (id, ObjProperty::RIGHT_VISITED, true);
+				else
+					logGlobal->warnStream() << "Warning: hero is not on any Magic Spring visitable offsets!";
+			}
 		}
 	}
 	else
 		messageID = 75;
 	showInfoDialog(h,messageID,soundBase::GENIE);
 }
+void CGMagicSpring::newTurn() const
+{
+	CGVisitableOPW::newTurn();
+	if (cb->getDate(Date::DAY_OF_WEEK) == 1)
+	{
+		cb->setObjProperty(id, ObjProperty::LEFTRIGHT_CLEAR, false);
+	}
+}
+
 
 const std::string & CGMagicSpring::getHoverText() const
 {
+	//TODO: change hover text depending on hovered tile
 	hoverName = VLC->generaltexth->names[ID] + " " + visitedTxt(visited);
 	return hoverName;
 }

+ 14 - 4
lib/CObjectHandler.h

@@ -193,8 +193,8 @@ public:
 	void setOwner(PlayerColor ow);
 	int getWidth() const; //returns width of object graphic in tiles
 	int getHeight() const; //returns height of object graphic in tiles
-	bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
-	int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos)
+	virtual bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
+	virtual int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos)
 	int3 visitablePos() const;
 	bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles)
 	bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles)
@@ -1036,7 +1036,7 @@ public:
 
 	bool wasVisited(PlayerColor player) const;
 	void onHeroVisit(const CGHeroInstance * h) const override;
-	void newTurn() const override;
+	virtual void newTurn() const override;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1079,14 +1079,24 @@ public:
 
 class DLL_LINKAGE CGMagicSpring : public CGVisitableOPW
 {///unfortunately, this one is quite different than others
+	enum EVisitedEntrance
+	{
+		CLEAR = 0, LEFT = 1, RIGHT
+	};
 public:
+	EVisitedEntrance visitedTile; //only one entrance was visited - there are two
+
+	std::vector<int3> getVisitableOffsets() const;
+	int3 getVisitableOffset() const override;
+	void setPropertyDer(ui8 what, ui32 val) override;
+	void newTurn() const override;
 	void onHeroVisit(const CGHeroInstance * h) const override;
 	const std::string & getHoverText() const override;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CGObjectInstance&>(*this);
-		h & visited;
+		h & visitedTile & visited;
 	}
 };
 

+ 1 - 1
lib/Connection.h

@@ -27,7 +27,7 @@
 #include "mapping/CCampaignHandler.h" //for CCampaignState
 #include "rmg/CMapGenerator.h" // for CMapGenOptions
 
-const ui32 version = 742;
+const ui32 version = 743;
 
 class CConnection;
 class CGObjectInstance;

+ 4 - 1
lib/NetPacks.h

@@ -1190,7 +1190,10 @@ namespace ObjProperty
 
 		//creature-bank specific
 		BANK_DAYCOUNTER, BANK_CLEAR_ARTIFACTS, BANK_ADD_ARTIFACT, BANK_MULTIPLIER, BANK_CONFIG_PRESET, 
-		BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET
+		BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET,
+
+		//magic spring
+		LEFT_VISITED, RIGHT_VISITED, LEFTRIGHT_CLEAR
 	};
 }
 

+ 23 - 2
server/CGameHandler.cpp

@@ -4236,6 +4236,27 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
 				sendAndApply(&shr);
 			if (spellID == SpellID::SACRIFICE) //remove victim
 			{
+				if (selectedStack == gs->curB->activeStack)
+				//set another active stack than the one removed, or bad things will happen
+				//TODO: make that part of BattleStacksRemoved? what about client update?
+				{
+					//makeStackDoNothing(gs->curB->getStack (selectedStack));
+
+					BattleSetActiveStack sas;
+
+					//std::vector<const CStack *> hlp;
+					//battleGetStackQueue(hlp, 1, selectedStack); //next after this one
+
+					//if(hlp.size())
+					//{
+					//	sas.stack = hlp[0]->ID;
+					//}
+					//else
+					//	complain ("No new stack to activate!");
+					sas.stack = gs->curB->getNextStack()->ID; //why the hell next stack has same ID as current?
+					sendAndApply(&sas);
+
+				}
 				BattleStacksRemoved bsr;
 				bsr.stackIDs.insert (selectedStack); //somehow it works for teleport?
 				sendAndApply(&bsr);
@@ -4491,7 +4512,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 									ECastingMode::HERO_CASTING, nullptr, ba.selectedStack);
 
 				sendAndApply(&end_action);
-				if( !gs->curB->battleGetStackByID(gs->curB->activeStack, false)->alive() )
+				if( !gs->curB->battleGetStackByID(gs->curB->activeStack, true))
 				{
 					battleMadeAction.setn(true);
 				}
@@ -6052,7 +6073,7 @@ void CGameHandler::runBattle()
 						sendAndApply(&sas);
 						boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
 						battleMadeAction.data = false;
-						while (next->alive() &&
+						while (next->alive() && //next is invalid after sacrificing current stack :?
 							(!battleMadeAction.data  &&  !battleResult.get())) //active stack hasn't made its action and battle is still going
 							battleMadeAction.cond.wait(lock);
 					}