Selaa lähdekoodia

Cloned stack dissapear when killed.
Fixed #864

DjWarmonger 13 vuotta sitten
vanhempi
sitoutus
5c86d32903

+ 24 - 14
client/BattleInterface/CBattleInterface.cpp

@@ -946,18 +946,21 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 					{
 						if ((int)creatureSpellToCast > -1) //use randomized spell (Faerie Dragon), or only avaliable spell (Archangel)
 						{
-							const CSpell * spell =  CGI->spellh->spells[creatureSpellToCast];
-							if (curInt->cb->battleCanCastThisSpell(spell, BattleHex(myNumber)) == ESpellCastProblem::OK)
+							if (shere != sactive) //can't cast on itself
 							{
-								if ((!spell->isNegative() && ourStack) || (!spell->isPositive() && !ourStack))
+								const CSpell * spell =  CGI->spellh->spells[creatureSpellToCast];
+								if (curInt->cb->battleCanCastThisSpell(spell, BattleHex(myNumber)) == ESpellCastProblem::OK)
 								{
-									CCS->curh->changeGraphic(3, 0);
-									stackCastsSpell = true;
-									std::string buf = CGI->generaltexth->allTexts[27]; //cast %s on &s
-									boost::replace_first (buf, "%s", spell->name);
-									boost::replace_first (buf, "%s", shere->getName());
-									console->alterTxt = buf;
-									console->whoSetAlter = 0;
+									if ((!spell->isNegative() && ourStack) || (!spell->isPositive() && !ourStack))
+									{
+										CCS->curh->changeGraphic(3, 0);
+										stackCastsSpell = true;
+										std::string buf = CGI->generaltexth->allTexts[27]; //cast %s on &s
+										boost::replace_first (buf, "%s", spell->name);
+										boost::replace_first (buf, "%s", shere->getName());
+										console->alterTxt = buf;
+										console->whoSetAlter = 0;
+									}
 								}
 							}
 						}
@@ -1503,7 +1506,7 @@ void CBattleInterface::bConsoleDownf()
 
 void CBattleInterface::newStack(const CStack * stack)
 {
-	Point coords = CClickableHex::getXYUnitAnim(stack->position, stack->owner == attackingHeroInstance->tempOwner, stack, this);;
+	Point coords = CClickableHex::getXYUnitAnim(stack->position, stack->owner == attackingHeroInstance->tempOwner, stack, this);
 
 	if(stack->position < 0) //turret
 	{
@@ -1538,6 +1541,7 @@ void CBattleInterface::newStack(const CStack * stack)
 	creAnims[stack->ID]->setType(CCreatureAnim::HOLDING);
 	creAnims[stack->ID]->pos = Rect(coords.x, coords.y, creAnims[stack->ID]->fullWidth, creAnims[stack->ID]->fullHeight);
 	creDir[stack->ID] = stack->attackerOwned;
+	
 }
 
 void CBattleInterface::stackRemoved(int stackID)
@@ -1551,7 +1555,8 @@ void CBattleInterface::stackActivated(const CStack * stack) //TODO: check it all
 {
 	//givenCommand = NULL;
 	stackToActivate = stack;
-	if(pendingAnims.size() == 0)
+	waitForAnims();
+	//if(pendingAnims.size() == 0)
 		activateStack();
 }
 
@@ -1563,9 +1568,10 @@ void CBattleInterface::stackMoved(const CStack * stack, std::vector<BattleHex> d
 
 void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos)
 {
-	for(size_t h = 0; h < attackedInfos.size(); ++h)
+	for (size_t h = 0; h < attackedInfos.size(); ++h)
 	{
-		addNewAnim(new CDefenceAnimation(attackedInfos[h], this));
+		if (!attackedInfos[h].cloneKilled) //FIXME: play dead animation for cloned creature before it vanishes
+			addNewAnim(new CDefenceAnimation(attackedInfos[h], this));
 		if (attackedInfos[h].rebirth)
 		{
 			displayEffect(50, attackedInfos[h].defender->position); //TODO: play reverse death animation
@@ -1580,6 +1586,8 @@ void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attacked
 		killed += attackedInfos[h].killed;
 		damage += attackedInfos[h].dmg;
 	}
+	if (attackedInfos.front().cloneKilled) //FIXME: cloned stack is already removed
+		return;
 	if (targets > 1)
 		printConsoleAttacked(attackedInfos.front().defender, damage, killed, attackedInfos.front().attacker, true); //creatures perish
 	else
@@ -1589,6 +1597,8 @@ void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attacked
 	{
 		if (attackedInfos[h].rebirth)
 			creAnims[attackedInfos[h].defender->ID]->setType(CCreatureAnim::HOLDING);
+		if (attackedInfos[h].cloneKilled)
+			stackRemoved(attackedInfos[h].defender->ID);
 	}
 }
 

+ 1 - 0
client/BattleInterface/CBattleInterface.h

@@ -62,6 +62,7 @@ struct StackAttackedInfo
 	bool byShooting; //if true, stack has been attacked by shooting
 	bool killed; //if true, stack has been killed
 	bool rebirth; //if true, play rebirth animation after all
+	bool cloneKilled;
 };
 
 /// Struct for battle effect animation e.g. morale, prayer, armageddon, bless,...

+ 3 - 6
client/CPlayerInterface.cpp

@@ -640,10 +640,8 @@ void CPlayerInterface::battleNewStackAppeared(const CStack * stack)
 	{ //another local interface should do this
 		return;
 	}
-
-	//changing necessary things in battle interface
+	//boost::unique_lock<boost::recursive_mutex> un(*pim);
 	battleInt->newStack(stack);
-	//battleInt->addNewAnim(new CDummyAnim(battleInt, 2)); //wait a moment
 }
 
 void CPlayerInterface::battleObstaclesRemoved(const std::set<si32> & removedObstacles)
@@ -686,7 +684,7 @@ void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr)
 		return;
 	}
 
-	//boost::unique_lock<boost::recursive_mutex> un(*pim); //fixme: this one caused deadlock
+	boost::unique_lock<boost::recursive_mutex> un(*pim); //fixme: this one caused deadlock
 	for(std::set<ui32>::const_iterator it = bsr.stackIDs.begin(); it != bsr.stackIDs.end(); ++it) //for each removed stack
 	{
 		battleInt->stackRemoved(*it);
@@ -820,9 +818,8 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
 			if (defender && !i->isSecondary())
 				battleInt->displayEffect(i->effect, defender->position);
 		}
-		StackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed(), i->willRebirth()};
+		StackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed(), i->willRebirth(), i->cloneKilled()};
 		arg.push_back(to_put);
-
 	}
 
 	if(bsa.begin()->isEffect() && bsa.begin()->effect == 12) //for armageddon - I hope this condition is enough

+ 2 - 1
client/NetPacksClient.cpp

@@ -603,7 +603,8 @@ void BattleStackMoved::applyFirstCl( CClient *cl )
 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStackMoved,movedStack,tilesToMove,distance);
 }
 
-void BattleStackAttacked::applyCl( CClient *cl )
+//void BattleStackAttacked::( CClient *cl )
+void BattleStackAttacked::applyFirstCl( CClient *cl )
 {
 	std::vector<BattleStackAttacked> bsa;
 	bsa.push_back(*this);

+ 2 - 2
lib/BattleState.cpp

@@ -1299,7 +1299,7 @@ si8 BattleInfo::hasWallPenalty( const CStack* stack, BattleHex destHex ) const
 	if (stackLeft && destRight) //shooting from outside to inside
 	{
 		int row = (stack->position + destHex) / (2 * GameConstants::BFIELD_WIDTH);
-		if (stack->position > destHex && ((destHex & GameConstants::BFIELD_WIDTH - stack->position % GameConstants::BFIELD_WIDTH) < 2)) //shooting up high
+		if (stack->position > destHex && ((destHex % GameConstants::BFIELD_WIDTH - stack->position % GameConstants::BFIELD_WIDTH) < 2)) //shooting up high
 			row -= 2;
 		int wallPos = lineToWallHex(row);
 		if (hexToWallPart(wallPos) != -1) //wall still exists or is indestructible
@@ -2732,7 +2732,7 @@ void CStack::prepareAttacked(BattleStackAttacked &bsa) const
 	if (bsa.damageAmount && vstd::contains(state, EBattleStackState::CLONED)) // block ability should not kill clone (0 damage)
 	{
 		bsa.killedAmount = count;
-		bsa.flags |= BattleStackAttacked::KILLED;
+		bsa.flags |= BattleStackAttacked::CLONE_KILLED;
 		return; // no rebirth I believe
 	}
 

+ 8 - 3
lib/NetPacks.h

@@ -1270,12 +1270,13 @@ struct StacksHealedOrResurrected : public CPackForClient //3013
 struct BattleStackAttacked : public CPackForClient//3005
 {
 	BattleStackAttacked(){flags = 0; type = 3005;};
-	void applyCl(CClient *cl);
+	void applyFirstCl(CClient * cl);
+	//void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui32 stackAttacked, attackerID;
 	ui32 newAmount, newHP, killedAmount, damageAmount;
-	enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4, REBIRTH = 8};
+	enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4, REBIRTH = 8, CLONE_KILLED = 16};
 	ui8 flags; //uses EFlags (above)
 	ui32 effect; //set only if flag EFFECT is set
 	std::vector<StacksHealedOrResurrected> healedStacks; //used when life drain
@@ -1283,7 +1284,11 @@ struct BattleStackAttacked : public CPackForClient//3005
 
 	bool killed() const//if target stack was killed
 	{
-		return flags & KILLED;
+		return flags & KILLED || flags & CLONE_KILLED;
+	}
+	bool cloneKilled() const
+	{
+		return flags & CLONE_KILLED;
 	}
 	bool isEffect() const//if stack has been attacked by a spell
 	{

+ 8 - 1
lib/NetPacksLib.cpp

@@ -972,6 +972,12 @@ DLL_LINKAGE void BattleStackAttacked::applyGs( CGameState *gs )
 		at->casts--;
 		at->state.insert(EBattleStackState::ALIVE); //hmm?
 	}
+	if (cloneKilled())
+	{
+		BattleStacksRemoved bsr; //remove body
+		bsr.stackIDs.insert(at->ID);
+		bsr.applyGs(gs);
+	}
 }
 
 DLL_LINKAGE void BattleAttack::applyGs( CGameState *gs )
@@ -1006,7 +1012,8 @@ DLL_LINKAGE void BattleAttack::applyGs( CGameState *gs )
 	for(std::vector<BattleStackAttacked>::const_iterator it = bsa.begin(); it != bsa.end(); ++it)
 	{
 		CStack * stack = gs->curB->getStack(it->stackAttacked, false);
-		stack->getBonusList().remove_if(Bonus::UntilBeingAttacked);
+		if (stack) //cloned stack is already gone
+			stack->getBonusList().remove_if(Bonus::UntilBeingAttacked);
 	}
 }