mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Towards duel support.
This commit is contained in:
		| @@ -261,7 +261,7 @@ BattleAction CBattleLogic::MakeDecision(int stackID) | ||||
| 	const CStack *currentStack = m_cb->battleGetStackByID(stackID); | ||||
| 	if(currentStack->position < 0 || currentStack->getCreature()->idNumber == 147) //turret or first aid kit | ||||
| 	{ | ||||
| 		return MakeDefend(stackID); | ||||
| 		return BattleAction::makeDefend(currentStack); | ||||
| 	} | ||||
| 	MakeStatistics(stackID); | ||||
|  | ||||
| @@ -285,11 +285,11 @@ BattleAction CBattleLogic::MakeDecision(int stackID) | ||||
| 	if (additionalInfo == -1 || creatures.empty()) | ||||
| 	{ | ||||
| 		// defend | ||||
| 		return MakeDefend(stackID); | ||||
| 		return BattleAction::makeDefend(currentStack); | ||||
| 	} | ||||
| 	else if (additionalInfo == -2) | ||||
| 	{ | ||||
| 		return MakeWait(stackID); | ||||
| 		return BattleAction::makeWait(currentStack); | ||||
| 	} | ||||
|  | ||||
| 	list<int>::iterator it, eit; | ||||
| @@ -472,26 +472,6 @@ std::vector<int> CBattleLogic::GetAvailableHexesForAttacker(const CStack *defend | ||||
| 	return fields; | ||||
| } | ||||
|  | ||||
| BattleAction CBattleLogic::MakeDefend(int stackID) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = m_side; | ||||
| 	ba.actionType = action_defend; | ||||
| 	ba.stackNumber = stackID; | ||||
| 	ba.additionalInfo = -1; | ||||
| 	return ba; | ||||
| } | ||||
|  | ||||
| BattleAction CBattleLogic::MakeWait(int stackID) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = m_side; | ||||
| 	ba.actionType = action_wait; | ||||
| 	ba.stackNumber = stackID; | ||||
| 	ba.additionalInfo = -1; | ||||
| 	return ba; | ||||
| } | ||||
|  | ||||
| BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID) | ||||
| { | ||||
| 	const CStack *attackerStack = m_cb->battleGetStackByID(attackerID), | ||||
| @@ -501,19 +481,12 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID) | ||||
| 	//don't attack ourselves | ||||
| 	if(destinationStack->attackerOwned == !m_side) | ||||
| 	{ | ||||
| 		return MakeDefend(attackerID); | ||||
| 		return BattleAction::makeDefend(attackerStack); | ||||
| 	} | ||||
|  | ||||
| 	if (m_cb->battleCanShoot(attackerID, m_cb->battleGetPos(destinationID))) | ||||
| 	if (m_cb->battleCanShoot(attackerID, m_cb->battleGetPos(destinationID)))	// shoot | ||||
| 	{ | ||||
| 		// shoot | ||||
| 		BattleAction ba; | ||||
| 		ba.side = m_side; | ||||
| 		ba.additionalInfo = -1; | ||||
| 		ba.actionType = action_shoot; // shoot | ||||
| 		ba.stackNumber = attackerID; | ||||
| 		ba.destinationTile = (ui16)m_cb->battleGetPos(destinationID); | ||||
| 		return ba; | ||||
| 		return BattleAction::makeShotAttack(attackerStack, destinationStack); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @@ -522,7 +495,7 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID) | ||||
| 		std::vector<int> av_tiles = GetAvailableHexesForAttacker(m_cb->battleGetStackByID(destinationID), m_cb->battleGetStackByID(attackerID)); | ||||
| 		if (av_tiles.size() < 1) | ||||
| 		{ | ||||
| 			return MakeDefend(attackerID); | ||||
| 			return BattleAction::makeDefend(attackerStack); | ||||
| 		} | ||||
|  | ||||
| 		// get the best tile - now the nearest | ||||
| @@ -549,7 +522,7 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID) | ||||
|  | ||||
| 		if(fields.size() == 0) | ||||
| 		{ | ||||
| 			return MakeDefend(attackerID); | ||||
| 			return BattleAction::makeDefend(attackerStack); | ||||
| 		} | ||||
|  | ||||
| 		BattleAction ba; | ||||
| @@ -566,7 +539,7 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID) | ||||
| 		else if(BattleInfo::mutualPosition(dest_tile, destStackPos-1) != -1) | ||||
| 			ba.additionalInfo = destStackPos-1; | ||||
| 		else | ||||
| 			MakeDefend(attackerID); | ||||
| 			return BattleAction::makeDefend(attackerStack); | ||||
|  | ||||
| 		int nearest_dist = m_battleHelper.InfiniteDistance; | ||||
| 		int nearest_pos = -1; | ||||
|   | ||||
| @@ -106,14 +106,6 @@ private: | ||||
| 	 * Helper function. It's used for performing an attack action. | ||||
| 	 */ | ||||
| 	std::vector<int> GetAvailableHexesForAttacker(const CStack *defender, const CStack *attacker = NULL); | ||||
| 	/** | ||||
| 	 * Just make defend action. | ||||
| 	 */ | ||||
| 	BattleAction MakeDefend(int stackID); | ||||
| 	/** | ||||
| 	 * Just make wait action. | ||||
| 	 */ | ||||
| 	BattleAction MakeWait(int stackID); | ||||
| 	/** | ||||
| 	 * Make an attack action if it's possible. | ||||
| 	 * If it's not possible then function returns defend action. | ||||
|   | ||||
| @@ -3,33 +3,122 @@ | ||||
| #include "../../lib/CGameState.h" | ||||
|  | ||||
| CStupidAI::CStupidAI(void) | ||||
| 	: side(-1), cb(NULL) | ||||
| { | ||||
| 	print("created"); | ||||
| } | ||||
|  | ||||
|  | ||||
| CStupidAI::~CStupidAI(void) | ||||
| { | ||||
| 	print("destroyed"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::init( IBattleCallback * CB ) | ||||
| { | ||||
|  | ||||
| 	print("init called, saving ptr to IBattleCallback"); | ||||
| 	cb = CB; | ||||
| } | ||||
|  | ||||
| void CStupidAI::actionFinished( const BattleAction *action ) | ||||
| { | ||||
|  | ||||
| 	print("actionFinished called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::actionStarted( const BattleAction *action ) | ||||
| { | ||||
|  | ||||
| 	print("actionStarted called"); | ||||
| } | ||||
|  | ||||
| BattleAction CStupidAI::activeStack( const CStack * stack ) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.actionType = BattleAction::DEFEND; | ||||
| 	ba.stackNumber = stack->ID; | ||||
| 	return ba; | ||||
| 	print("activeStack called"); | ||||
| 	return BattleAction::makeDefend(stack); | ||||
| 	if(stack->position % 17  <  5) //move army little towards enemy | ||||
| 	{ | ||||
| 		THex dest = stack->position + side*2 - 1; | ||||
| 		print(stack->nodeName() << "will be moved to " + boost::lexical_cast<std::string>(dest)); | ||||
| 		return BattleAction::makeMove(stack, );  | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleAttack(const BattleAttack *ba) | ||||
| { | ||||
| 	print("battleAttack called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) | ||||
| { | ||||
| 	print("battleStacksAttacked called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleEnd(const BattleResult *br)  | ||||
| { | ||||
| 	print("battleEnd called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleResultsApplied()  | ||||
| { | ||||
| 	print("battleResultsApplied called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleNewRoundFirst(int round)  | ||||
| { | ||||
| 	print("battleNewRoundFirst called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleNewRound(int round)  | ||||
| { | ||||
| 	print("battleNewRound called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStackMoved(const CStack * stack, THex dest, int distance, bool end)  | ||||
| { | ||||
| 	print("battleStackMoved called");; | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleSpellCast(const BattleSpellCast *sc)  | ||||
| { | ||||
| 	print("battleSpellCast called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStacksEffectsSet(const SetStackEffect & sse)  | ||||
| { | ||||
| 	print("battleStacksEffectsSet called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool Side)  | ||||
| { | ||||
| 	print("battleStart called"); | ||||
| 	side = Side; | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom)  | ||||
| { | ||||
| 	print("battleStacksHealedRes called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleNewStackAppeared(const CStack * stack)  | ||||
| { | ||||
| 	print("battleNewStackAppeared called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleObstaclesRemoved(const std::set<si32> & removedObstacles)  | ||||
| { | ||||
| 	print("battleObstaclesRemoved called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleCatapultAttacked(const CatapultAttack & ca)  | ||||
| { | ||||
| 	print("battleCatapultAttacked called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStacksRemoved(const BattleStacksRemoved & bsr)  | ||||
| { | ||||
| 	print("battleStacksRemoved called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::print(const std::string &text) const | ||||
| { | ||||
| 	tlog0 << "CStupidAI [" << this <<"]: " << text << std::endl; | ||||
| } | ||||
| @@ -2,6 +2,10 @@ | ||||
|  | ||||
| class CStupidAI : public CBattleGameInterface | ||||
| { | ||||
| 	int side; | ||||
| 	IBattleCallback *cb; | ||||
|  | ||||
| 	void print(const std::string &text) const; | ||||
| public: | ||||
| 	CStupidAI(void); | ||||
| 	~CStupidAI(void); | ||||
| @@ -10,5 +14,22 @@ public: | ||||
| 	void actionFinished(const BattleAction *action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero | ||||
| 	void actionStarted(const BattleAction *action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero | ||||
| 	BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack | ||||
|  | ||||
| 	void battleAttack(const BattleAttack *ba) OVERRIDE; //called when stack is performing attack | ||||
| 	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) OVERRIDE; //called when stack receives damage (after battleAttack()) | ||||
| 	void battleEnd(const BattleResult *br) OVERRIDE; | ||||
| 	void battleResultsApplied() OVERRIDE; //called when all effects of last battle are applied | ||||
| 	void battleNewRoundFirst(int round) OVERRIDE; //called at the beginning of each turn before changes are applied; | ||||
| 	void battleNewRound(int round) OVERRIDE; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn | ||||
| 	void battleStackMoved(const CStack * stack, THex dest, int distance, bool end) OVERRIDE; | ||||
| 	void battleSpellCast(const BattleSpellCast *sc) OVERRIDE; | ||||
| 	void battleStacksEffectsSet(const SetStackEffect & sse) OVERRIDE;//called when a specific effect is set to stacks | ||||
| 	void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) OVERRIDE; //called by engine when battle starts; side=0 - left, side=1 - right | ||||
| 	void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom) OVERRIDE; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp | ||||
| 	void battleNewStackAppeared(const CStack * stack) OVERRIDE; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned | ||||
| 	void battleObstaclesRemoved(const std::set<si32> & removedObstacles) OVERRIDE; //called when a certain set  of obstacles is removed from batlefield; IDs of them are given | ||||
| 	void battleCatapultAttacked(const CatapultAttack & ca) OVERRIDE; //called when catapult makes an attack | ||||
| 	void battleStacksRemoved(const BattleStacksRemoved & bsr) OVERRIDE; //called when certain stack is completely removed from battlefield | ||||
|  | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,2 +1,3 @@ | ||||
| #pragma  once | ||||
| #include <boost/lexical_cast.hpp> | ||||
| #include "../../AI_Base.h" | ||||
| @@ -476,7 +476,14 @@ bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID) | ||||
| int CBattleCallback::battleGetBattlefieldType() | ||||
| { | ||||
| 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx); | ||||
| 	return gs->battleGetBattlefieldType(); | ||||
| 	//return gs->battleGetBattlefieldType(); | ||||
|  | ||||
| 	if(!gs->curB) | ||||
| 	{ | ||||
| 		tlog2<<"battleGetBattlefieldType called when there is no battle!"<<std::endl; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return gs->curB->battlefieldType; | ||||
| } | ||||
|  | ||||
| int CBattleCallback::battleGetObstaclesAtTile(THex tile) //returns bitfield  | ||||
|   | ||||
| @@ -2993,7 +2993,7 @@ void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	creAnims[ID]->nextFrame(to, creAnims[ID]->pos.x, creAnims[ID]->pos.y, creDir[ID], animCount, incrementFrame, ID==activeStack->ID, ID==mouseHoveredStack); //increment always when moving, never if stack died | ||||
| 	creAnims[ID]->nextFrame(to, creAnims[ID]->pos.x, creAnims[ID]->pos.y, creDir[ID], animCount, incrementFrame, activeStack && ID==activeStack->ID, ID==mouseHoveredStack); //increment always when moving, never if stack died | ||||
|  | ||||
| 	//printing amount | ||||
| 	if(stack->count > 0 //don't print if stack is not alive | ||||
|   | ||||
| @@ -279,6 +279,8 @@ int main(int argc, char** argv) | ||||
| 	{ | ||||
| 		StartInfo *si = new StartInfo(); | ||||
| 		si->mode = StartInfo::DUEL; | ||||
| 		si->playerInfos[0].color = 0; | ||||
| 		si->playerInfos[1].color = 1; | ||||
| 		startGame(si); | ||||
| 	} | ||||
| 	mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH)); | ||||
|   | ||||
| @@ -116,7 +116,8 @@ void CClient::waitForMoveAndSend(int color) | ||||
| { | ||||
| 	try | ||||
| 	{ | ||||
| 		BattleAction ba = playerint[color]->activeStack(gs->curB->getStack(gs->curB->activeStack, false)); | ||||
| 		assert(vstd::contains(battleints, color)); | ||||
| 		BattleAction ba = battleints[color]->activeStack(gs->curB->getStack(gs->curB->activeStack, false)); | ||||
| 		*serv << &MakeAction(ba); | ||||
| 		return; | ||||
| 	}HANDLE_EXCEPTION | ||||
| @@ -402,13 +403,14 @@ void CClient::newGame( CConnection *con, StartInfo *si ) | ||||
| 				playerint[color] = new CPlayerInterface(color); | ||||
| 				humanPlayers++; | ||||
| 			} | ||||
| 			battleints[color] = playerint[color]; | ||||
|  | ||||
| 			playerint[color]->init(cb); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			CBattleCallback * cbc = new CBattleCallback(gs, color, this); | ||||
| 			battleints[color] = CAIHandler::getNewBattleAI(cb,conf.cc.defaultAI); | ||||
| 			battleints[color] = CAIHandler::getNewBattleAI(cb,"StupidAI"); | ||||
| 			battleints[color]->init(cbc); | ||||
| 		} | ||||
| 	} | ||||
| @@ -417,16 +419,21 @@ void CClient::newGame( CConnection *con, StartInfo *si ) | ||||
| 	{ | ||||
| 		CPlayerInterface *p = new CPlayerInterface(-1); | ||||
| 		p->observerInDuelMode = true; | ||||
| 		playerint[254] = p; | ||||
| 		battleints[254] = playerint[254] = p; | ||||
| 		GH.curInt = p; | ||||
| 		p->init(new CCallback(gs, -1, this)); | ||||
| 		battleStarted(gs->curB); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		playerint[255] =  CAIHandler::getNewAI(cb,conf.cc.defaultAI); | ||||
| 		playerint[255]->init(new CCallback(gs,255,this)); | ||||
| 	} | ||||
|  | ||||
| 	serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state); | ||||
| 	hotSeat = (humanPlayers > 1); | ||||
|  | ||||
| 	playerint[255] =  CAIHandler::getNewAI(cb,conf.cc.defaultAI); | ||||
| 	playerint[255]->init(new CCallback(gs,255,this)); | ||||
|  | ||||
| } | ||||
|  | ||||
| template <typename Handler> | ||||
| @@ -553,12 +560,12 @@ void CClient::battleStarted(const BattleInfo * info) | ||||
|  | ||||
| 	new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1], Rect((conf.cc.resx - 800)/2, (conf.cc.resy - 600)/2, 800, 600), att, def); | ||||
|  | ||||
| 	if(vstd::contains(playerint,info->side1)) | ||||
| 		playerint[info->side1]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 0); | ||||
| 	if(vstd::contains(playerint,info->side2)) | ||||
| 		playerint[info->side2]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1); | ||||
| 	if(vstd::contains(playerint,254)) | ||||
| 		playerint[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1); | ||||
| 	if(vstd::contains(battleints,info->side1)) | ||||
| 		battleints[info->side1]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 0); | ||||
| 	if(vstd::contains(battleints,info->side2)) | ||||
| 		battleints[info->side2]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1); | ||||
| 	if(vstd::contains(battleints,254)) | ||||
| 		battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1); | ||||
| } | ||||
|  | ||||
| template void CClient::serialize( CISer<CLoadFile> &h, const int version ); | ||||
|   | ||||
| @@ -29,6 +29,14 @@ | ||||
| 		if(vstd::contains(cl->playerint,player))		\ | ||||
| 			cl->playerint[player]->function(__VA_ARGS__); | ||||
|  | ||||
| #define BATTLE_INTERFACE_CALL_IF_PRESENT(player,function,...) 	\ | ||||
| 		if(vstd::contains(cl->battleints,player))		\ | ||||
| 			cl->battleints[player]->function(__VA_ARGS__); | ||||
|  | ||||
| #define BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(function,...) 	\ | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, function, __VA_ARGS__) \ | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, function, __VA_ARGS__) \ | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT(254, function, __VA_ARGS__) | ||||
| /* | ||||
|  * NetPacksClient.cpp, part of VCMI engine | ||||
|  * | ||||
| @@ -486,14 +494,12 @@ void BattleStart::applyCl( CClient *cl ) | ||||
|  | ||||
| void BattleNextRound::applyFirstCl(CClient *cl) | ||||
| { | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleNewRoundFirst,round); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleNewRoundFirst,round); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleNewRoundFirst,round); | ||||
| } | ||||
|  | ||||
| void BattleNextRound::applyCl( CClient *cl ) | ||||
| { | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleNewRound,round); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleNewRound,round); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleNewRound,round); | ||||
| } | ||||
|  | ||||
| void BattleSetActiveStack::applyCl( CClient *cl ) | ||||
| @@ -508,23 +514,19 @@ void BattleSetActiveStack::applyCl( CClient *cl ) | ||||
| 	{ | ||||
| 		playerToCall = activated->owner; | ||||
| 	} | ||||
| 	if( vstd::contains(cl->playerint, playerToCall) ) | ||||
| 	if( vstd::contains(cl->battleints, playerToCall) ) | ||||
| 		boost::thread( boost::bind(&CClient::waitForMoveAndSend, cl, playerToCall) ); | ||||
| } | ||||
|  | ||||
| void BattleResult::applyFirstCl( CClient *cl ) | ||||
| { | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side1]->battleEnd(this); | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side2]->battleEnd(this); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleEnd,this); | ||||
| } | ||||
|  | ||||
| void BattleStackMoved::applyFirstCl( CClient *cl ) | ||||
| { | ||||
| 	const CStack * movedStack = GS(cl)->curB->getStack(stack); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStackMoved,movedStack,tile,distance,ending); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStackMoved,movedStack,tile,distance,ending); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStackMoved,movedStack,tile,distance,ending); | ||||
| } | ||||
|  | ||||
| void BattleStackAttacked::applyCl( CClient *cl ) | ||||
| @@ -532,16 +534,12 @@ void BattleStackAttacked::applyCl( CClient *cl ) | ||||
| 	std::vector<BattleStackAttacked> bsa; | ||||
| 	bsa.push_back(*this); | ||||
|  | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStacksAttacked,bsa); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStacksAttacked,bsa); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksAttacked,bsa); | ||||
| } | ||||
|  | ||||
| void BattleAttack::applyFirstCl( CClient *cl ) | ||||
| { | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side1]->battleAttack(this); | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side2]->battleAttack(this); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleAttack,this); | ||||
| 	for (int g=0; g<bsa.size(); ++g) | ||||
| 	{ | ||||
| 		for (int z=0; z<bsa[g].healedStacks.size(); ++z) | ||||
| @@ -553,59 +551,39 @@ void BattleAttack::applyFirstCl( CClient *cl ) | ||||
|  | ||||
| void BattleAttack::applyCl( CClient *cl ) | ||||
| { | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStacksAttacked,bsa); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStacksAttacked,bsa); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksAttacked,bsa); | ||||
| } | ||||
|  | ||||
| void StartAction::applyFirstCl( CClient *cl ) | ||||
| { | ||||
| 	cl->curbaction = new BattleAction(ba); | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side1]->actionStarted(&ba); | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side2]->actionStarted(&ba); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionStarted, &ba); | ||||
| } | ||||
|  | ||||
| void BattleSpellCast::applyCl( CClient *cl ) | ||||
| { | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side1]->battleSpellCast(this); | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side2]->battleSpellCast(this); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleSpellCast,this); | ||||
|  | ||||
| 	if(id >= 66 && id <= 69) //elemental summoning | ||||
| 	{ | ||||
| 		if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) | ||||
| 			cl->playerint[GS(cl)->curB->side1]->battleNewStackAppeared(GS(cl)->curB->stacks[GS(cl)->curB->stacks.size() - 1]); | ||||
| 		if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) | ||||
| 			cl->playerint[GS(cl)->curB->side2]->battleNewStackAppeared(GS(cl)->curB->stacks[GS(cl)->curB->stacks.size() - 1]); | ||||
| 		BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleNewStackAppeared,GS(cl)->curB->stacks.back()); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SetStackEffect::applyCl( CClient *cl ) | ||||
| { | ||||
| 	BattleSpellCast sc; | ||||
| 	sc.id = effect.id; | ||||
| 	sc.side = 3; //doesn't matter | ||||
| 	sc.skill = effect.val; | ||||
|  | ||||
| 	//informing about effects | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side1]->battleStacksEffectsSet(*this); | ||||
| 	if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) | ||||
| 		cl->playerint[GS(cl)->curB->side2]->battleStacksEffectsSet(*this); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksEffectsSet,*this); | ||||
| } | ||||
|  | ||||
| void StacksInjured::applyCl( CClient *cl ) | ||||
| { | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStacksAttacked,stacks); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStacksAttacked,stacks); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksAttacked,stacks); | ||||
| } | ||||
|  | ||||
| void BattleResultsApplied::applyCl( CClient *cl ) | ||||
| { | ||||
| 	INTERFACE_CALL_IF_PRESENT(player1,battleResultsApplied); | ||||
| 	INTERFACE_CALL_IF_PRESENT(player2,battleResultsApplied); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleResultsApplied); | ||||
| } | ||||
|  | ||||
| void StacksHealedOrResurrected::applyCl( CClient *cl ) | ||||
| @@ -615,29 +593,25 @@ void StacksHealedOrResurrected::applyCl( CClient *cl ) | ||||
| 	{ | ||||
| 		shiftedHealed.push_back(std::make_pair(healedStacks[v].stackID, healedStacks[v].healedHP)); | ||||
| 	} | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleStacksHealedRes, shiftedHealed, lifeDrain, drainedFrom); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleStacksHealedRes, shiftedHealed, lifeDrain, drainedFrom); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksHealedRes, shiftedHealed, lifeDrain, drainedFrom); | ||||
| } | ||||
|  | ||||
| void ObstaclesRemoved::applyCl( CClient *cl ) | ||||
| { | ||||
| 	//inform interfaces about removed obstacles | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleObstaclesRemoved, obstacles); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleObstaclesRemoved, obstacles); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleObstaclesRemoved, obstacles); | ||||
| } | ||||
|  | ||||
| void CatapultAttack::applyCl( CClient *cl ) | ||||
| { | ||||
| 	//inform interfaces about catapult attack | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleCatapultAttacked, *this); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleCatapultAttacked, *this); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleCatapultAttacked, *this); | ||||
| } | ||||
|  | ||||
| void BattleStacksRemoved::applyCl( CClient *cl ) | ||||
| { | ||||
| 	//inform interfaces about removed stacks | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleStacksRemoved, *this); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleStacksRemoved, *this); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksRemoved, *this); | ||||
| } | ||||
|  | ||||
| CGameState* CPackForClient::GS( CClient *cl ) | ||||
| @@ -647,8 +621,7 @@ CGameState* CPackForClient::GS( CClient *cl ) | ||||
|  | ||||
| void EndAction::applyCl( CClient *cl ) | ||||
| { | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,actionFinished,cl->curbaction); | ||||
| 	INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,actionFinished,cl->curbaction); | ||||
| 	BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionFinished, cl->curbaction); | ||||
|  | ||||
| 	delete cl->curbaction; | ||||
| 	cl->curbaction = NULL; | ||||
|   | ||||
							
								
								
									
										59
									
								
								lib/BattleAction.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								lib/BattleAction.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| #define VCMI_DLL | ||||
| #include "BattleAction.h" | ||||
| #include "CGameState.h" | ||||
|  | ||||
| BattleAction::BattleAction() | ||||
| { | ||||
| 	side = -1; | ||||
| 	stackNumber = -1; | ||||
| 	actionType = INVALID; | ||||
| 	destinationTile = -1; | ||||
| 	additionalInfo = -1; | ||||
| } | ||||
|  | ||||
| BattleAction BattleAction::makeDefend(const CStack *stack) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = !stack->attackerOwned; | ||||
| 	ba.actionType = DEFEND; | ||||
| 	ba.stackNumber = stack->ID; | ||||
| 	return ba; | ||||
| } | ||||
|  | ||||
| BattleAction BattleAction::makeMeleeAttack(const CStack *stack) /*WARNING: stacks must be neighbouring! */ | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = !stack->attackerOwned; | ||||
| 	ba.actionType = WAIT; | ||||
| 	ba.stackNumber = stack->ID; | ||||
| 	return ba; | ||||
| } | ||||
|  | ||||
| BattleAction BattleAction::makeWait(const CStack *stack) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = !stack->attackerOwned; | ||||
| 	ba.actionType = WAIT; | ||||
| 	ba.stackNumber = stack->ID; | ||||
| 	return ba; | ||||
| } | ||||
|  | ||||
| BattleAction BattleAction::makeShotAttack(const CStack *shooter, const CStack *target) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = !shooter->attackerOwned; | ||||
| 	ba.actionType = SHOOT; | ||||
| 	ba.stackNumber = shooter->ID; | ||||
| 	ba.destinationTile = target->position; | ||||
| 	return ba; | ||||
| } | ||||
|  | ||||
| BattleAction BattleAction::makeMove(const CStack *stack, THex dest) | ||||
| { | ||||
| 	BattleAction ba; | ||||
| 	ba.side = !stack->attackerOwned; | ||||
| 	ba.actionType = WALK; | ||||
| 	ba.stackNumber = stack->ID; | ||||
| 	ba.destinationTile = dest; | ||||
| 	return ba; | ||||
| } | ||||
| @@ -1,6 +1,8 @@ | ||||
| #pragma once; | ||||
| #ifndef __BATTLEACTION_H__ | ||||
| #define __BATTLEACTION_H__ | ||||
|  | ||||
| #include "../global.h" | ||||
| /* | ||||
|  * BattleAction.h, part of VCMI engine | ||||
|  * | ||||
| @@ -11,13 +13,15 @@ | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| struct BattleAction | ||||
| class CStack; | ||||
|  | ||||
| struct DLL_EXPORT BattleAction | ||||
| { | ||||
| 	ui8 side; //who made this action: false - left, true - right player | ||||
| 	ui32 stackNumber;//stack ID, -1 left hero, -2 right hero, | ||||
| 	enum ActionType | ||||
| 	{ | ||||
| 		NO_ACTION = 0, HERO_SPELL, WALK, DEFEND, RETREAT, SURRENDER, WALK_AND_ATTACK, SHOOT, WAIT, CATAPULT, MONSTER_SPELL, BAD_MORALE, STACK_HEAL | ||||
| 		INVALID = -1, NO_ACTION = 0, HERO_SPELL, WALK, DEFEND, RETREAT, SURRENDER, WALK_AND_ATTACK, SHOOT, WAIT, CATAPULT, MONSTER_SPELL, BAD_MORALE, STACK_HEAL | ||||
| 	}; | ||||
| 	ui8 actionType; //    0 = No action;   1 = Hero cast a spell   2 = Walk   3 = Defend   4 = Retreat from the battle | ||||
| 		//5 = Surrender   6 = Walk and Attack   7 = Shoot    8 = Wait   9 = Catapult | ||||
| @@ -28,5 +32,13 @@ struct BattleAction | ||||
| 	{ | ||||
| 		h & side & stackNumber & actionType & destinationTile & additionalInfo; | ||||
| 	} | ||||
|  | ||||
| 	BattleAction(); | ||||
|  | ||||
| 	static BattleAction makeDefend(const CStack *stack); | ||||
| 	static BattleAction makeWait(const CStack *stack); | ||||
| 	static BattleAction makeMeleeAttack(const CStack *stack); //WARNING: stacks must be neighbouring!; | ||||
| 	static BattleAction makeShotAttack(const CStack *shooter, const CStack *target); | ||||
| 	static BattleAction makeMove(const CStack *stack, THex dest); | ||||
| }; | ||||
| #endif // __BATTLEACTION_H__ | ||||
|   | ||||
| @@ -60,6 +60,7 @@ public: | ||||
|  | ||||
| class DLL_EXPORT CArtifactInstance : public CBonusSystemNode | ||||
| { | ||||
| 	void init(); | ||||
| public: | ||||
| 	ConstTransitivePtr<CArtifact> art;  | ||||
| 	si32 id; //id of the instance | ||||
| @@ -67,7 +68,6 @@ public: | ||||
| 	CArtifactInstance(); | ||||
| 	CArtifactInstance(CArtifact *Art); | ||||
|  | ||||
| 	void init(); | ||||
| 	std::string nodeName() const OVERRIDE; | ||||
| 	void setType(CArtifact *Art); | ||||
|  | ||||
| @@ -80,6 +80,12 @@ public: | ||||
| 	static CArtifactInstance *createScroll(const CSpell *s); | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CCombinedArtifactInstance : public CArtifactInstance | ||||
| { | ||||
| public: | ||||
|  | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner | ||||
| { //used only for dynamic cast :P | ||||
| public: | ||||
|   | ||||
| @@ -1041,7 +1041,7 @@ const CGHeroInstance * CStack::getMyHero() const | ||||
| std::string CStack::nodeName() const | ||||
| { | ||||
| 	std::ostringstream oss; | ||||
| 	oss << "Battle stack of " << count << " creatures of "; | ||||
| 	oss << "Battle stack [" << ID << "]: " << count << " creatures of "; | ||||
| 	if(type) | ||||
| 		oss << type->namePl; | ||||
| 	else | ||||
| @@ -1486,6 +1486,7 @@ BattleInfo * setupBattle( int3 tile, int terrain, int terType, const CArmedInsta | ||||
| 	std::vector<CStack*> & stacks = (curB->stacks); | ||||
|  | ||||
| 	curB->tile = tile; | ||||
| 	curB->battlefieldType = terType; | ||||
| 	curB->belligerents[0] = const_cast<CArmedInstance*>(armies[0]); | ||||
| 	curB->belligerents[1] = const_cast<CArmedInstance*>(armies[1]); | ||||
| 	curB->heroes[0] = const_cast<CGHeroInstance*>(heroes[0]); | ||||
| @@ -1930,12 +1931,14 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) | ||||
| 			const CGHeroInstance *heroes[2]; | ||||
| 			const CGTownInstance *town = NULL; | ||||
| 			CGHeroInstance *h = new CGHeroInstance(); | ||||
| 			h->setOwner(0); | ||||
| 			h->subID = 1; | ||||
| 			h->initHero(1); | ||||
| 			h->initObj(); | ||||
| 			//h->putStack(0, new CStackInstance(34, 5)); | ||||
|  | ||||
| 			CGCreature *c = new CGCreature(); | ||||
| 			c->setOwner(1); | ||||
| 			c->putStack(0, new CStackInstance(70, 6)); | ||||
| 			c->subID = 34; | ||||
| 			c->initObj(); | ||||
|   | ||||
| @@ -212,11 +212,12 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode | ||||
| 	std::vector<CObstacleInstance> obstacles; | ||||
| 	ui8 castSpells[2]; //[0] - attacker, [1] - defender | ||||
| 	SiegeInfo si; | ||||
| 	si32 battlefieldType; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & side1 & side2 & round & activeStack & siege & tid & tile & stacks & belligerents & obstacles | ||||
| 			& castSpells & si; | ||||
| 			& castSpells & si & battlefieldType; | ||||
| 		h & heroes; | ||||
| 		h & static_cast<CBonusSystemNode&>(*this); | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user