浏览代码

- Second part of battle interface.
- Testing for Stack Artifacts feature.

DjWarmonger 13 年之前
父节点
当前提交
294276ea13
共有 4 个文件被更改,包括 142 次插入74 次删除
  1. 91 64
      client/BattleInterface/CBattleInterface.cpp
  2. 2 2
      client/BattleInterface/CBattleInterface.h
  3. 46 6
      lib/CArtHandler.cpp
  4. 3 2
      lib/CArtHandler.h

+ 91 - 64
client/BattleInterface/CBattleInterface.cpp

@@ -1859,11 +1859,8 @@ void CBattleInterface::battleTriggerEffect(const BattleTriggerEffect & bte)
 	switch (bte.effect)
 	{
 		case Bonus::HP_REGENERATION:
-			if( stack->hasBonusOfType(Bonus::HP_REGENERATION) || stack->hasBonusOfType(Bonus::FULL_HP_REGENERATION))
-			{
-				displayEffect(74, stack->position);
-				CCS->soundh->playSound(soundBase::REGENER);
-			}
+			displayEffect(74, stack->position);
+			CCS->soundh->playSound(soundBase::REGENER);
 			break;
 		case Bonus::MANA_DRAIN:
 			displayEffect(77, stack->position);
@@ -1935,7 +1932,7 @@ void CBattleInterface::activateStack()
 			creatureSpellToCast = spellcaster->subtype;
 
 		if(creatureSpellToCast < 0) //TODO proper way of detecting casters of positive spells
-			spellSelMode = FRIENDLY_CREATURE;
+			spellSelMode = FRIENDLY_CREATURE_SPELL;
 		else
 			spellSelMode = selectionTypeByPositiveness(*CGI->spellh->spells[creatureSpellToCast]);
 	}
@@ -1988,17 +1985,31 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
 		if (stack->hasBonusOfType (Bonus::SPELLCASTER))
 		{
 			 //TODO: poll possible spells
+			const CSpell * spell;
 			BOOST_FOREACH (Bonus * spellBonus, *stack->getBonuses (Selector::type(Bonus::SPELLCASTER)))
 			{
-				possibleActions.push_back (selectionTypeByPositiveness (*CGI->spellh->spells[spellBonus->subtype]));
+				spell = CGI->spellh->spells[spellBonus->subtype];
+				if (spell->isRisingSpell())
+				{
+					possibleActions.push_back (RISING_SPELL);
+				}
+				//possibleActions.push_back (NO_LOCATION);
+				//possibleActions.push_back (ANY_LOCATION);
+				//possibleActions.push_back (OTHER_SPELL);
+				else
+				{
+					switch (spellBonus->subtype)
+					{
+						case Spells::REMOVE_OBSTACLE:
+							possibleActions.push_back (OBSTACLE);
+							break;
+						default:
+							possibleActions.push_back (selectionTypeByPositiveness (*spell));
+							break;
+					}
+				}
+
 			}
-			//TODO: determine whether spell is rising
-			//possibleActions.push_back (RISING_SPELL);
-			//possibleActions.push_back (OBSTACLE);
-			//possibleActions.push_back (SACRIFICE);
-			//possibleActions.push_back (NO_LOCATION);
-			//possibleActions.push_back (ANY_LOCATION);
-			//possibleActions.push_back (OTHER_SPELL);
 		}
 		if (stack->hasBonusOfType (Bonus::RANDOM_SPELLCASTER))
 			possibleActions.push_back (RANDOM_GENIE_SPELL);
@@ -2570,11 +2581,11 @@ CBattleInterface::PossibleActions CBattleInterface::selectionTypeByPositiveness(
 	switch(spell.positiveness)
 	{
 	case CSpell::NEGATIVE :
-		return HOSTILE_CREATURE;
+		return HOSTILE_CREATURE_SPELL;
 	case CSpell::NEUTRAL:
 		return ANY_CREATURE;
 	case CSpell::POSITIVE:
-		return FRIENDLY_CREATURE;
+		return FRIENDLY_CREATURE_SPELL;
 	}
 	assert(0);
 	return NO_LOCATION; //should never happen
@@ -2608,7 +2619,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 	std::function<void()> realizeAction;
 
 	//helper lambda that appropriately realizes action / sets cursor and tooltip
-	//TODO: separate action at mouse move and clicking
 	auto realizeThingsToDo = [&]()
 	{
 		if(eventType == MOVE)
@@ -2635,15 +2645,16 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 	bool ourStack = false;
 	if (shere)
 		ourStack = shere->owner == curInt->playerID;
-
+	
+	//TODO: handle
 	bool noStackIsHovered = true; //will cause removing a blue glow
 	
 	localActions.clear();
 	BOOST_FOREACH (PossibleActions action, possibleActions)
 	{
-		bool legalAction = false;
-		bool illegalAction = false;
-		//TODO: copy actions avaliable to perform at this hex to localActions. set currentAction
+		bool legalAction = false; //this action is legal and can't be performed
+		bool illegalAction = false; //this action is not legal and should display message
+		
 		switch (action)
 		{ 
 			case MOVE_TACTICS:
@@ -2672,11 +2683,11 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				if(curInt->cb->battleCanShoot (activeStack, myNumber))
 					legalAction = true;
 				break;
-			case HOSTILE_CREATURE: //TODO: check spell immunity
+			case HOSTILE_CREATURE_SPELL: //TODO: check spell immunity
 				if (shere && !ourStack && isCastingPossibleHere (sactive, shere, myNumber))
 					legalAction = true;
 				break;
-			case FRIENDLY_CREATURE:
+			case FRIENDLY_CREATURE_SPELL:
 				if (shere && ourStack && isCastingPossibleHere (sactive, shere, myNumber))
 					legalAction = true;
 				break;
@@ -2704,14 +2715,14 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 			{
 				const ui8 skill = spellToCast ? getActiveHero()->getSpellSchoolLevel(CGI->spellh->spells[spellToCast->additionalInfo]) : 0; //skill level 
 				//TODO: creature can cast a spell with some skill / spellpower as well
-				//TODO: explicitely save spell_to_cast * CSpell, power, skill
+				//TODO: explicitely save power, skill
 				if (curInt->cb->battleCanTeleportTo(activeStack, myNumber, skill))
 					legalAction = true;
 				else
 					illegalAction = true;
 			}
 				break;
-			case OTHER_SPELL: //TODO
+			case SACRIFICE: //TODO
 				break;
 			case CATAPULT:
 				if (isCatapultAttackable(myNumber))
@@ -2744,6 +2755,10 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 			illegalAction = selectedAction;
 		else if (illegalActions.size())
 			illegalAction = illegalActions.front();
+		else if (shere && ourStack && shere->alive()) //last possibility - display info about our creature
+		{
+			currentAction = CREATURE_INFO;
+		}
 		else
 			illegalAction = INVALID; //we should never be here
 	}
@@ -2819,8 +2834,8 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 				consoleMsg = (boost::format(CGI->generaltexth->allTexts[296]) % shere->getName() % sactive->shots % estDmgText).str();
 			}
 				break;
-			case HOSTILE_CREATURE:
-			case FRIENDLY_CREATURE:
+			case HOSTILE_CREATURE_SPELL:
+			case FRIENDLY_CREATURE_SPELL:
 			case RISING_SPELL:
 			case RANDOM_GENIE_SPELL:
 				if (spellToCast) //TODO: merge hero spell and creature spell into it
@@ -2839,9 +2854,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 			case OBSTACLE:
 				consoleMsg = CGI->generaltexth->allTexts[550];
 				isCastingPossible = true;
-				break;
-			case OTHER_SPELL:
-				break;
+				break;;
 			case HEAL:
 				cursorFrame = ECursor::COMBAT_HEAL;
 				consoleMsg = (boost::format(CGI->generaltexth->allTexts[419]) % shere->getName()).str(); //Apply first aid to the %s
@@ -2854,15 +2867,36 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 			case CATAPULT:
 				cursorFrame = ECursor::COMBAT_SHOOT_CATAPULT;
 				realizeAction = [=]{ giveCommand(BattleAction::CATAPULT, myNumber, activeStack->ID); };
+			case CREATURE_INFO:
+			{
+				cursorFrame = ECursor::COMBAT_QUERY;
+				consoleMsg = (boost::format(CGI->generaltexth->allTexts[297]) % shere->getName()).str();
+				realizeAction = [=]{ GH.pushInt(createCreWindow(shere, true)); };
+	
+				//setting console text
+				const time_t curTime = time(NULL);
+				CCreatureAnimation *hoveredStackAnim = creAnims[shere->ID];
+
+				if (shere->ID != mouseHoveredStack
+					&& curTime > lastMouseHoveredStackAnimationTime + HOVER_ANIM_DELTA
+					&& hoveredStackAnim->getType() == CCreatureAnim::HOLDING 
+					&& hoveredStackAnim->framesInGroup(CCreatureAnim::MOUSEON) > 0)
+				{
+					hoveredStackAnim->playOnce(CCreatureAnim::MOUSEON);
+					lastMouseHoveredStackAnimationTime = curTime;
+				}
+				noStackIsHovered = false;
+				mouseHoveredStack = shere->ID;
+			}
 				break;
 		}
 	}
-	else
+	else //no possible valid action, display message
 	{
 		switch (illegalAction)
 		{
-			case HOSTILE_CREATURE:
-			case FRIENDLY_CREATURE:
+			case HOSTILE_CREATURE_SPELL:
+			case FRIENDLY_CREATURE_SPELL:
 			case RISING_SPELL:
 			case RANDOM_GENIE_SPELL:
 				cursorFrame = ECursor::COMBAT_BLOCKED;
@@ -2883,19 +2917,33 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 		cursorFrame = 0;
 		if(consoleMsg.empty() && sp)
 			consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[26]) % sp->name); //Cast %s
-
+		
 		realizeAction = [=]
 		{
-			if(creatureCasting)
-			{
-				giveCommand(BattleAction::MONSTER_SPELL, myNumber, sactive->ID, creatureSpellToCast);
-			}
-			else
+			switch (sp->id)
 			{
-				spellToCast->destinationTile = myNumber;
-				curInt->cb->battleMakeAction(spellToCast);
-				endCastingSpell();
+				case TELEPORT: //TODO: choose second target for Teleport or Sacrifice
+					possibleActions.clear();
+					possibleActions.push_back (TELEPORT);
+					break;
+				case SACRIFICE:
+					possibleActions.clear();
+					possibleActions.push_back (SACRIFICE);
+					break;
+				default:
+					if(creatureCasting)
+					{
+						giveCommand(BattleAction::MONSTER_SPELL, myNumber, sactive->ID, creatureSpellToCast);
+					}
+					else
+					{
+						spellToCast->destinationTile = myNumber;
+						curInt->cb->battleMakeAction(spellToCast);
+						endCastingSpell();
+					}
+					break;
 			}
+
 		};
 	}
 
@@ -2903,32 +2951,11 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 	if(noStackIsHovered)
 		mouseHoveredStack = -1;
 
-	if (shere && ourStack && shere->alive()) //TODO: handle hover properly
-	{
-		cursorFrame = ECursor::COMBAT_QUERY;
-		consoleMsg = (boost::format(CGI->generaltexth->allTexts[297]) % shere->getName()).str();
-		realizeAction = [=]{ GH.pushInt(createCreWindow(shere, true)); };
-	
-		//setting console text
-		const time_t curTime = time(NULL);
-		CCreatureAnimation *hoveredStackAnim = creAnims[shere->ID];
-
-		if (shere->ID != mouseHoveredStack
-			&& curTime > lastMouseHoveredStackAnimationTime + HOVER_ANIM_DELTA
-			&& hoveredStackAnim->getType() == CCreatureAnim::HOLDING 
-			&& hoveredStackAnim->framesInGroup(CCreatureAnim::MOUSEON) > 0)
-		{
-			hoveredStackAnim->playOnce(CCreatureAnim::MOUSEON);
-			lastMouseHoveredStackAnimationTime = curTime;
-		}
-		noStackIsHovered = false;
-		mouseHoveredStack = shere->ID;
-	}
 }
 
 bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CStack * shere, BattleHex myNumber)
 {
-	creatureCasting = (spellDestSelectMode >= NO_LOCATION && spellDestSelectMode <= OTHER_SPELL) && //what does it really check?
+	creatureCasting = (spellDestSelectMode >= NO_LOCATION && spellDestSelectMode <= RANDOM_GENIE_SPELL) && //what does it really check?
 							stackCanCastSpell && shere != sactive;
 							//TODO: use currentAction
 							

+ 2 - 2
client/BattleInterface/CBattleInterface.h

@@ -93,10 +93,10 @@ class CBattleInterface : public CIntObject
 {
 	enum PossibleActions // actions performed at l-click
 	{
-		INVALID = -1,
+		INVALID = -1, CREATURE_INFO,
 		MOVE_TACTICS, CHOOSE_TACTICS_STACK,
 		MOVE_STACK, ATTACK, WALK_AND_ATTACK, ATTACK_AND_RETURN, SHOOT, //OPEN_GATE, //we can open castle gate during siege
-		NO_LOCATION, ANY_LOCATION, FRIENDLY_CREATURE, HOSTILE_CREATURE, RISING_SPELL, ANY_CREATURE, OBSTACLE, TELEPORT, SACRIFICE, RANDOM_GENIE_SPELL, OTHER_SPELL,
+		NO_LOCATION, ANY_LOCATION, FRIENDLY_CREATURE_SPELL, HOSTILE_CREATURE_SPELL, RISING_SPELL, ANY_CREATURE, OBSTACLE, TELEPORT, SACRIFICE, RANDOM_GENIE_SPELL,
 		CATAPULT, HEAL, RISE_DEMONS
 	};
 private:

+ 46 - 6
lib/CArtHandler.cpp

@@ -188,6 +188,11 @@ std::string CArtifact::nodeName() const
 // // 	//boost::algorithm::replace_first(description, "[spell name]", VLC->spellh->spells[spellid].name);
 // }
 
+void CArtifact::setDescription (std::string desc)
+{
+	description = desc;
+}
+
 CArtHandler::CArtHandler()
 {
 	VLC->arth = this;
@@ -475,9 +480,10 @@ void CArtHandler::getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &ou
 		out.push_back(art);
 	}
 }
-void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int subtype, int valType, ILimiter * limiter )
+void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int subtype, int valType, ILimiter * limiter, int additionalInfo)
 {
 	Bonus *added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,aid,subtype);
+	added->additionalInfo = additionalInfo;
 	added->valType = valType;
 	added->limiter.reset(limiter);
 	if(type == Bonus::MORALE || type == Bonus::LUCK)
@@ -487,9 +493,10 @@ void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int sub
 	artifacts[aid]->addNewBonus(added);
 }
 
-void CArtHandler::giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype, IPropagator* propagator /*= NULL*/)
+void CArtHandler::giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype, IPropagator* propagator /*= NULL*/, int additionalInfo)
 {
 	Bonus *added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,aid,subtype);
+	added->additionalInfo = additionalInfo;
 	added->valType = Bonus::BASE_NUMBER;
 	added->propagator.reset(propagator);
 	if(type == Bonus::MORALE || type == Bonus::LUCK)
@@ -752,10 +759,43 @@ void CArtHandler::addBonuses()
 		makeItCreatureArt(142);
 		makeItCreatureArt(143);
 		makeItCreatureArt(156);
-		giveArtBonus(141, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Magic Wans
-		giveArtBonus(142, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Tower Arrow
-		giveArtBonus(143, Bonus::STACK_HEALTH, +400, -1, Bonus::PERCENT_TO_BASE); //Monster's Power
-		giveArtBonus(156, Bonus::STACK_HEALTH, +2); //Warlord's banner
+		//Magic Wand
+		giveArtBonus(141, Bonus::CASTS, 10);
+		giveArtBonus(141, Bonus::SPELLCASTER, 0, Spells::IMPLOSION);
+		giveArtBonus(141, Bonus::SPELLCASTER, 0, Spells::FIREBALL);
+		giveArtBonus(141, Bonus::RANDOM_SPELLCASTER, 0);
+		giveArtBonus(141, Bonus::DAEMON_SUMMONING, 10, 63); //rise vampire lords
+		giveArtBonus(141, Bonus::ENCHANTER, 0, Spells::LIGHTNING_BOLT, NULL, 2);
+		giveArtBonus(141, Bonus::REBIRTH, 1, 1);
+		giveArtBonus(141, Bonus::MANA_DRAIN, 10);
+		giveArtBonus(141, Bonus::HEALER, 25);
+		artifacts[141].get()->setDescription ("Casts Implosion / Fireball, random Genie spell, summons Vampire Lords from corpses, casts Lighthning Bolt every 2 turns, rebirths at least one creature, drains enemy mana and heals");
+		//Tower Arrow
+		giveArtBonus(142, Bonus::NO_DISTANCE_PENALTY, 0);
+		giveArtBonus(142, Bonus::ADDITIONAL_ATTACK, 2);
+		giveArtBonus(142, Bonus::SPELL_LIKE_ATTACK, 1, Spells::INFERNO);
+		giveArtBonus(142, Bonus::CATAPULT, 0);
+		giveArtBonus(142, Bonus::ACID_BREATH, 20);
+		giveArtBonus(142, Bonus::SHOTS, 200, 0, Bonus::PERCENT_TO_BASE);
+		giveArtBonus(142, Bonus::SPELL_BEFORE_ATTACK, 1, Spells::AGE, NULL, 50);
+		giveArtBonus(142, Bonus::SPELL_AFTER_ATTACK, 1, Spells::BERSERK, NULL, 50);
+		giveArtBonus(142, Bonus::SPELL_AFTER_ATTACK, 1, Spells::POISON, NULL, 50);
+		giveArtBonus(142, Bonus::SPELL_AFTER_ATTACK, 1, Spells::DISRUPTING_RAY, NULL, 50);
+		artifacts[142].get()->setDescription ("Tripple shots, tripple attack, casts various spells during attack, attacks have range of Inferno, no distance penalty, catapult");
+		//Monster's Power
+		giveArtBonus(143, Bonus::STACK_HEALTH, +100, -1, Bonus::PERCENT_TO_BASE);
+		giveArtBonus(143, Bonus::CREATURE_DAMAGE, +100, 2, Bonus::PERCENT_TO_ALL);
+		giveArtBonus(143, Bonus::HP_REGENERATION, 50);
+		giveArtBonus(143, Bonus::NO_RETALIATION, 0);
+		giveArtBonus(143, Bonus::RETURN_AFTER_STRIKE, 0);
+		giveArtBonus(143, Bonus::ATTACKS_ALL_ADJACENT, 0);
+		giveArtBonus(143, Bonus::SPELL_RESISTANCE_AURA, 100);
+		giveArtBonus(143, Bonus::DIRECT_DAMAGE_IMMUNITY, 0);
+		artifacts[143].get()->setDescription ("Double health, double max damage, hp regeneration, can't retaliate, return after strike, attack all around, 100% spell reisstance aura, immune to direct damage spells");
+		//Warlord's banner
+		giveArtBonus(156, Bonus::STACK_HEALTH, +2);
+		artifacts[156].get()->setDescription ("+2 stack HP");
+
 	}
 }
 

+ 3 - 2
lib/CArtHandler.h

@@ -49,6 +49,7 @@ public:
 	const std::string &Name() const; //getter
 	const std::string &Description() const; //getter
 	bool isBig () const;
+	void setDescription (std::string desc);
 
 	int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
 	std::string nodeName() const OVERRIDE;
@@ -217,8 +218,8 @@ public:
 
 class DLL_LINKAGE CArtHandler //handles artifacts
 {
-	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER, ILimiter * limiter = NULL);
-	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype, IPropagator* propagator);
+	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER, ILimiter * limiter = NULL, int additionalinfo = 0);
+	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype, IPropagator* propagator, int additionalinfo = 0);
 public:
 	std::vector<CArtifact*> treasures, minors, majors, relics;
 	std::vector< ConstTransitivePtr<CArtifact> > artifacts;