瀏覽代碼

* some work towards fix of 537
* 338 seems to be fixed

mateuszb 14 年之前
父節點
當前提交
d630d88ac1
共有 4 個文件被更改,包括 62 次插入4 次删除
  1. 24 0
      CCallback.cpp
  2. 8 0
      CCallback.h
  3. 28 3
      client/CSpellWindow.cpp
  4. 2 1
      lib/BattleState.cpp

+ 24 - 0
CCallback.cpp

@@ -1087,3 +1087,27 @@ std::vector<int> CBattleCallback::battleGetDistances(const CStack * stack, THex
 	return ret;
 	return ret;
 }
 }
 
 
+CBattleCallback::ESpellCastProblem CBattleCallback::battleCanCastThisSpell( const CSpell * spell )
+{
+	if(!battleCanCastSpell())
+		return GENERAL_CASTING_PROBLEM;
+
+	int spellIDs[] = {66, 67, 68, 69}; //IDs of summon elemental spells (fire, earth, water, air)
+	int creIDs[] = {114, 113, 115, 112}; //(fire, earth, water, air)
+
+	int * idp = std::find(spellIDs, spellIDs + ARRAY_COUNT(spellIDs), spell->id);
+	int arpos = idp - spellIDs;
+	if(arpos < ARRAY_COUNT(spellIDs))
+	{
+		//check if there are summoned elementals of other type
+		BOOST_FOREACH ( const CStack * st, gs->curB->stacks)
+		{
+			if (vstd::contains(st->state, SUMMONED) && st->getCreature()->idNumber != creIDs[arpos])
+			{
+				return ANOTHER_ELEMENTAL_SUMMONED;
+			}
+		}
+	}
+
+	return OK;
+}

+ 8 - 0
CCallback.h

@@ -73,6 +73,12 @@ struct InfoAboutTown
 class IBattleCallback
 class IBattleCallback
 {
 {
 public:
 public:
+	///describes why player cannot cast a specific spell
+	enum ESpellCastProblem
+	{
+		OK, GENERAL_CASTING_PROBLEM, ANOTHER_ELEMENTAL_SUMMONED
+	};
+
 	bool waitTillRealize; //if true, request functions will return after they are realized by server
 	bool waitTillRealize; //if true, request functions will return after they are realized by server
 	//battle
 	//battle
 	virtual int battleGetBattlefieldType()=0; //   1. sand/shore   2. sand/mesas   3. dirt/birches   4. dirt/hills   5. dirt/pines   6. grass/hills   7. grass/pines   8. lava   9. magic plains   10. snow/mountains   11. snow/trees   12. subterranean   13. swamp/trees   14. fiery fields   15. rock lands   16. magic clouds   17. lucid pools   18. holy ground   19. clover field   20. evil fog   21. "favourable winds" text on magic plains background   22. cursed ground   23. rough   24. ship to ship   25. ship
 	virtual int battleGetBattlefieldType()=0; //   1. sand/shore   2. sand/mesas   3. dirt/birches   4. dirt/hills   5. dirt/pines   6. grass/hills   7. grass/pines   8. lava   9. magic plains   10. snow/mountains   11. snow/trees   12. subterranean   13. swamp/trees   14. fiery fields   15. rock lands   16. magic clouds   17. lucid pools   18. holy ground   19. clover field   20. evil fog   21. "favourable winds" text on magic plains background   22. cursed ground   23. rough   24. ship to ship   25. ship
@@ -88,6 +94,7 @@ public:
 	virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
 	virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
 	virtual bool battleCanShoot(const CStack * stack, THex dest)=0; //returns true if unit with id ID can shoot to dest
 	virtual bool battleCanShoot(const CStack * stack, THex dest)=0; //returns true if unit with id ID can shoot to dest
 	virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
 	virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
+	virtual ESpellCastProblem battleCanCastThisSpell(const CSpell * spell)=0; //determines if given spell can be casted (and returns problem description)
 	virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle
 	virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle
 	virtual const CGTownInstance * battleGetDefendedTown()=0; //returns defended town if current battle is a siege, NULL instead
 	virtual const CGTownInstance * battleGetDefendedTown()=0; //returns defended town if current battle is a siege, NULL instead
 	virtual ui8 battleGetWallState(int partOfWall)=0; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
 	virtual ui8 battleGetWallState(int partOfWall)=0; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
@@ -216,6 +223,7 @@ public:
 	std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory
 	std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory
 	bool battleCanShoot(const CStack * stack, THex dest) OVERRIDE; //returns true if unit with id ID can shoot to dest
 	bool battleCanShoot(const CStack * stack, THex dest) OVERRIDE; //returns true if unit with id ID can shoot to dest
 	bool battleCanCastSpell() OVERRIDE; //returns true, if caller can cast a spell
 	bool battleCanCastSpell() OVERRIDE; //returns true, if caller can cast a spell
+	ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) OVERRIDE; //determines if given spell can be casted (and returns problem description)
 	bool battleCanFlee() OVERRIDE; //returns true if caller can flee from the battle
 	bool battleCanFlee() OVERRIDE; //returns true if caller can flee from the battle
 	const CGTownInstance * battleGetDefendedTown() OVERRIDE; //returns defended town if current battle is a siege, NULL instead
 	const CGTownInstance * battleGetDefendedTown() OVERRIDE; //returns defended town if current battle is a siege, NULL instead
 	ui8 battleGetWallState(int partOfWall) OVERRIDE; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
 	ui8 battleGetWallState(int partOfWall) OVERRIDE; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle

+ 28 - 3
client/CSpellWindow.cpp

@@ -16,7 +16,9 @@
 #include <sstream>
 #include <sstream>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
 #include "CBitmapHandler.h"
 #include "CBitmapHandler.h"
+#include "../lib/CHeroHandler.h"
 
 
 /*
 /*
  * CSpellWindow.cpp, part of VCMI engine
  * CSpellWindow.cpp, part of VCMI engine
@@ -617,9 +619,32 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 		//we will cast a spell
 		//we will cast a spell
 		if(sp->combatSpell && owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell()) //if battle window is open
 		if(sp->combatSpell && owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell()) //if battle window is open
 		{
 		{
-			int spell = mySpell;
-			owner->fexitb();
-			owner->myInt->battleInt->castThisSpell(spell);
+			IBattleCallback::ESpellCastProblem problem = owner->myInt->cb->battleCanCastThisSpell(sp);
+			switch (problem)
+			{
+			case IBattleCallback::OK:
+				{
+					int spell = mySpell;
+					owner->fexitb();
+					owner->myInt->battleInt->castThisSpell(spell);
+					break;
+				}
+			case IBattleCallback::ANOTHER_ELEMENTAL_SUMMONED:
+				{
+					std::string text = CGI->generaltexth->allTexts[538], summoner, elemental, caster;
+					std::vector<const CStack *> stacks = owner->myInt->cb->battleGetStacks();
+					if (owner->myHero->type->sex)
+					{ //female
+						caster = CGI->generaltexth->allTexts[540];
+					}
+					else
+					{ //male
+						caster = CGI->generaltexth->allTexts[539];
+					}
+
+					owner->myInt->showInfoDialog(text);
+				}
+			}
 		}
 		}
 		else if(!sp->combatSpell && !owner->myInt->battleInt) //adventure spell
 		else if(!sp->combatSpell && !owner->myInt->battleInt) //adventure spell
 		{
 		{

+ 2 - 1
lib/BattleState.cpp

@@ -143,7 +143,7 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool atta
 
 
 	for(unsigned int g=0; g<stacks.size(); ++g)
 	for(unsigned int g=0; g<stacks.size(); ++g)
 	{
 	{
-		if(!stacks[g]->alive() || stacks[g]->ID==stackToOmmit->ID || stacks[g]->position < 0) //we don't want to lock position of this stack (eg. if it's a turret)
+		if(!stacks[g]->alive() || (stackToOmmit && stacks[g]->ID==stackToOmmit->ID) || stacks[g]->position < 0) //we don't want to lock position of this stack (eg. if it's a turret)
 			continue;
 			continue;
 
 
 		accessibility[stacks[g]->position] = false;
 		accessibility[stacks[g]->position] = false;
@@ -1781,6 +1781,7 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
 	case 47: //disrupting ray
 	case 47: //disrupting ray
 	 	sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -1 * power, sse.turnsRemain));
 	 	sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -1 * power, sse.turnsRemain));
 	 	sf.back().id = sse.id;
 	 	sf.back().id = sse.id;
+		sf.back().valType = Bonus::ADDITIVE_VALUE;
 	 	break;
 	 	break;
 	case 48: //prayer
 	case 48: //prayer
 	 	sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain));
 	 	sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain));