Explorar o código

initial implementation.

AlexVinS %!s(int64=10) %!d(string=hai) anos
pai
achega
69c458e881

+ 9 - 6
client/battle/CBattleInterface.cpp

@@ -1188,19 +1188,22 @@ void CBattleInterface::hexLclicked(int whichOne)
 
 void CBattleInterface::stackIsCatapulting(const CatapultAttack & ca)
 {
-	for(auto it = ca.attackedParts.begin(); it != ca.attackedParts.end(); ++it)
+	if(ca.attacker != -1) //no shooting animation for spells like earthquake
 	{
 		const CStack * stack = curInt->cb->battleGetStackByID(ca.attacker);
-		addNewAnim(new CShootingAnimation(this, stack, it->destinationTile, nullptr, true, it->damageDealt));
+		for(auto attackInfo : ca.attackedParts)
+		{
+			addNewAnim(new CShootingAnimation(this, stack, attackInfo.destinationTile, nullptr, true, attackInfo.damageDealt));
+		}		
 	}
 
 	waitForAnims();
 
-	for(auto it = ca.attackedParts.begin(); it != ca.attackedParts.end(); ++it)
+	for(auto attackInfo : ca.attackedParts)
 	{
-		SDL_FreeSurface(siegeH->walls[it->attackedPart + 2]);
-		siegeH->walls[it->attackedPart + 2] = BitmapHandler::loadBitmap(
-			siegeH->getSiegeName(it->attackedPart + 2, curInt->cb->battleGetWallState(it->attackedPart)) );
+		SDL_FreeSurface(siegeH->walls[attackInfo.attackedPart + 2]);
+		siegeH->walls[attackInfo.attackedPart + 2] = BitmapHandler::loadBitmap(
+			siegeH->getSiegeName(attackInfo.attackedPart + 2, curInt->cb->battleGetWallState(attackInfo.attackedPart)));
 	}
 }
 

+ 0 - 1
lib/NetPacks.h

@@ -1555,7 +1555,6 @@ struct ObstaclesRemoved : public CPackForClient //3014
 };
 
 struct ELF_VISIBILITY CatapultAttack : public CPackForClient //3015
-
 {
 	struct AttackInfo
 	{

+ 77 - 0
lib/spells/BattleSpellMechanics.cpp

@@ -152,6 +152,83 @@ void DispellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast *
 	}
 }
 
+///EarthquakeMechanics
+void EarthquakeMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
+{
+	if(nullptr == parameters.cb->town)
+	{
+		env->complain("EarthquakeMechanics: not town siege");
+		return;		
+	}
+	
+	if(CGTownInstance::NONE == parameters.cb->town->fortLevel())
+	{
+		env->complain("EarthquakeMechanics: town has no fort");
+		return;		
+	}
+	
+	//start with all damagable parts	
+	std::set<EWallPart::EWallPart> possibleTargets = 
+	{
+		EWallPart::KEEP,
+		EWallPart::BOTTOM_TOWER, 
+		EWallPart::BOTTOM_WALL, 
+		EWallPart::BELOW_GATE, 
+		EWallPart::OVER_GATE, 
+		EWallPart::UPPER_WALL, 
+		EWallPart::UPPER_TOWER, 
+		EWallPart::GATE
+	};
+	
+	assert(possibleTargets.size() == EWallPart::PARTS_COUNT);
+	
+	vstd::erase_if(possibleTargets, [parameters](EWallPart::EWallPart part)
+	{
+		return (parameters.cb->si.wallState[part] == EWallState::DESTROYED) || (parameters.cb->si.wallState[part] == EWallState::NONE);
+	});
+	
+	if(0 == possibleTargets.size())
+	{
+		env->complain("EarthquakeMechanics: no target to attack");
+		return;
+	}	
+	
+	int targetsToAttack = 2;
+	
+	switch(parameters.spellLvl)
+	{
+	case 2:
+		targetsToAttack = 3;
+		break;
+	case 3:
+		targetsToAttack = 4;
+		break;
+	default:
+		break;
+	}
+	
+	CatapultAttack ca;
+	ca.attacker = -1;
+	
+	do
+	{
+		EWallPart::EWallPart target = *RandomGeneratorUtil::nextItem(possibleTargets, env->getRandomGenerator());
+		
+		CatapultAttack::AttackInfo attackInfo;
+		
+		attackInfo.damageDealt = 1;
+		attackInfo.attackedPart = target;
+		attackInfo.destinationTile = BattleHex::INVALID;
+		
+		ca.attackedParts.push_back(attackInfo);
+		
+		possibleTargets.erase(target);
+		targetsToAttack--;
+	}
+	while(targetsToAttack > 0 && possibleTargets.size() > 0);
+	
+	env->sendAndApply(&ca);
+}
 
 ///HypnotizeMechanics
 ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const

+ 8 - 0
lib/spells/BattleSpellMechanics.h

@@ -44,6 +44,14 @@ public:
 	void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
 };
 
+class DLL_LINKAGE EarthquakeMechanics : public DefaultSpellMechanics
+{
+public:
+	EarthquakeMechanics(CSpell * s): DefaultSpellMechanics(s){};
+protected:
+	void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;	
+};
+
 class DLL_LINKAGE HypnotizeMechanics : public DefaultSpellMechanics
 {
 public:

+ 2 - 0
lib/spells/ISpellMechanics.cpp

@@ -42,6 +42,8 @@ ISpellMechanics * ISpellMechanics::createMechanics(CSpell * s)
 		return new DispellMechanics(s);
 	case SpellID::DISPEL_HELPFUL_SPELLS:
 		return new DispellHelpfulMechanics(s);
+	case SpellID::EARTHQUAKE:
+		return new EarthquakeMechanics(s);
 	case SpellID::FIRE_WALL:
 	case SpellID::FORCE_FIELD:
 		return new WallMechanics(s);