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

Added abstract method to caster interface

nordsoft 2 жил өмнө
parent
commit
0093a44889

+ 4 - 0
include/vcmi/spells/Caster.h

@@ -15,6 +15,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class PlayerColor;
 struct MetaString;
 class ServerCallback;
+class CGHeroInstance;
 
 namespace battle
 {
@@ -65,6 +66,9 @@ public:
 	virtual void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const = 0;
 
 	virtual void spendMana(ServerCallback * server, const int32_t spellCost) const = 0;
+	
+	///used to identify actual hero caster
+	virtual const CGHeroInstance * getHeroCaster() const = 0;
 };
 
 }

+ 5 - 0
lib/battle/CUnitState.cpp

@@ -418,6 +418,11 @@ int32_t CUnitState::getCasterUnitId() const
 	return static_cast<int32_t>(unitId());
 }
 
+const CGHeroInstance * CUnitState::getHeroCaster() const
+{
+	return nullptr;
+}
+
 int32_t CUnitState::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const
 {
 	int32_t skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->getIndex()));

+ 1 - 0
lib/battle/CUnitState.h

@@ -192,6 +192,7 @@ public:
 	int64_t getEffectValue(const spells::Spell * spell) const override;
 
 	PlayerColor getCasterOwner() const override;
+	const CGHeroInstance * getHeroCaster() const override;
 	void getCasterName(MetaString & text) const override;
 	void getCastDescription(const spells::Spell * spell, const std::vector<const Unit *> & attacked, MetaString & text) const override;
 

+ 5 - 0
lib/mapObjects/CGHeroInstance.cpp

@@ -669,6 +669,11 @@ void CGHeroInstance::getCastDescription(const spells::Spell * spell, const std::
 		attacked.at(0)->addNameReplacement(text, true);
 }
 
+const CGHeroInstance * CGHeroInstance::getHeroCaster() const
+{
+	return this;
+}
+
 void CGHeroInstance::spendMana(ServerCallback * server, const int spellCost) const
 {
 	if(spellCost != 0)

+ 1 - 0
lib/mapObjects/CGHeroInstance.h

@@ -275,6 +275,7 @@ public:
 	int64_t getEffectValue(const spells::Spell * spell) const override;
 
 	PlayerColor getCasterOwner() const override;
+	const CGHeroInstance * getHeroCaster() const override;
 
 	void getCasterName(MetaString & text) const override;
 	void getCastDescription(const spells::Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;

+ 19 - 23
lib/spells/AdventureSpellMechanics.cpp

@@ -143,12 +143,13 @@ SummonBoatMechanics::SummonBoatMechanics(const CSpell * s):
 
 ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
 {
-	//casts to minimal abstraction level
-	const auto * objectCaster = dynamic_cast<const CGObjectInstance *>(parameters.caster);
-	const auto * heroCaster = dynamic_cast<const CGHeroInstance *>(parameters.caster);
-	const auto * boatGeneratorCaster = dynamic_cast<const IBoatGenerator *>(parameters.caster);
+	if(!parameters.caster->getHeroCaster())
+	{
+		logGlobal->error("Summoning boat without hero as actor");
+		return ESpellCastResult::ERROR;
+	}
 	
-	if(heroCaster && heroCaster->boat)
+	if(parameters.caster->getHeroCaster()->boat)
 	{
 		InfoWindow iw;
 		iw.player = parameters.caster->getCasterOwner();
@@ -158,9 +159,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
 		return ESpellCastResult::CANCEL;
 	}
 
-	int3 summonPos(-1, -1, -1);
-	if(boatGeneratorCaster)
-		summonPos = (boatGeneratorCaster)->bestLocation();
+	int3 summonPos = parameters.caster->getHeroCaster()->bestLocation();
 	
 	if(summonPos.x < 0)
 	{
@@ -187,22 +186,19 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
 	//try to find unoccupied boat to summon
 	const CGBoat * nearest = nullptr;
 	double dist = 0;
-	if(objectCaster)
+	for(const CGObjectInstance * obj : env->getMap()->objects)
 	{
-		for(const CGObjectInstance * obj : env->getMap()->objects)
+		if(obj && obj->ID == Obj::BOAT)
 		{
-			if(obj && obj->ID == Obj::BOAT)
-			{
-				const auto * b = dynamic_cast<const CGBoat *>(obj);
-				if(b->hero)
-					continue; //we're looking for unoccupied boat
+			const auto * b = dynamic_cast<const CGBoat *>(obj);
+			if(b->hero)
+				continue; //we're looking for unoccupied boat
 
-				double nDist = b->pos.dist2d(objectCaster->visitablePos());
-				if(!nearest || nDist < dist) //it's first boat or closer than previous
-				{
-					nearest = b;
-					dist = nDist;
-				}
+			double nDist = b->pos.dist2d(parameters.caster->getHeroCaster()->visitablePos());
+			if(!nearest || nDist < dist) //it's first boat or closer than previous
+			{
+				nearest = b;
+				dist = nDist;
 			}
 		}
 	}
@@ -221,11 +217,11 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
 		iw.text.addTxt(MetaString::GENERAL_TXT, 335); //There are no boats to summon.
 		env->apply(&iw);
 	}
-	else if(boatGeneratorCaster) //create boat
+	else //create boat
 	{
 		NewObject no;
 		no.ID = Obj::BOAT;
-		no.subID = boatGeneratorCaster->getBoatType();
+		no.subID = parameters.caster->getHeroCaster()->getBoatType();
 		no.pos = summonPos + int3(1,0,0);
 		env->apply(&no);
 	}

+ 8 - 0
lib/spells/ProxyCaster.cpp

@@ -118,6 +118,14 @@ void ProxyCaster::spendMana(ServerCallback * server, const int32_t spellCost) co
 		actualCaster->spendMana(server, spellCost);
 }
 
+const CGHeroInstance * ProxyCaster::getHeroCaster() const
+{
+	if(actualCaster)
+		return actualCaster->getHeroCaster();
+	
+	return nullptr;
+}
+
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 0
lib/spells/ProxyCaster.h

@@ -35,6 +35,7 @@ public:
 	void getCasterName(MetaString & text) const override;
 	void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;
 	void spendMana(ServerCallback * server, const int32_t spellCost) const override;
+	const CGHeroInstance * getHeroCaster() const override;
 
 protected:
 	const Caster * actualCaster;