1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Towards duel support.

This commit is contained in:
Michał W. Urbańczyk 2010-12-25 01:43:40 +00:00
parent 6383c9a013
commit 2cf6729eee
15 changed files with 269 additions and 123 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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;
}

View File

@ -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
};

View File

@ -1,2 +1,3 @@
#pragma once
#include <boost/lexical_cast.hpp>
#include "../../AI_Base.h"

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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 );

View File

@ -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
View 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;
}

View File

@ -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__

View File

@ -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:

View File

@ -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();

View File

@ -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);
}