Quellcode durchsuchen

Creature spells are now functional.
It includes Master Genie, Archangel, Faerie Dragon & Elementals

DjWarmonger vor 14 Jahren
Ursprung
Commit
f4fc77ccb8
6 geänderte Dateien mit 95 neuen und 20 gelöschten Zeilen
  1. 41 9
      client/CBattleInterface.cpp
  2. 6 6
      config/creatures.json
  3. 3 0
      lib/BattleState.cpp
  4. 1 1
      lib/HeroBonus.h
  5. 4 3
      lib/NetPacksLib.cpp
  6. 40 1
      server/CGameHandler.cpp

+ 41 - 9
client/CBattleInterface.cpp

@@ -2140,8 +2140,8 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 							std::ostringstream estDmg;
 							estDmg << estimatedDmg.first << " - " << estimatedDmg.second;
 							//printing
-							sprintf(buf, CGI->generaltexth->allTexts[36].c_str(), shere->count == 1 ? shere->getCreature()->nameSing.c_str() : shere->getCreature()->namePl.c_str(),
-								estDmg.str().c_str());
+							sprintf(buf, CGI->generaltexth->allTexts[36].c_str(),
+								shere->count == 1 ? shere->getCreature()->nameSing.c_str() : shere->getCreature()->namePl.c_str(), estDmg.str().c_str());
 							console->alterTxt = buf;
 							console->whoSetAlter = 0;
 						}
@@ -2170,19 +2170,20 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 			else //available tile
 			{
 				//setting console text and cursor
-				const CStack *sactive = activeStack;
-				if(sactive) //there can be a moment when stack is dead ut next is not yet activated
+				if(activeStack) //there can be a moment when stack is dead ut next is not yet activated
 				{
 					char buf[500];
-					if(sactive->hasBonusOfType(Bonus::FLYING))
+					if(activeStack->hasBonusOfType(Bonus::FLYING))
 					{
 						CCS->curh->changeGraphic(1,2);
-						sprintf(buf, CGI->generaltexth->allTexts[295].c_str(), sactive->count == 1 ? sactive->getCreature()->nameSing.c_str() : sactive->getCreature()->namePl.c_str());
+						sprintf(buf, CGI->generaltexth->allTexts[295].c_str(),
+							activeStack->count == 1 ? activeStack->getCreature()->nameSing.c_str() : activeStack->getCreature()->namePl.c_str());
 					}
 					else
 					{
 						CCS->curh->changeGraphic(1,1);
-						sprintf(buf, CGI->generaltexth->allTexts[294].c_str(), sactive->count == 1 ? sactive->getCreature()->nameSing.c_str() : sactive->getCreature()->namePl.c_str());
+						sprintf(buf, CGI->generaltexth->allTexts[294].c_str(),
+							activeStack->count == 1 ? activeStack->getCreature()->nameSing.c_str() : activeStack->getCreature()->namePl.c_str());
 					}
 
 					console->alterTxt = buf;
@@ -2894,11 +2895,42 @@ void CBattleInterface::hexLclicked(int whichOne)
 				endCastingSpell();
 			}
 		}
-		else //we don't aim for spell target
+		else //we don't aim for spell target area
 		{
 			bool walkableTile = false;
 			if (dest)
 			{
+				bool ourStack = actSt->owner == dest->owner;
+
+				//try to cast stack spell first
+				if (stackCanCastSpell && spellSelMode > STACK_SPELL_CANCELLED) //player did not decide to cancel this spell
+				{
+					if ((int)creatureSpellToCast > -1) //use randomized spell (Faerie Dragon), or only avaliable spell (Archangel)
+					{
+						const CSpell * spell =  CGI->spellh->spells[creatureSpellToCast];
+						if (curInt->cb->battleCanCastThisSpell(spell, THex(whichOne)) == SpellCasting::OK)
+						{
+							if (spell->positiveness > -1 && ourStack || spell->positiveness < 1 && !ourStack)
+							{
+								giveCommand(BattleAction::MONSTER_SPELL, whichOne, actSt->ID, creatureSpellToCast);
+							}
+						}
+					}
+					else if (ourStack) //must have only random positive spell (genie)
+					{
+						if (dest != actSt) //can't cast on itself
+						{
+							int spellID = curInt->cb->battleGetRandomStackSpell(dest, CBattleInfoCallback::RANDOM_GENIE);
+							if (spellID > -1) //can cast any spell on target stack
+							{
+								giveCommand(BattleAction::MONSTER_SPELL, whichOne, actSt->ID, spellID); //use randomized spell
+							}
+						}
+					}
+					creatureSpellToCast = -1;
+					return; //no further action after cast
+				}
+
 				if (dest->alive())
 				{
 					if(dest->owner != actSt->owner && curInt->cb->battleCanShoot(activeStack, whichOne)) //shooting
@@ -2906,7 +2938,7 @@ void CBattleInterface::hexLclicked(int whichOne)
 						CCS->curh->changeGraphic(1, 6); //cursor should be changed
 						giveCommand (BattleAction::SHOOT, whichOne, activeStack->ID);
 					}
-					else if(dest->owner != actSt->owner) //attacking
+					else if(!ourStack) //attacking
 					{
 						const CStack * actStack = activeStack;
 						int attackFromHex = -1; //hex from which we will attack chosen stack

+ 6 - 6
config/creatures.json

@@ -396,8 +396,8 @@
 				"level": 5,
 				"name": [ "Caliph" ],
 				"faction": 2,
-				"ability_add": [ [ "CREATURE_ENCHANT_POWER", 5, 0, 0 ],		//spells last 6 turns
-							   	 [ "RANDOM_SPELLCASTER", 0, 0, 0 ],  		//master genies cast spells
+				"ability_add": [ [ "CREATURE_ENCHANT_POWER", 5, 0, 0 ],		//spells last 5 turns
+							   	 [ "RANDOM_SPELLCASTER", 2, 0, 0 ],  		//master genies cast spells on advanced level
 								 [ "CASTS", 3, 0, 0],
 								 [ "HATE", 50, 53, 0 ],
 								 [ "HATE", 50, 52, 0 ] ],				  	//master genies hate efreet sultans
@@ -1293,7 +1293,7 @@
 				"faction": 8,
 				"ability_add": [ [ "NON_LIVING", 0, 0, 0 ],				
 							   	 [ "DOUBLE_WIDE", 0, 0, 0 ],					//ice elemental should be treated as double-wide
-								 [ "CREATURE_ENCHANT_POWER", 5, 0, 0 ],
+								 [ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 								 [ "CASTS", 3, 0, 0 ],
 								 [ "SPELLCASTER", 2, 32, 0 ]], 				
 				"defname": "CICEE.DEF",
@@ -1307,7 +1307,7 @@
 				"name": [ "StoneElemental" ],
 				"faction": 8,
 				"ability_add": [ [ "NON_LIVING", 0, 0, 0 ],						//magma elementals shouldn't get morale
-								[ "CREATURE_ENCHANT_POWER", 5, 0, 0 ],
+								[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 								[ "CASTS", 3, 0, 0 ],
 								[ "SPELLCASTER", 2, 33, 0 ]],
 				"defname": "CSTONE.DEF"
@@ -1319,7 +1319,7 @@
 				"name": [ "StormElemental" ],
 				"faction": 8,
 				"ability_add": [ [ "NON_LIVING", 0, 0, 0 ],						//storm elementals shouldn't get morale
-								[ "CREATURE_ENCHANT_POWER", 5, 0, 0 ],
+								[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 								[ "CASTS", 3, 0, 0 ],
 								[ "SPELLCASTER", 2, 30, 0 ]],				
 				"defname": "CSTORM.DEF",
@@ -1334,7 +1334,7 @@
 				"name": [ "ElectricityElemental" ],
 				"faction": 8,									
 				"ability_add": [ [ "NON_LIVING", 0, 0, 0 ] ,					//energy elementals shouldn't get morale //Crystal Dragons do not fly
-								[ "CREATURE_ENCHANT_POWER", 5, 0, 0 ],
+								[ "CREATURE_ENCHANT_POWER", 6, 0, 0 ],
 								[ "CASTS", 3, 0, 0 ],
 								[ "SPELLCASTER", 2, 31, 0 ]],						
 				"defname": "CNRG.DEF"

+ 3 - 0
lib/BattleState.cpp

@@ -2007,6 +2007,9 @@ TSpell BattleInfo::getRandomBeneficialSpell(const CStack * subject) const
 						continue;
 				}
 					break;
+				case 65: //clone - not allowed
+					continue;
+					break;
 			}
 			possibleSpells.push_back(i);
 		}

+ 1 - 1
lib/HeroBonus.h

@@ -102,7 +102,7 @@ namespace PrimarySkill
 	BONUS_NAME(SPELL_DAMAGE_REDUCTION) /*eg. golems; value - reduction in %, subtype - spell school; -1 - all, 0 - air, 1 - fire, 2 - water, 3 - earth*/ \
 	BONUS_NAME(NO_WALL_PENALTY)							\
 	BONUS_NAME(NON_LIVING) /*eg. gargoyle*/				\
-	BONUS_NAME(RANDOM_SPELLCASTER) /*eg. master genie, For Genie spells, subtype - spell id */ \
+	BONUS_NAME(RANDOM_SPELLCASTER) /*eg. master genie, val - level*/ \
 	BONUS_NAME(BLOCKS_RETALIATION) /*eg. naga*/			\
 	BONUS_NAME(SPELL_IMMUNITY) /*subid - spell id*/		\
 	BONUS_NAME(MANA_CHANNELING) /*value in %, eg. familiar*/ \

+ 4 - 3
lib/NetPacksLib.cpp

@@ -1278,15 +1278,16 @@ DLL_EXPORT void BattleStackAdded::applyGs(CGameState *gs)
 
 DLL_EXPORT void BattleSetStackProperty::applyGs(CGameState *gs)
 {
+	CStack * stack = gs->curB->getStack(stackID);
 	switch (which)
 	{
 		case CASTS:
 		{
 			if (absolute)
-				gs->curB->stacks[stackID]->casts = val;
+				stack->casts = val;
 			else
-				gs->curB->stacks[stackID]->casts--;
-			amax(gs->curB->stacks[stackID]->casts, 0);
+				stack->casts += val;
+			amax(stack->casts, 0);
 			break;
 		}
 	}

+ 40 - 1
server/CGameHandler.cpp

@@ -3312,12 +3312,45 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 
 				BattleSetStackProperty ssp;
 				ssp.stackID = ba.stackNumber;
-				ssp.which = BattleSetStackProperty::CASTS;
+				ssp.which = BattleSetStackProperty::CASTS; //reduce number of casts
 				ssp.val = -1;
 				ssp.absolute = false;
 				sendAndApply(&ssp);
 			}
 
+			sendAndApply(&end_action);
+			break;
+		}
+		case BattleAction::MONSTER_SPELL:
+		{
+			StartAction start_action(ba);
+			sendAndApply(&start_action);
+
+			CStack * stack = gs->curB->getStack(ba.stackNumber);
+			int spellID = ba.additionalInfo;
+			THex destination(ba.destinationTile);
+
+			int spellLvl = 0;
+			Bonus * bonus = stack->getBonus(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
+			if (bonus)
+				amax(spellLvl, bonus->val);
+			bonus = stack->getBonus(Selector::type(Bonus::RANDOM_SPELLCASTER));
+			if (bonus)
+				amax(spellLvl, bonus->val);
+			amin (spellLvl, 3);
+
+			int casterSide = gs->curB->whatSide(stack->owner);
+			const CGHeroInstance * secHero = gs->curB->getHero(gs->curB->theOtherPlayer(stack->owner));
+
+			handleSpellCasting(spellID, spellLvl, destination, casterSide, stack->owner, NULL, secHero, 0, SpellCasting::CREATURE_ACTIVE_CASTING, stack);
+
+			BattleSetStackProperty ssp;
+			ssp.stackID = ba.stackNumber;
+			ssp.which = BattleSetStackProperty::CASTS; //reduce number of casts
+			ssp.val = -1;
+			ssp.absolute = false;
+			sendAndApply(&ssp);
+
 			sendAndApply(&end_action);
 			break;
 		}
@@ -3520,7 +3553,10 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
 				if (unitSpellPower)
 					sc.dmgToDisplay = spellDamage = stack->count * unitSpellPower; //TODO: handle immunities
 				else //Faerie Dragon
+				{
 					usedSpellPower = stack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * stack->count / 100;
+					sc.dmgToDisplay = 0;
+				}
 			}
 			for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
 			{
@@ -3536,7 +3572,10 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
 				if (spellDamage)
 					bsa.damageAmount = spellDamage;
 				else
+				{
 					bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
+					sc.dmgToDisplay += bsa.damageAmount;
+				}
 				bsa.stackAttacked = (*it)->ID;
 				bsa.attackerID = -1;
 				(*it)->prepareAttacked(bsa);