1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

* fixed defending creature in battle end window (slot id was used instead of creature id)

* redone casualties calculacion
* redone battle-end checking (now it works always)
* further fixes/checkings around netcode
This commit is contained in:
Michał W. Urbańczyk
2008-09-09 07:05:02 +00:00
parent 6233066b91
commit 5e0986f9d8
6 changed files with 89 additions and 63 deletions

View File

@@ -1449,10 +1449,10 @@ CBattleReslutWindow::CBattleReslutWindow(const BattleResult &br, SDL_Rect & pos,
int bestPower = 0; int bestPower = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator it = owner->army2->slots.begin(); it!=owner->army2->slots.end(); ++it) for(std::map<si32,std::pair<ui32,si32> >::const_iterator it = owner->army2->slots.begin(); it!=owner->army2->slots.end(); ++it)
{ {
if( CGI->creh->creatures[it->first].AIValue > bestPower) if( CGI->creh->creatures[it->second.first].AIValue > bestPower)
{ {
bestPower = CGI->creh->creatures[it->first].AIValue; bestPower = CGI->creh->creatures[it->second.first].AIValue;
bestMonsterID = it->first; bestMonsterID = it->second.first;
} }
} }
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 391, 38)); SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 391, 38));

View File

@@ -253,8 +253,8 @@ std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
return path; return path;
} }
CStack::CStack(CCreature * C, int A, int O, int I, bool AO) CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
:creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints) :creature(C),amount(A), baseAmount(A), owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints), slot(S)
{ {
} }
void CGameState::applyNL(IPack * pack) void CGameState::applyNL(IPack * pack)
@@ -552,27 +552,6 @@ void CGameState::applyNL(IPack * pack)
at->amount = br->newAmount; at->amount = br->newAmount;
at->firstHPleft = br->newHP; at->firstHPleft = br->newHP;
at->alive = !br->killed(); at->alive = !br->killed();
if(br->killedAmount>0) //setting casualities
{
bool found = false;
for(std::set<std::pair<ui32,si32> >::iterator it = curB->cas[1 - at->attackerOwned].begin(); it!=curB->cas[1 - at->attackerOwned].end(); ++it)
{
if(it->first == at->creature->idNumber)
{
found = true;
std::pair<ui32,si32> mod = *it;
mod.second += br->killedAmount;
curB->cas[1 - at->attackerOwned].insert(it, mod);
curB->cas[1 - at->attackerOwned].erase(it);
}
}
if(!found)
{
curB->cas[1 - at->attackerOwned].insert(std::make_pair(at->creature->idNumber, br->killedAmount));
}
}
break; break;
} }
case 3006: case 3006:
@@ -1341,3 +1320,38 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender)
return (float)damageBase * (float)attacker->amount * dmgBonusMultiplier; return (float)damageBase * (float)attacker->amount * dmgBonusMultiplier;
} }
void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualties )
{
for(int i=0; i<stacks.size();i++)//setting casualties
{
if(!stacks[i]->alive)
{
casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount));
}
else if(stacks[i]->amount != stacks[i]->baseAmount)
{
casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount - stacks[i]->amount));
}
}
//if(br->killedAmount>0)
//{
// bool found = false;
// for(std::set<std::pair<ui32,si32> >::iterator it = curB->cas[1 - at->attackerOwned].begin(); it!=curB->cas[1 - at->attackerOwned].end(); ++it)
// {
// if(it->first == at->creature->idNumber)
// {
// found = true;
// std::pair<ui32,si32> mod = *it;
// mod.second += br->killedAmount;
// curB->cas[1 - at->attackerOwned].insert(it, mod);
// curB->cas[1 - at->attackerOwned].erase(it);
// }
// }
// if(!found)
// {
// curB->cas[1 - at->attackerOwned].insert(std::make_pair(at->creature->idNumber, br->killedAmount));
// }
//}
}

View File

@@ -58,11 +58,10 @@ struct DLL_EXPORT BattleInfo
si32 hero1, hero2; si32 hero1, hero2;
CCreatureSet army1, army2; CCreatureSet army1, army2;
std::vector<CStack*> stacks; std::vector<CStack*> stacks;
std::set<std::pair<ui32,si32> > cas[2]; //first => casualties of attackers - set of pairs crid<>number
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2 & cas[0] & cas[1]; h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2;
} }
CStack * getStack(int stackID); CStack * getStack(int stackID);
CStack * getStackT(int tileID); CStack * getStackT(int tileID);
@@ -75,6 +74,7 @@ struct DLL_EXPORT BattleInfo
static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left) static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
static std::vector<int> neighbouringTiles(int hex); static std::vector<int> neighbouringTiles(int hex);
static int calculateDmg(const CStack* attacker, const CStack* defender); //TODO: add additional conditions and require necessary data static int calculateDmg(const CStack* attacker, const CStack* defender); //TODO: add additional conditions and require necessary data
void calculateCasualties(std::set<std::pair<ui32,si32> > *casualties);
}; };
class DLL_EXPORT CStack class DLL_EXPORT CStack
@@ -82,15 +82,15 @@ class DLL_EXPORT CStack
public: public:
ui32 ID; //unique ID of stack ui32 ID; //unique ID of stack
CCreature * creature; CCreature * creature;
ui32 amount; ui32 amount, baseAmount;
ui32 firstHPleft; //HP of first creature in stack ui32 firstHPleft; //HP of first creature in stack
ui8 owner; ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (255 for neutrals/called creatures)
ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle) ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
ui16 position; //position on battlefield ui16 position; //position on battlefield
ui8 alive; //true if it is alive ui8 alive; //true if it is alive
CStack(CCreature * C, int A, int O, int I, bool AO); CStack(CCreature * C, int A, int O, int I, bool AO, int S);
CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1){}; CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1){};
template <typename Handler> void save(Handler &h, const int version) template <typename Handler> void save(Handler &h, const int version)
{ {
@@ -104,7 +104,7 @@ public:
} }
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & ID & amount & firstHPleft & owner & attackerOwned & position & alive; h & ID & amount & baseAmount & firstHPleft & owner & attackerOwned & position & alive;
if(h.saving) if(h.saving)
save(h,version); save(h,version);
else else

View File

@@ -56,13 +56,16 @@ CConnection::CConnection(std::string host, std::string port, std::string Name, s
std::cout<< "Critical problem: No endpoints found!" << std::endl; std::cout<< "Critical problem: No endpoints found!" << std::endl;
goto connerror1; goto connerror1;
} }
int i=0;
while(pom != end) while(pom != end)
{ {
std::cout << (boost::asio::ip::tcp::endpoint&)*pom << std::endl; std::cout << "\t" << i << ": " << (boost::asio::ip::tcp::endpoint&)*pom << std::endl;
pom++; pom++;
} }
i=0;
while(endpoint_iterator != end) while(endpoint_iterator != end)
{ {
std::cout << "Trying connection to " << (boost::asio::ip::tcp::endpoint&)*endpoint_iterator << " (" << i++ << ")" << std::endl;
socket->connect(*endpoint_iterator, error); socket->connect(*endpoint_iterator, error);
if(!error) if(!error)
{ {
@@ -71,18 +74,20 @@ CConnection::CConnection(std::string host, std::string port, std::string Name, s
} }
else else
{ {
std::cout << "Problem with connecting. " << std::endl; std::cout << "Problem with connecting: " << std::endl << error << std::endl;
} }
endpoint_iterator++;
} }
//we shouldn't be here - error handling //we shouldn't be here - error handling
connerror1: connerror1:
std::cout << "Something went wrong... checking for error info" << std::endl;
if(error) if(error)
std::cout << error <<std::endl; std::cout << error <<std::endl;
else else
std::cout << "No error info. " << std::endl; std::cout << "No error info. " << std::endl;
delete io_service; delete io_service;
delete socket; //delete socket;
throw std::string("Can't establish connection :("); throw std::string("Can't establish connection :(");
} }
CConnection::CConnection( CConnection::CConnection(
@@ -99,7 +104,12 @@ CConnection::CConnection(boost::asio::basic_socket_acceptor<boost::asio::ip::tcp
boost::system::error_code error = asio::error::host_not_found; boost::system::error_code error = asio::error::host_not_found;
socket = new tcp::socket(*io_service); socket = new tcp::socket(*io_service);
acceptor->accept(*socket,error); acceptor->accept(*socket,error);
if (error){ delete socket; throw "Can't establish connection :("; } if (error)
{
std::cout << "Error on accepting: " << std::endl << error << std::endl;
delete socket;
throw "Can't establish connection :(";
}
init(); init();
} }
int CConnection::write(const void * data, unsigned size) int CConnection::write(const void * data, unsigned size)

View File

@@ -271,32 +271,11 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
BattleSetActiveStack sas; BattleSetActiveStack sas;
sas.stack = stacks[i]->ID; sas.stack = stacks[i]->ID;
sendAndApply(&sas); sendAndApply(&sas);
//wait for response about battle action
boost::unique_lock<boost::mutex> lock(battleMadeAction.mx); boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
while(!battleMadeAction.data) while(!battleMadeAction.data)
battleMadeAction.cond.wait(lock); battleMadeAction.cond.wait(lock);
battleMadeAction.data = false; battleMadeAction.data = false;
} checkForBattleEnd(stacks);
//checking winning condition
bool hasStack[2]; //hasStack[0] - true if attacker has a living stack; defender similarily
hasStack[0] = hasStack[1] = false;
for(int b = 0; b<stacks.size(); ++b)
{
if(stacks[b]->alive)
{
hasStack[1-stacks[b]->attackerOwned] = true;
}
}
if(!hasStack[0] || !hasStack[1]) //somebody has won
{
BattleResult *br = new BattleResult;
br->result = 0;
br->winner = hasStack[1]; //fleeing side loses
br->casualties[0] = gs->curB->cas[0]; //setting casualities
br->casualties[1] = gs->curB->cas[1]; //as above - second side ;]
battleResult.set(br);
} }
} }
@@ -887,8 +866,7 @@ upgend:
BattleResult *br = new BattleResult; BattleResult *br = new BattleResult;
br->result = 1; br->result = 1;
br->winner = !ba.side; //fleeing side loses br->winner = !ba.side; //fleeing side loses
br->casualties[0] = gs->curB->cas[0]; //setting casualities gs->curB->calculateCasualties(br->casualties);
br->casualties[1] = gs->curB->cas[1]; //as above - second side ;]
battleResult.set(br); battleResult.set(br);
break; break;
} }
@@ -1204,7 +1182,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
curB->activeStack = -1; curB->activeStack = -1;
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++) for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
{ {
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true)); stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
stacks[stacks.size()-1]->ID = stacks.size()-1; stacks[stacks.size()-1]->ID = stacks.size()-1;
} }
//initialization of positions //initialization of positions
@@ -1258,7 +1236,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
break; break;
} }
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++) for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false)); stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
switch(army2.slots.size()) //for defender switch(army2.slots.size()) //for defender
{ {
case 0: case 0:
@@ -1332,3 +1310,25 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
bs.info = curB; bs.info = curB;
sendAndApply(&bs); sendAndApply(&bs);
} }
void CGameHandler::checkForBattleEnd( std::vector<CStack*> &stacks )
{
//checking winning condition
bool hasStack[2]; //hasStack[0] - true if attacker has a living stack; defender similarily
hasStack[0] = hasStack[1] = false;
for(int b = 0; b<stacks.size(); ++b)
{
if(stacks[b]->alive)
{
hasStack[1-stacks[b]->attackerOwned] = true;
}
}
if(!hasStack[0] || !hasStack[1]) //somebody has won
{
BattleResult *br = new BattleResult;
br->result = 0;
br->winner = hasStack[1]; //fleeing side loses
gs->curB->calculateCasualties(br->casualties);
battleResult.set(br);
}
}

View File

@@ -54,6 +54,8 @@ class CGameHandler
void changeSecSkill(int ID, ui16 which, int val, bool abs=false); void changeSecSkill(int ID, ui16 which, int val, bool abs=false);
void moveStack(int stack, int dest); void moveStack(int stack, int dest);
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero
void checkForBattleEnd( std::vector<CStack*> &stacks );
void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 ); void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 );
public: public: