Selaa lähdekoodia

- No battle actions will be available during tactics phase
- Fixed moving stacks during tactics
- Fixed Genie spell targeting
- Fixed AI getting stuck at Tree of Knowledge when no resources

DjWarmonger 13 vuotta sitten
vanhempi
sitoutus
d6873d7570
4 muutettua tiedostoa jossa 69 lisäystä ja 65 poistoa
  1. 6 0
      AI/VCAI/VCAI.cpp
  2. 61 64
      client/BattleInterface/CBattleInterface.cpp
  3. 1 1
      lib/CCreatureSet.cpp
  4. 1 0
      lib/GameConstants.h

+ 6 - 0
AI/VCAI/VCAI.cpp

@@ -2666,6 +2666,12 @@ bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj)
 		case Obj::LIBRARY_OF_ENLIGHTENMENT:
 			if (h->level < 12)
 				return false;
+		case Obj::TREE_OF_KNOWLEDGE:
+			{
+				TResources myRes = ai->myCb->getResourceAmount();
+				if (myRes[Res::GOLD] - GOLD_RESERVE < 2000 || myRes[Res::GEMS] < 10)
+					return false;
+			}
 			break;
 	}
 

+ 61 - 64
client/BattleInterface/CBattleInterface.cpp

@@ -1941,14 +1941,9 @@ void CBattleInterface::activateStack()
 	{
 		stackCanCastSpell = true;
 		if(randomSpellcaster)
-			creatureSpellToCast = curInt->cb->battleGetRandomStackSpell(s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
-		else
-			creatureSpellToCast = spellcaster->subtype;
-
-		if(creatureSpellToCast < 0) //TODO proper way of detecting casters of positive spells
-			spellSelMode = FRIENDLY_CREATURE_SPELL;
+			creatureSpellToCast = -1;
 		else
-			spellSelMode = selectionTypeByPositiveness(*CGI->spellh->spells[creatureSpellToCast]);
+			creatureSpellToCast = curInt->cb->battleGetRandomStackSpell(s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
 	}
 	else
 	{
@@ -1996,63 +1991,69 @@ void CBattleInterface::endCastingSpell()
 void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
 {
 	possibleActions.clear();
-	//first action will be prioritized over later ones
-	if (stack->casts) //TODO: check for battlefield effects that prevent casting?
+	if (tacticsMode)
+	{
+		possibleActions += MOVE_TACTICS, CHOOSE_TACTICS_STACK;
+	}
+	else
 	{
-		if (stack->hasBonusOfType (Bonus::SPELLCASTER))
+		//first action will be prioritized over later ones
+		if (stack->casts) //TODO: check for battlefield effects that prevent casting?
 		{
-			 //TODO: poll possible spells
-			const CSpell * spell;
-			BonusList spellBonuses = *stack->getBonuses (Selector::type(Bonus::SPELLCASTER));
-			BOOST_FOREACH (Bonus * spellBonus, spellBonuses)
+			if (stack->hasBonusOfType (Bonus::SPELLCASTER))
 			{
-				spell = CGI->spellh->spells[spellBonus->subtype];
-				if (spell->isRisingSpell())
+				 //TODO: poll possible spells
+				const CSpell * spell;
+				BonusList spellBonuses = *stack->getBonuses (Selector::type(Bonus::SPELLCASTER));
+				BOOST_FOREACH (Bonus * spellBonus, spellBonuses)
 				{
-					possibleActions.push_back (RISING_SPELL);
-				}
-				//possibleActions.push_back (NO_LOCATION);
-				//possibleActions.push_back (ANY_LOCATION);
-				//possibleActions.push_back (OTHER_SPELL);
-				else
-				{
-					switch (spellBonus->subtype)
+					spell = CGI->spellh->spells[spellBonus->subtype];
+					if (spell->isRisingSpell())
 					{
-						case Spells::REMOVE_OBSTACLE:
-							possibleActions.push_back (OBSTACLE);
-							break;
-						default:
-							possibleActions.push_back (selectionTypeByPositiveness (*spell));
-							break;
+						possibleActions.push_back (RISING_SPELL);
+					}
+					//possibleActions.push_back (NO_LOCATION);
+					//possibleActions.push_back (ANY_LOCATION);
+					//possibleActions.push_back (OTHER_SPELL);
+					else
+					{
+						switch (spellBonus->subtype)
+						{
+							case Spells::REMOVE_OBSTACLE:
+								possibleActions.push_back (OBSTACLE);
+								break;
+							default:
+								possibleActions.push_back (selectionTypeByPositiveness (*spell));
+								break;
+						}
 					}
-				}
 
+				}
+				std::sort(possibleActions.begin(), possibleActions.end());
+				auto it = std::unique (possibleActions.begin(), possibleActions.end());
+				possibleActions.erase (it, possibleActions.end());
 			}
-			std::sort(possibleActions.begin(), possibleActions.end());
-			auto it = std::unique (possibleActions.begin(), possibleActions.end());
-			possibleActions.erase (it, possibleActions.end());
+			if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER))
+				possibleActions.push_back (RANDOM_GENIE_SPELL);
+			if (stack->hasBonusOfType (Bonus::DAEMON_SUMMONING))
+				possibleActions.push_back (RISE_DEMONS);
 		}
-		if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER))
-			possibleActions.push_back (RANDOM_GENIE_SPELL);
-		if (stack->hasBonusOfType (Bonus::DAEMON_SUMMONING))
-			possibleActions.push_back (RISE_DEMONS);
-	}
-	if (stack->shots && stack->hasBonusOfType (Bonus::SHOOTER))
-		possibleActions.push_back (SHOOT);
-	if (stack->hasBonusOfType (Bonus::RETURN_AFTER_STRIKE))
-		possibleActions.push_back (ATTACK_AND_RETURN);
+		if (stack->shots && stack->hasBonusOfType (Bonus::SHOOTER))
+			possibleActions.push_back (SHOOT);
+		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
+		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))
-		possibleActions.push_back (HEAL);
+		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))
+			possibleActions.push_back (HEAL);
+	}
 }
 
 void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
@@ -2602,8 +2603,6 @@ void CBattleInterface::bTacticNextStack(const CStack *current /*= NULL*/)
 	else
 		stackActivated(stacksOfMine.front());
 
-	possibleActions.clear();
-	possibleActions += MOVE_TACTICS, CHOOSE_TACTICS_STACK;
 }
 
 CBattleInterface::PossibleActions CBattleInterface::selectionTypeByPositiveness(const CSpell & spell)
@@ -2702,17 +2701,14 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 		
 		switch (action)
 		{ 
-			case MOVE_TACTICS:
-				break;
 			case CHOOSE_TACTICS_STACK:
 				if (shere && ourStack)
 					legalAction = true;
 				break;
+			case MOVE_TACTICS:
 			case MOVE_STACK:
-			{
-				if (canStackMoveHere (sactive, myNumber))
+				if (canStackMoveHere (sactive, myNumber) && !shere)
 					legalAction = true;
-			}
 				break;
 			case ATTACK:
 			case WALK_AND_ATTACK:
@@ -2749,7 +2745,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				break;
 			case RANDOM_GENIE_SPELL:
 			{
-				if (shere)
+				if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures
 				{
 					int spellID = curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE);
 					if (spellID > -1)
@@ -2829,8 +2825,9 @@ 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_TACTICS:
 			case MOVE_STACK:
-				if(activeStack->hasBonusOfType(Bonus::FLYING))
+				if (activeStack->hasBonusOfType(Bonus::FLYING))
 				{
 					cursorFrame = ECursor::COMBAT_FLY;
 					consoleMsg = (boost::format(CGI->generaltexth->allTexts[295]) % activeStack->getName()).str(); //Fly %s here
@@ -2843,7 +2840,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 
 				realizeAction = [=]
 				{
-					if(activeStack->doubleWide())
+					if (activeStack->doubleWide())
 					{
 						std::vector<BattleHex> acc = curInt->cb->battleGetAvailableHexes(activeStack, false);
 						int shiftedDest = myNumber + (activeStack->attackerOwned ? 1 : -1);
@@ -2854,7 +2851,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 					}
 					else
 					{
-						giveCommand(BattleAction::WALK, myNumber, activeStack->ID);
+						giveCommand (BattleAction::WALK, myNumber, activeStack->ID);
 					}
 				};
 				break;
@@ -2867,7 +2864,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				realizeAction = [=]
 				{
 					BattleHex attackFromHex = fromWhichHexAttack(myNumber);
-					if(attackFromHex >= 0) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
+					if (attackFromHex >= 0) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
 					{
 						giveCommand(BattleAction::WALK_AND_ATTACK, attackFromHex, activeStack->ID, myNumber);
 					}

+ 1 - 1
lib/CCreatureSet.cpp

@@ -959,7 +959,7 @@ CCommanderInstance::CCommanderInstance (TCreature id)
 	name = "Commando"; //TODO - parse them
 }
 
-void CCommanderInstance::init() //called only after CStackInstance::init was executed
+void CCommanderInstance::init()
 {
 	alive = true;
 	experience = 0;

+ 1 - 0
lib/GameConstants.h

@@ -205,6 +205,7 @@ namespace Obj
 		SHIPWRECK = 85,
 		STABLES = 94,
 		TRADING_POST = 99,
+		TREE_OF_KNOWLEDGE = 102,
 		SUBTERRANEAN_GATE = 103,
 		UNIVERSITY = 104,
 		SCHOOL_OF_WAR = 107,