瀏覽代碼

Fix 0001331

AlexVinS 10 年之前
父節點
當前提交
11b3426bea

+ 26 - 26
lib/spells/AdventureSpellMechanics.cpp

@@ -20,7 +20,7 @@
 #include "../CGameInfoCallback.h"
 
 ///SummonBoatMechanics
-bool SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
+ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
 {
 	const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
 	//check if spell works at all
@@ -31,7 +31,7 @@ bool SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 		iw.text.addTxt(MetaString::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
 		iw.text.addReplacement(parameters.caster->name);
 		env->sendAndApply(&iw);
-		return true;
+		return ESpellCastResult::OK;
 	}
 
 	//try to find unoccupied boat to summon
@@ -41,7 +41,7 @@ bool SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 	if(summonPos.x < 0)
 	{
 		env->complain("There is no water tile available!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	for(const CGObjectInstance * obj : env->getMap()->objects)
@@ -84,11 +84,11 @@ bool SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 		no.pos = summonPos + int3(1,0,0);;
 		env->sendAndApply(&no);
 	}
-	return true;
+	return ESpellCastResult::OK;
 }
 
 ///ScuttleBoatMechanics
-bool ScuttleBoatMechanics::applyAdventureEffects(const SpellCastEnvironment* env, AdventureSpellCastParameters& parameters) const
+ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(const SpellCastEnvironment* env, AdventureSpellCastParameters& parameters) const
 {
 	const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
 	//check if spell works at all
@@ -99,13 +99,13 @@ bool ScuttleBoatMechanics::applyAdventureEffects(const SpellCastEnvironment* env
 		iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
 		iw.text.addReplacement(parameters.caster->name);
 		env->sendAndApply(&iw);
-		return true;
+		return ESpellCastResult::OK;
 	}
 
 	if(!env->getMap()->isInTheMap(parameters.pos))
 	{
 		env->complain("Invalid dst tile for scuttle!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	//TODO: test range, visibility
@@ -113,22 +113,22 @@ bool ScuttleBoatMechanics::applyAdventureEffects(const SpellCastEnvironment* env
 	if(!t->visitableObjects.size() || t->visitableObjects.back()->ID != Obj::BOAT)
 	{
 		env->complain("There is no boat to scuttle!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	RemoveObject ro;
 	ro.id = t->visitableObjects.back()->id;
 	env->sendAndApply(&ro);
-	return true;
+	return ESpellCastResult::OK;
 }
 
 ///DimensionDoorMechanics
-bool DimensionDoorMechanics::applyAdventureEffects(const SpellCastEnvironment* env, AdventureSpellCastParameters& parameters) const
+ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(const SpellCastEnvironment* env, AdventureSpellCastParameters& parameters) const
 {
 	if(!env->getMap()->isInTheMap(parameters.pos))
 	{
 		env->complain("Destination is out of map!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
@@ -137,19 +137,19 @@ bool DimensionDoorMechanics::applyAdventureEffects(const SpellCastEnvironment* e
 	if(nullptr == dest)
 	{
 		env->complain("Destination tile doesn't exist!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	if(nullptr == curr)
 	{
 		env->complain("Source tile doesn't exist!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	if(parameters.caster->movement <= 0)
 	{
 		env->complain("Hero needs movement points to cast Dimension Door!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
@@ -161,7 +161,7 @@ bool DimensionDoorMechanics::applyAdventureEffects(const SpellCastEnvironment* e
 		iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today.
 		iw.text.addReplacement(parameters.caster->name);
 		env->sendAndApply(&iw);
-		return true;
+		return ESpellCastResult::CANCEL;
 	}
 
 	GiveBonus gb;
@@ -183,23 +183,23 @@ bool DimensionDoorMechanics::applyAdventureEffects(const SpellCastEnvironment* e
 		smp.val = std::max<ui32>(0, parameters.caster->movement - 300);
 		env->sendAndApply(&smp);
 	}
-	return true;
+	return ESpellCastResult::OK;
 }
 
 ///TownPortalMechanics
-bool TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters& parameters) const
+ESpellCastResult TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters& parameters) const
 {
 	if (!env->getMap()->isInTheMap(parameters.pos))
 	{
 		env->complain("Destination tile not present!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	TerrainTile tile = env->getMap()->getTile(parameters.pos);
 	if (tile.visitableObjects.empty() || tile.visitableObjects.back()->ID != Obj::TOWN)
 	{
 		env->complain("Town not found for Town Portal!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	CGTownInstance * town = static_cast<CGTownInstance*>(tile.visitableObjects.back());
@@ -209,13 +209,13 @@ bool TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 	if(relations == PlayerRelations::ENEMIES)
 	{
 		env->complain("Can't teleport to enemy!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	if (town->visitingHero)
 	{
 		env->complain("Can't teleport to occupied town!");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 
 	if (parameters.caster->getSpellSchoolLevel(owner) < 2)
@@ -234,7 +234,7 @@ bool TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 		if (town->id != nearest)
 		{
 			env->complain("This hero can only teleport to nearest town!");
-			return false;
+			return ESpellCastResult::ERROR;
 		}
 
 	}
@@ -244,7 +244,7 @@ bool TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 	if(parameters.caster->movement < movementCost)
 	{
 		env->complain("This hero has not enough movement points!");
-		return false;		
+		return ESpellCastResult::ERROR;		
 	}
 	
 	if(env->moveHero(parameters.caster->id, town->visitablePos() + parameters.caster->getVisitableOffset() ,1))
@@ -254,10 +254,10 @@ bool TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env
 		smp.val = std::max<ui32>(0, parameters.caster->movement - movementCost);
 		env->sendAndApply(&smp);		
 	}
-	return true;
+	return ESpellCastResult::OK;
 }
 
-bool ViewMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
+ESpellCastResult ViewMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
 {
 	ShowWorldViewEx pack;
 
@@ -275,7 +275,7 @@ bool ViewMechanics::applyAdventureEffects(const SpellCastEnvironment * env, Adve
 
 	env->sendAndApply(&pack);
 
-	return true;
+	return ESpellCastResult::OK;
 }
 
 bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int spellLevel) const

+ 5 - 5
lib/spells/AdventureSpellMechanics.h

@@ -20,7 +20,7 @@ class DLL_LINKAGE SummonBoatMechanics : public DefaultSpellMechanics
 public:
 	SummonBoatMechanics(CSpell * s): DefaultSpellMechanics(s){};
 protected:
-	bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
+	ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
 };
 
 class DLL_LINKAGE ScuttleBoatMechanics : public DefaultSpellMechanics
@@ -28,7 +28,7 @@ class DLL_LINKAGE ScuttleBoatMechanics : public DefaultSpellMechanics
 public:
 	ScuttleBoatMechanics(CSpell * s): DefaultSpellMechanics(s){};
 protected:
-	bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
+	ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
 };
 
 class DLL_LINKAGE DimensionDoorMechanics : public DefaultSpellMechanics
@@ -36,7 +36,7 @@ class DLL_LINKAGE DimensionDoorMechanics : public DefaultSpellMechanics
 public:
 	DimensionDoorMechanics(CSpell * s): DefaultSpellMechanics(s){};
 protected:
-	bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
+	ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
 };
 
 class DLL_LINKAGE TownPortalMechanics : public DefaultSpellMechanics
@@ -44,7 +44,7 @@ class DLL_LINKAGE TownPortalMechanics : public DefaultSpellMechanics
 public:
 	TownPortalMechanics(CSpell * s): DefaultSpellMechanics(s){};
 protected:
-	bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
+	ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
 };
 
 class DLL_LINKAGE ViewMechanics : public DefaultSpellMechanics
@@ -52,7 +52,7 @@ class DLL_LINKAGE ViewMechanics : public DefaultSpellMechanics
 public:
 	ViewMechanics(CSpell * s): DefaultSpellMechanics(s){};
 protected:
-	bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
+	ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override;
 	virtual bool filterObject(const CGObjectInstance * obj, const int spellLevel) const = 0;
 };
 

+ 16 - 10
lib/spells/CDefaultSpellMechanics.cpp

@@ -175,20 +175,26 @@ bool DefaultSpellMechanics::adventureCast(const SpellCastEnvironment * env, Adve
 		asc.spellID = owner->id;
 		env->sendAndApply(&asc);
 	}
-
-	if(applyAdventureEffects(env, parameters))
+	
+	switch(applyAdventureEffects(env, parameters))
 	{
-		SetMana sm;
-		sm.hid = caster->id;
-		sm.absolute = false;
-		sm.val = -cost;
-		env->sendAndApply(&sm);
+	case ESpellCastResult::OK:
+		{
+			SetMana sm;
+			sm.hid = caster->id;
+			sm.absolute = false;
+			sm.val = -cost;
+			env->sendAndApply(&sm);
+			return true;			
+		}
+		break;
+	case ESpellCastResult::CANCEL:
 		return true;
 	}
 	return false;
 }
 
-bool DefaultSpellMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
+ESpellCastResult DefaultSpellMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
 {
 	if(owner->hasEffects())
 	{
@@ -206,13 +212,13 @@ bool DefaultSpellMechanics::applyAdventureEffects(const SpellCastEnvironment * e
 			env->sendAndApply(&gb);
 		}
 
-		return true;
+		return ESpellCastResult::OK;
 	}
 	else
 	{
 		//There is no generic algorithm of adventure cast
 		env->complain("Unimplemented adventure spell");
-		return false;
+		return ESpellCastResult::ERROR;
 	}
 }
 

+ 8 - 1
lib/spells/CDefaultSpellMechanics.h

@@ -25,6 +25,13 @@ struct SpellCastContext
 	StacksInjured & si;
 };
 
+enum class ESpellCastResult
+{
+	OK,
+	CANCEL,//cast failed but it is not an error
+	ERROR//internal error occurred
+};
+
 class DLL_LINKAGE DefaultSpellMechanics : public ISpellMechanics
 {
 public:
@@ -50,7 +57,7 @@ protected:
 	ui32 calculateHealedHP(const CGHeroInstance * caster, const CStack * stack, const CStack * sacrificedStack) const;
 
 	///actual adventure cast implementation
-	virtual bool applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const;
+	virtual ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const;
 	
 	void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
 };