mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Added special slots for war machines and arrow towers
This commit is contained in:
		| @@ -469,7 +469,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp | ||||
| 		auto handleWarMachine= [&](int side, ArtifactPosition artslot, CreatureID cretype, BattleHex hex) | ||||
| 		{ | ||||
| 			if(heroes[side] && heroes[side]->getArt(artslot)) | ||||
| 				stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID(255), hex)); | ||||
| 				stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID::WAR_MACHINES_SLOT, hex)); | ||||
| 		}; | ||||
|  | ||||
| 		handleWarMachine(0, ArtifactPosition::MACH1, CreatureID::BALLISTA, 52); | ||||
| @@ -526,15 +526,15 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp | ||||
| 	if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL) | ||||
| 	{ | ||||
| 		// keep tower | ||||
| 		CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -2); | ||||
| 		CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -2); | ||||
| 		stacks.push_back(stack); | ||||
|  | ||||
| 		if (curB->town->fortLevel() >= CGTownInstance::CASTLE) | ||||
| 		{ | ||||
| 			// lower tower + upper tower | ||||
| 			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -4); | ||||
| 			CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -4); | ||||
| 			stacks.push_back(stack); | ||||
| 			stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -3); | ||||
| 			stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -3); | ||||
| 			stacks.push_back(stack); | ||||
| 		} | ||||
|  | ||||
| @@ -712,7 +712,7 @@ std::shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile) | ||||
|  | ||||
| BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType) | ||||
| { | ||||
| 	static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap =  | ||||
| 	static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap = | ||||
| 	{ | ||||
| 		{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD}, | ||||
| 		{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND}, | ||||
| @@ -1141,7 +1141,7 @@ bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed | ||||
|  | ||||
| ui8 CStack::counterAttacksTotal() const | ||||
| { | ||||
| 	//after dispell bonus should remain during current round  | ||||
| 	//after dispell bonus should remain during current round | ||||
| 	ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION); | ||||
| 	vstd::amax(counterAttacksTotalCache, val); | ||||
| 	return counterAttacksTotalCache; | ||||
| @@ -1183,9 +1183,9 @@ ui32 CStack::calculateHealedHealthPoints(ui32 toHeal, const bool resurrect) cons | ||||
| ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) const | ||||
| { | ||||
| 	int skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id)); | ||||
| 	 | ||||
|  | ||||
| 	vstd::abetween(skill, 0, 3); | ||||
| 	 | ||||
|  | ||||
| 	return skill; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -19,7 +19,10 @@ | ||||
| #include "spells/CSpellHandler.h" | ||||
|  | ||||
| const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2); | ||||
| const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255); | ||||
| const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3); | ||||
| const SlotID SlotID::WAR_MACHINES_SLOT = SlotID(-4); | ||||
| const SlotID SlotID::ARROW_TOWERS_SLOT = SlotID(-5); | ||||
|  | ||||
| const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253); | ||||
| const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254); | ||||
| const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255); | ||||
|   | ||||
| @@ -237,6 +237,8 @@ class SlotID : public BaseForID<SlotID, si32> | ||||
|  | ||||
| 	DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER; | ||||
| 	DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///<for all summoned creatures, only during battle | ||||
| 	DLL_LINKAGE static const SlotID WAR_MACHINES_SLOT; ///<for all war machines during battle | ||||
| 	DLL_LINKAGE static const SlotID ARROW_TOWERS_SLOT; ///<for all arrow towers during battle | ||||
|  | ||||
| 	bool validSlot() const | ||||
| 	{ | ||||
| @@ -444,11 +446,11 @@ namespace ESpellCastProblem | ||||
|  | ||||
| namespace ECastingMode | ||||
| { | ||||
| 	enum ECastingMode  | ||||
| 	enum ECastingMode | ||||
| 	{ | ||||
| 		HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack | ||||
| 		MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING, | ||||
| 		SPELL_LIKE_ATTACK,  | ||||
| 		SPELL_LIKE_ATTACK, | ||||
| 		PASSIVE_CASTING//f.e. opening battle spells | ||||
| 	}; | ||||
| } | ||||
|   | ||||
| @@ -3914,7 +3914,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) | ||||
| 			BattleStackAdded bsa; | ||||
| 			bsa.attacker = summoner->attackerOwned; | ||||
|  | ||||
| 			bsa.creID = summonedType;  | ||||
| 			bsa.creID = summonedType; | ||||
| 			ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum()); | ||||
| 			ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect | ||||
|  | ||||
| @@ -5887,7 +5887,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl | ||||
| 	PlayerColor color = army->tempOwner; | ||||
| 	if(color == PlayerColor::UNFLAGGABLE) | ||||
| 		color = PlayerColor::NEUTRAL; | ||||
| 		 | ||||
|  | ||||
| 	auto killStack = [&, this](const SlotID slot, const CStackInstance * instance) | ||||
| 	{ | ||||
| 		StackLocation sl(army, slot); | ||||
| @@ -5928,47 +5928,67 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl | ||||
|  | ||||
| 	for(CStack *st : bat->stacks) | ||||
| 	{ | ||||
| 		if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks | ||||
| 		if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account temporary summoned stacks | ||||
| 			continue; | ||||
| 		if (st->owner != color) //remove only our stacks | ||||
| 			continue; | ||||
|  | ||||
| 		logGlobal->debugStream() << "Calculating casualties for " << st->nodeName(); | ||||
|  | ||||
| 		//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor | ||||
| 		st->count = std::max (0, st->count - st->resurrected); | ||||
|  | ||||
| 		if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts? | ||||
| 		if(st->slot == SlotID::ARROW_TOWERS_SLOT) | ||||
| 		{ | ||||
| 			//do nothing | ||||
| 			logGlobal->debugStream() << "Ignored arrow towers stack"; | ||||
| 		} | ||||
| 		else if(st->slot == SlotID::WAR_MACHINES_SLOT) | ||||
| 		{ | ||||
| 			auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber); | ||||
| 			//catapult artifact remain even if "creature" killed in siege | ||||
| 			if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT) | ||||
|  | ||||
| 			if(warMachine == ArtifactID::NONE) | ||||
| 			{ | ||||
| 				logGlobal->errorStream() << "Invalid creature in war machine virtual slot: " << st->nodeName(); | ||||
| 			} | ||||
| 			//catapult artifact remain even if "creature" killed in siege | ||||
| 			else if(warMachine != ArtifactID::CATAPULT && !st->count) | ||||
| 			{ | ||||
| 				logGlobal->debugStream() << "War machine has been destroyed"; | ||||
| 				auto hero = dynamic_ptr_cast<CGHeroInstance> (army); | ||||
| 				if (hero) | ||||
| 					removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true))); | ||||
| 				else | ||||
| 					logGlobal->errorStream() << "War machine in army without hero"; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		if(army->slotEmpty(st->slot)) | ||||
| 		else if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER) | ||||
| 		{ | ||||
| 			if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0) | ||||
| 			if(st->alive() && st->count > 0) | ||||
| 			{ | ||||
| 				logGlobal->debugStream() << "Stack has been permanently summoned"; | ||||
| 				//this stack was permanently summoned | ||||
| 				const CreatureID summonedType = st->type->idNumber; | ||||
| 				summoned[summonedType] += st->count; | ||||
| 			}			 | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		else if(st->base && !army->slotEmpty(st->slot)) | ||||
| 		{ | ||||
| 			if(st->count == 0 || !st->alive()) | ||||
| 			{ | ||||
| 				killStack(st->slot, st->base); | ||||
| 				logGlobal->debugStream() << "Stack has been destroyed"; | ||||
| 			} | ||||
| 			else if(st->count < army->getStackCount(st->slot)) | ||||
| 			{			 | ||||
| 			{ | ||||
| 				StackLocation sl(army, st->slot); | ||||
| 				newStackCounts.push_back(TStackAndItsNewCount(sl, st->count)); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			logGlobal->warnStream() << "Unhandled stack " << st->nodeName(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user