فهرست منبع

Casting DD or TP will now spend mana before hero movement (and any side
effects such as visiting objects)

Ivan Savenko 1 سال پیش
والد
کامیت
6c45353aa7
2فایلهای تغییر یافته به همراه45 افزوده شده و 15 حذف شده
  1. 39 11
      lib/spells/AdventureSpellMechanics.cpp
  2. 6 4
      lib/spells/AdventureSpellMechanics.h

+ 39 - 11
lib/spells/AdventureSpellMechanics.cpp

@@ -119,29 +119,31 @@ ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnviron
 
 ESpellCastResult AdventureSpellMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
 {
-    return ESpellCastResult::OK;
+	return ESpellCastResult::OK;
+}
+
+void AdventureSpellMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
+{
+	// no-op, only for implementation in derived classes
 }
 
 void AdventureSpellMechanics::performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
 {
+	const auto level = parameters.caster->getSpellSchoolLevel(owner);
+	const auto cost = owner->getCost(level);
+
 	AdvmapSpellCast asc;
 	asc.casterID = ObjectInstanceID(parameters.caster->getCasterUnitId());
 	asc.spellID = owner->id;
 	env->apply(&asc);
 
 	ESpellCastResult result = applyAdventureEffects(env, parameters);
-	endCast(env, parameters, result);
-}
-
-void AdventureSpellMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const ESpellCastResult result) const
-{
-	const auto level = parameters.caster->getSpellSchoolLevel(owner);
-	const auto cost = owner->getCost(level);
 
 	switch(result)
 	{
 	case ESpellCastResult::OK:
 		parameters.caster->spendMana(env, cost);
+		endCast(env, parameters);
 		break;
 	default:
 		break;
@@ -427,10 +429,17 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
 		smp.val = 0;
 	env->apply(&smp);
 
+	return ESpellCastResult::OK;
+}
+
+void DimensionDoorMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
+{
+	int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
+	const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
+	const TerrainTile * curr = env->getCb()->getTile(casterPosition);
+
 	if(dest->isClear(curr))
 		env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), true);
-
-	return ESpellCastResult::OK;
 }
 
 ///TownPortalMechanics
@@ -526,6 +535,26 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
 		return ESpellCastResult::ERROR;
 	}
 
+	return ESpellCastResult::OK;
+}
+
+void TownPortalMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
+{
+	const int moveCost = movementCost(parameters);
+	const CGTownInstance * destination = nullptr;
+
+	if(parameters.caster->getSpellSchoolLevel(owner) < 2)
+	{
+		std::vector <const CGTownInstance*> pool = getPossibleTowns(env, parameters);
+		destination = findNearestTown(env, parameters, pool);
+	}
+	else
+	{
+		const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
+		auto * const topObj = tile.topVisitableObj(false);
+		destination = dynamic_cast<const CGTownInstance*>(topObj);
+	}
+
 	if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(destination->visitablePos()), true))
 	{
 		SetMovePoints smp;
@@ -533,7 +562,6 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
 		smp.val = std::max<ui32>(0, parameters.caster->getHeroCaster()->movementPointsRemaining() - moveCost);
 		env->apply(&smp);
 	}
-	return ESpellCastResult::OK;
 }
 
 ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const

+ 6 - 4
lib/spells/AdventureSpellMechanics.h

@@ -18,10 +18,10 @@ class CGTownInstance;
 
 enum class ESpellCastResult
 {
-	OK,
-	CANCEL,//cast failed but it is not an error
+	OK, // cast successful
+	CANCEL, // cast failed but it is not an error, no mana has been spent
 	PENDING,
-	ERROR//internal error occurred
+	ERROR// error occured, for example invalid request from player
 };
 
 class AdventureSpellMechanics : public IAdventureSpellMechanics
@@ -37,11 +37,11 @@ protected:
 	///actual adventure cast implementation
 	virtual ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
 	virtual ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
+	virtual void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
 	virtual bool canBeCastImpl(spells::Problem & problem, const CGameInfoCallback * cb, const spells::Caster * caster) const;
 	virtual bool canBeCastAtImpl(spells::Problem & problem, const CGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const;
 
 	void performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
-	void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const ESpellCastResult result) const;
 };
 
 class SummonBoatMechanics final : public AdventureSpellMechanics
@@ -73,6 +73,7 @@ protected:
 	bool canBeCastAtImpl(spells::Problem & problem, const CGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const override;
 
 	ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
+	void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
 };
 
 class TownPortalMechanics final : public AdventureSpellMechanics
@@ -82,6 +83,7 @@ public:
 protected:
 	ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
 	ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
+	void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
 private:
 	const CGTownInstance * findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector <const CGTownInstance*> & pool) const;
 	int32_t movementCost(const AdventureSpellCastParameters & parameters) const;