Răsfoiți Sursa

* 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)

mateuszb 16 ani în urmă
părinte
comite
b42a7fa87b
5 a modificat fișierele cu 120 adăugiri și 49 ștergeri
  1. 3 2
      CBattleInterface.cpp
  2. 27 3
      CCallback.cpp
  3. 74 19
      CGameState.cpp
  4. 2 2
      config/obstacles.txt
  5. 14 23
      server/CGameHandler.cpp

+ 3 - 2
CBattleInterface.cpp

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

+ 27 - 3
CCallback.cpp

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

+ 74 - 19
CGameState.cpp

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

+ 2 - 2
config/obstacles.txt

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

+ 14 - 23
server/CGameHandler.cpp

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