1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* CCallback battle calls are more safe now when there is no battle (may prevent some bugs)

* corrected some obstacles entries
* removed two stack corruption bugs
* a few tweaks in battle path/available hexes calculation (more of them is needed)
This commit is contained in:
mateuszb 2009-02-14 13:49:30 +00:00
parent fd07f7f33e
commit b42a7fa87b
5 changed files with 120 additions and 49 deletions

View File

@ -1419,10 +1419,11 @@ void CBattleInterface::hexLclicked(int whichOne)
if(LOCPLINT->cb->battleGetStackByID(activeStack)->creature->isDoubleWide())
{
std::vector<int> acc = LOCPLINT->cb->battleGetAvailableHexes(activeStack, false);
int shiftedDest = whichOne + (LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned ? 1 : -1);
if(vstd::contains(acc, whichOne))
giveCommand(2,whichOne,activeStack);
else
giveCommand(2,whichOne + (LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned ? 1 : -1),activeStack);
else if(vstd::contains(acc, shiftedDest))
giveCommand(2,shiftedDest,activeStack);
}
else
{

View File

@ -486,6 +486,11 @@ CStack* CCallback::battleGetStackByPos(int pos)
int CCallback::battleGetPos(int stack)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB)
{
tlog2<<"battleGetPos called when there is no battle!"<<std::endl;
return -1;
}
for(size_t g=0; g<gs->curB->stacks.size(); ++g)
{
if(gs->curB->stacks[g]->ID == stack)
@ -512,12 +517,21 @@ std::map<int, CStack> CCallback::battleGetStacks()
std::vector<CStack> CCallback::battleGetStackQueue()
{
if(!gs->curB)
{
tlog2<<"battleGetStackQueue called when there is not battle!"<<std::endl;
return std::vector<CStack>();
}
return gs->curB->getStackQueue();
}
CCreature CCallback::battleGetCreature(int number)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx); //TODO use me?
if(!gs->curB)
{
tlog2<<"battleGetCreature called when there is no battle!"<<std::endl;
}
for(size_t h=0; h<gs->curB->stacks.size(); ++h)
{
if(gs->curB->stacks[h]->ID == number) //creature found
@ -533,13 +547,23 @@ CCreature CCallback::battleGetCreature(int number)
std::vector<int> CCallback::battleGetAvailableHexes(int ID, bool addOccupiable)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB)
{
tlog2<<"battleGetAvailableHexes called when there is no battle!"<<std::endl;
return std::vector<int>();
}
return gs->curB->getAccessibility(ID, addOccupiable);
//return gs->battleGetRange(ID);
}
bool CCallback::battleIsStackMine(int ID)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx); //TODO use me ?
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB)
{
tlog2<<"battleIsStackMine called when there is no battle!"<<std::endl;
return false;
}
for(size_t h=0; h<gs->curB->stacks.size(); ++h)
{
if(gs->curB->stacks[h]->ID == ID) //creature found
@ -549,9 +573,9 @@ bool CCallback::battleIsStackMine(int ID)
}
bool CCallback::battleCanShoot(int ID, int dest)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx); //TODO use me?
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
CStack *our = battleGetStackByID(ID), *dst = battleGetStackByPos(dest);
if(!our || !dst) return false;
if(!our || !dst || !gs->curB) return false;
for(size_t g=0; g<our->effects.size(); ++g)
{

View File

@ -190,7 +190,8 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, int stackToOmmit)
std::vector<int> blocked = VLC->heroh->obstacles[obstacles[b].ID].getBlocked(obstacles[b].pos);
for(int c=0; c<blocked.size(); ++c)
{
accessibility[blocked[c]] = false;
if(blocked[c] >=0 && blocked[c] < BFIELD_SIZE)
accessibility[blocked[c]] = false;
}
}
}
@ -199,23 +200,6 @@ void BattleInfo::getAccessibilityMapForTwoHex(bool *accessibility, bool atackerS
bool mac[BFIELD_SIZE];
getAccessibilityMap(mac,stackToOmmit);
memcpy(accessibility,mac,BFIELD_SIZE);
if(!addOccupiable)
{
for(int b=0; b<BFIELD_SIZE; ++b)
{
if( mac[b] && !(atackerSide ? mac[b-1] : mac[b+1]))
{
accessibility[b] = false;
}
}
//removing accessibility for side hexes
for(int v=0; v<BFIELD_SIZE; ++v)
if(atackerSide ? (v%BFIELD_WIDTH)==1 : (v%BFIELD_WIDTH)==(BFIELD_WIDTH - 2))
accessibility[v] = false;
}
}
void BattleInfo::makeBFS(int start, bool*accessibility, int *predecessor, int *dists) //both pointers must point to the at least 187-elements int arrays
{
@ -258,10 +242,53 @@ std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable)
int pr[BFIELD_SIZE], dist[BFIELD_SIZE];
makeBFS(s->position,ac,pr,dist);
if(s->creature->isDoubleWide())
{
if(!addOccupiable)
{
std::vector<int> rem;
for(int b=0; b<BFIELD_SIZE; ++b)
{
if( ac[b] && !(s->attackerOwned ? ac[b-1] : ac[b+1]))
{
rem.push_back(b);
}
}
for(int g=0; g<rem.size(); ++g)
{
ac[rem[g]] = false;
}
//removing accessibility for side hexes
for(int v=0; v<BFIELD_SIZE; ++v)
if(s->attackerOwned ? (v%BFIELD_WIDTH)==1 : (v%BFIELD_WIDTH)==(BFIELD_WIDTH - 2))
ac[v] = false;
}
else
{
std::vector<int> rem;
for(int b=0; b<BFIELD_SIZE; ++b)
{
if( ac[b] && !ac[b-1] && !ac[b+1] && b%BFIELD_WIDTH != 0 && b%BFIELD_WIDTH != (BFIELD_WIDTH-1))
{
rem.push_back(b);
}
}
for(int g=0; g<rem.size(); ++g)
{
ac[rem[g]] = false;
}
}
}
for(int i=0;i<BFIELD_SIZE;i++)
if(dist[i] <= s->speed())
if(dist[i] <= s->speed() && ac[i])
{
ret.push_back(i);
}
return ret;
}
@ -1562,6 +1589,34 @@ int CGameState::battleGetBattlefieldType(int3 tile)
else if(tile==int3() && !curB)
return -1;
//std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[tile.x][tile.y][tile.z].objects;
//for(int g=0; g<objs.size(); ++g)
//{
// switch(objs[g].first->ID)
// {
// case 222: //clover field
// return 19;
// case 223: //cursed ground
// return 22;
// case 224: //evil fog
// return 20;
// case 225: //favourable winds
// return 21;
// case 226: //fiery fields
// return 14;
// case 227: //holy ground
// return 18;
// case 228: //lucid pools
// return 17;
// case 229: //magic clouds
// return 16;
// case 230: //magic plains
// return 9;
// case 231: //rocklands
// return 15;
// }
//}
switch(map->terrain[tile.x][tile.y][tile.z].tertype)
{
case dirt:

View File

@ -20,12 +20,12 @@ BATTLE OBSTACLES
73 OBCFS02.DEF XXLNXX 0000000000000000001000000
74 OBCFS03.DEF NXXLNXX 0000000000000000001000000
0 OBDINO1.DEF XX 1111110000000010000000100
2 OBDINO2.DEF XXX 1111110000000010000000100
2 OBDINO2.DEF LXXX 1111110000000010000000100
1 OBDINO3.DEF XXLXX 1111110000000010000000100
6 OBDRK01.DEF XX 1111110000000010000000100
7 OBDRK02.DEF LXX 1111110000000010000000100
8 OBDRK03.DEF X 1111110000000010000000100
9 OBDRK04.DEF XX 1111110000000010000000100
9 OBDRK04.DEF LXX 1111110000000010000000100
10 OBDSH01.DEF XX 1111110000000010000000100
93 OBDSM01.DEF NXXLNXXLNNXX 1100000000000000000000000
17 OBDSM02.DEF XXLNX 1111100000000010000000100

View File

@ -241,18 +241,16 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
expert.insert(hero->secSkills[i].first);
none.erase(hero->secSkills[i].first);
}
//first offered skill
if(hero->secSkills.size() < hero->type->heroClass->skillLimit) //free skill slot
{
hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(none)); //new skill
}
else if(basicAndAdv.size())
else
{
int s = hero->type->heroClass->chooseSecSkill(basicAndAdv);
hlu.skills.push_back(s);
basicAndAdv.erase(s);
}
//second offered skill
if(basicAndAdv.size())
{
hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //new skill
@ -261,21 +259,8 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
{
hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(none)); //new skill
}
if(hlu.skills.size() > 1) //apply and ask for secondary skill
{
boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(callWith<ui16>,hlu.skills,boost::function<void(ui16)>(boost::bind(&CGameHandler::changeSecSkill,this,ID,_1,1,0)),_1));
applyAndAsk(&hlu,hero->tempOwner,callback); //call changeSecSkill with appropriate args when client responds
}
else if(hlu.skills.size() == 1) //apply, give only possible skill and send info
{
changeSecSkill(ID,hlu.skills.back(),1,false);
sendAndApply(&hlu);
}
else //apply and send info
{
sendAndApply(&hlu);
}
boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(callWith<ui16>,hlu.skills,boost::function<void(ui16)>(boost::bind(&CGameHandler::changeSecSkill,this,ID,_1,1,0)),_1));
applyAndAsk(&hlu,hero->tempOwner,callback); //call changeSecSkill with appropriate args when client responds
}
}
}
@ -1544,10 +1529,15 @@ void CGameHandler::moveStack(int stack, int dest)
//initing necessary tables
bool accessibility[BFIELD_SIZE];
if(curStack->creature->isDoubleWide())
gs->curB->getAccessibilityMapForTwoHex(accessibility,curStack->attackerOwned,curStack->ID);
else
gs->curB->getAccessibilityMap(accessibility,curStack->ID);
std::vector<int> accessible = gs->curB->getAccessibility(curStack->ID, false);
for(int b=0; b<BFIELD_SIZE; ++b)
{
accessibility[b] = false;
}
for(int g=0; g<accessible.size(); ++g)
{
accessibility[accessible[g]] = true;
}
//shifting destination (if we have double wide stack and we can occupy dest but not be exactly there)
if(!stackAtEnd && curStack->creature->isDoubleWide() && !accessibility[dest])
@ -2047,7 +2037,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
curB->obstacles.push_back(coi);
for(int b=0; b<block.size(); ++b)
{
obAv[block[b]] = false;
if(block[b] >= 0 && block[b] < BFIELD_SIZE)
obAv[block[b]] = false;
}
toBlock -= block.size();
}