2
0
Эх сурвалжийг харах

- Battle interface fixes. It's possible to move stacks & attack
- Creature window allows to pass stack artifact to hero
- Fixes for Mana Drain, including #916

DjWarmonger 13 жил өмнө
parent
commit
f720038ca5

+ 25 - 10
client/BattleInterface/CBattleInterface.cpp

@@ -1946,6 +1946,8 @@ void CBattleInterface::activateStack()
 
 	if(!pendingAnims.size() && !active)
 		activate();
+
+	getPossibleActionsForStack (activeStack);
 }
 
 double CBattleInterface::getAnimSpeedMultiplier() const
@@ -1986,7 +1988,8 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
 		{
 			 //TODO: poll possible spells
 			const CSpell * spell;
-			BOOST_FOREACH (Bonus * spellBonus, *stack->getBonuses (Selector::type(Bonus::SPELLCASTER)))
+			BonusList spellBonuses = *stack->getBonuses (Selector::type(Bonus::SPELLCASTER));
+			BOOST_FOREACH (Bonus * spellBonus, spellBonuses)
 			{
 				spell = CGI->spellh->spells[spellBonus->subtype];
 				if (spell->isRisingSpell())
@@ -2018,12 +2021,15 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
 	}
 	if (stack->shots && stack->hasBonusOfType (Bonus::SHOOTER))
 		possibleActions.push_back (SHOOT);
-	if (stack->hasBonusOfType (Bonus::RETURN_AFTER_STRIKE));
+	if (stack->hasBonusOfType (Bonus::RETURN_AFTER_STRIKE))
 		possibleActions.push_back (ATTACK_AND_RETURN);
 
 	possibleActions.push_back(ATTACK); //all active stacks can attack
 	possibleActions.push_back(WALK_AND_ATTACK); //not all stacks can always walk, but we will check this elsewhere
 
+	if (stack->canMove() && stack->Speed()); //probably no reason to try move war machines or bound stacks
+		possibleActions.push_back (MOVE_STACK); //all active stacks can attack
+
 	if (siegeH && stack->hasBonusOfType (Bonus::CATAPULT)) //TODO: check shots
 		possibleActions.push_back (CATAPULT);
 	if (stack->hasBonusOfType (Bonus::HEALER))
@@ -2664,19 +2670,28 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 					legalAction = true;
 				break;
 			case MOVE_STACK:
-				if (vstd::contains(occupyableHexes, myNumber) || activeStack->coversPos(myNumber))
-					//TODO
+			{
+				std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes (activeStack, false);
+				int shiftedDest = myNumber + (activeStack->attackerOwned ? 1 : -1);
+
+				if (vstd::contains(acc, myNumber))
 					legalAction = true;
+				else if (sactive->doubleWide() && vstd::contains(acc, shiftedDest))
+					legalAction = true;
+			}
 				break;
 			case ATTACK:
 			case WALK_AND_ATTACK:
 			case ATTACK_AND_RETURN:
 			{
-				std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes (activeStack, false);
+				if (shere && shere->alive())
+				{
+					setBattleCursor(myNumber); // temporary - needed for following function :(
+					BattleHex attackFromHex = fromWhichHexAttack(myNumber);
 
-				BattleHex attackFromHex = fromWhichHexAttack(myNumber);
-				if(shere->alive() && isTileAttackable(myNumber) && attackFromHex >= 0) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
-					legalAction = true;
+					if (isTileAttackable(myNumber) && attackFromHex >= 0) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
+						legalAction = true;
+				}
 			}
 				break;
 			case SHOOT:
@@ -2773,7 +2788,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				consoleMsg = (boost::format(CGI->generaltexth->allTexts[481]) % shere->getName()).str(); //Select %s
 				realizeAction = [=]{ stackActivated(shere); };
 				break;
-			case MOVE:
+			case MOVE_STACK:
 				if(activeStack->hasBonusOfType(Bonus::FLYING))
 				{
 					cursorFrame = ECursor::COMBAT_FLY;
@@ -2807,7 +2822,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 			case ATTACK_AND_RETURN: //TODO: allow to disable return
 			{
 				setBattleCursor(myNumber); //handle direction of cursor and attackable tile
-				setCursor = false; //don't overwrite settings from the call above
+				setCursor = false; //don't overwrite settings from the call above //TODO: what does it mean?
 				realizeAction = [=]
 				{
 					BattleHex attackFromHex = fromWhichHexAttack(myNumber);

+ 30 - 16
client/CCreatureWindow.cpp

@@ -20,6 +20,7 @@
 #include "../lib/BattleState.h"
 #include "../lib/CSpellHandler.h"
 #include "../lib/CArtHandler.h"
+#include "../lib/NetPacks.h" //ArtifactLocation
 
 #include "UIFramework/CGuiHandler.h"
 #include "UIFramework/CIntObjectClasses.h"
@@ -258,15 +259,15 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
 
 		if (GameConstants::STACK_ARTIFACT)
 		{
+			creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT);
 			if (type > BATTLE) //artifact buttons inactive in battle
 			{
+				//TODO: disable buttons if no artifact is equipped
 				leftArtRoll = new CAdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, -1), 437, 98, "hsbtns3.def", SDLK_LEFT);
 				rightArtRoll = new CAdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, +1), 516, 98, "hsbtns5.def", SDLK_RIGHT);
 				if (heroOwner)
-					passArtToHero = new CAdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, 0), 437, 148, "OVBUTN1.DEF", SDLK_HOME);
+					passArtToHero = new CAdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::passArtifactToHero, this), 437, 148, "OVBUTN1.DEF", SDLK_HOME);
 			}
-			if ((creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT)))
-				blitAt(graphics->artDefs->ourImages[creatureArtifact->artType->id].bitmap, 466, 100, *bitmap);
 		}
 	}
 
@@ -379,6 +380,12 @@ void CCreatureWindow::showAll(SDL_Surface * to)
 
 	BOOST_FOREACH(CBonusItem* b, bonusItems)
 		b->showAll (to);
+
+	if (GameConstants::STACK_ARTIFACT)
+	{
+		if (creatureArtifact)
+			blitAt(graphics->artDefs->ourImages[creatureArtifact->artType->id].bitmap, 466 + pos.x, 100 + pos.y, to);
+	}
 }
 
 void CCreatureWindow::show(SDL_Surface * to)
@@ -402,7 +409,26 @@ void CCreatureWindow::scrollArt(int dir)
 
 void CCreatureWindow::passArtifactToHero()
 {
-	//creatureArtifact->artType; //FIXME
+	const CGHeroInstance * h = dynamic_cast<const CGHeroInstance *>(stack->armyObj);
+	if (h && creatureArtifact)
+	{
+		LOCPLINT->cb->swapArtifacts (ArtifactLocation (stack, ArtifactPosition::CREATURE_SLOT), ArtifactLocation(h, creatureArtifact->firstBackpackSlot(h)));
+	}
+	else
+		tlog2 << "Pass artifact to hero should be disabled, no hero or no artifact!\n";
+
+	//redraw is handled via CArtifactHolder interface
+}
+
+void CCreatureWindow::artifactRemoved (const ArtifactLocation &artLoc)
+{
+	creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); //TODO: select next from the list (for Commanders)
+	redraw();
+}
+void CCreatureWindow::artifactMoved (const ArtifactLocation &artLoc, const ArtifactLocation &destLoc)
+{
+	creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); //TODO: select next from the list (for Commanders)
+	redraw();
 }
 
 void CCreatureWindow::clickRight(tribool down, bool previousState)
@@ -413,18 +439,6 @@ void CCreatureWindow::clickRight(tribool down, bool previousState)
 		close();
 }
 
-//void CCreatureWindow::activate()
-//{
-//	CIntObject::activate();
-//	if(type < 3)
-//		activateRClick();
-//}
-
-//void CCreatureWindow::deactivate()
-//{
-//
-//}
-
 void CCreatureWindow::close()
 {
 	GH.popIntTotally(this);

+ 7 - 1
client/CCreatureWindow.h

@@ -18,6 +18,7 @@ struct Bonus;
 class CCreature;
 class CStackInstance;
 class CStack;
+class ArtifactLocation;
 class CCreatureArtifactInstance;
 class CAdventureMapButton;
 class CBonusItem;
@@ -35,7 +36,7 @@ class CLabel;
 class CAnimImage;
 
 // New creature window
-class CCreatureWindow : public CIntObject
+class CCreatureWindow : public CArtifactHolder
 {
 public:
 	enum CreWinType {OTHER = 0, BATTLE = 1, ARMY = 2, HERO = 3}; //only last one should open permanently
@@ -62,6 +63,11 @@ public:
 	CAdventureMapButton * leftArtRoll, * rightArtRoll; //artifact selection
 	CAdventureMapButton * passArtToHero;
 
+	void artifactRemoved (const ArtifactLocation &artLoc);
+	void artifactMoved (const ArtifactLocation &artLoc, const ArtifactLocation &destLoc);
+	void artifactDisassembled (const ArtifactLocation &artLoc) {return;};
+	void artifactAssembled (const ArtifactLocation &artLoc) {return;};
+
 	boost::function<void()> dsm; //dismiss button callback
 	boost::function<void()> Upg; //upgrade button callback
 

+ 1 - 0
config/bonusnames.json

@@ -23,6 +23,7 @@
 			{ "id": "SPELL_IMMUNITY", "name": "Immune to %s", "description": "" },
 			{ "id": "CHARGE_IMMUNITY", "name": "Immune to Charge", "description": "Immune to Champion charge" },
 			{ "id": "MANA_CHANNELING", "name": "Magic Channel %d%", "description": "Gives mana spent by enemy" },
+			{ "id": "MANA_DRAIN", "name": "Mana Drain", "description": "Drains %d mana every turn" },
 			{ "id": "CHANGES_SPELL_COST_FOR_ENEMY", "name": "Magic Damper (%d)", "description": "Increase Cost of enemy spells" },
 			{ "id": "MAGIC_MIRROR", "name": "Magic Mirror (%d%)", "description": "Redirects offensive spell to enemy" },
 			{ "id": "MAGIC_RESISTANCE", "name": "Magic Resistance", "description": "%d% chance to resist enemy spell" },

+ 1 - 1
lib/CCreatureSet.cpp

@@ -583,7 +583,7 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
 				case Bonus::DRAGON_NATURE:
 				case Bonus::NON_LIVING:
 				case Bonus::UNDEAD:
-				case Bonus::FIRE_IMMUNITY: //TODO: what about direct, hostile and total immunity?
+				case Bonus::FIRE_IMMUNITY:
 				case Bonus::WATER_IMMUNITY:
 				case Bonus::AIR_IMMUNITY:
 				case Bonus::EARTH_IMMUNITY:

+ 2 - 1
lib/GameConstants.h

@@ -171,7 +171,8 @@ namespace EMarketMode
 
 namespace EBattleStackState
 {
-	enum EBattleStackState{ALIVE = 180, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFENDING, FEAR};
+	enum EBattleStackState{ALIVE = 180, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFENDING, FEAR,
+		DRAINED_MANA /*remember to drain mana only once per turn*/};
 }
 
 namespace ECommander

+ 2 - 0
lib/NetPacksLib.cpp

@@ -922,6 +922,7 @@ DLL_LINKAGE void BattleNextRound::applyGs( CGameState *gs )
 		s->state -= EBattleStackState::MOVED;
 		s->state -= EBattleStackState::HAD_MORALE;
 		s->state -= EBattleStackState::FEAR;
+		s->state -= EBattleStackState::DRAINED_MANA;
 		s->counterAttacks = 1 + s->valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
 		// new turn effects
 		s->battleTurnPassed();
@@ -952,6 +953,7 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs( CGameState *gs )
 		case Bonus::MANA_DRAIN:
 		{
 			CGHeroInstance * h = gs->getHero(additionalInfo);
+			st->state.insert (EBattleStackState::DRAINED_MANA);
 			h->mana -= val;
 			vstd::amax(h->mana, 0);
 			break;

+ 1 - 1
server/CGameHandler.cpp

@@ -4096,7 +4096,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
 				}
 			}
 		}
-		if(st->hasBonusOfType(Bonus::MANA_DRAIN))
+		if (st->hasBonusOfType(Bonus::MANA_DRAIN) && !vstd::contains(st->state, EBattleStackState::DRAINED_MANA))
 		{
 			const CGHeroInstance * enemy = gs->curB->getHero(gs->curB->theOtherPlayer(st->owner));
 			if (enemy)