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:
@@ -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));
|
||||||
|
|||||||
@@ -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));
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
14
CGameState.h
14
CGameState.h
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user