Browse Source

* servers will not allow using out-of-range slots ( #1061 )
* server won't crash on some scenarios when they're used
* fixed some minor discrepancies with creature placement in creature banks

Michał W. Urbańczyk 13 years ago
parent
commit
6530e7a1e1

+ 1 - 1
client/CBitmapHandler.cpp

@@ -159,7 +159,7 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
 
 	if (!(bitmap = loadBitmapFromDir("DATA/", fname, setKey)) &&
 		!(bitmap = loadBitmapFromDir("SPRITES/", fname, setKey)))
-		tlog0<<"Error: Failed to find file "<<fname<<"\n";
+		tlog1<<"Error: Failed to find file "<<fname<<"\n";
 
 	return bitmap;
 }

+ 6 - 0
client/GUIClasses.cpp

@@ -82,6 +82,12 @@ void CArmyTooltip::init(const InfoAboutArmy &army)
 
 	BOOST_FOREACH(auto & slot, army.army)
 	{
+		if(slot.first >= GameConstants::ARMY_SIZE)
+		{
+			tlog3 << "Warning: " << army.name << " has stack in slot " << slot.first << std::endl;
+			continue;
+		}
+
 		new CAnimImage("CPRSMALL", slot.second.type->idNumber + 2, 0, slotsPos[slot.first].x, slotsPos[slot.first].y);
 
 		std::string subtitle;

+ 5 - 5
config/battleStartpos.json

@@ -71,11 +71,11 @@
 			"levels": [
 				[ 15 ],
 				[ 15, 185 ],
-				[ 15, 185, 171 ],
-				[ 15, 185, 171, 1 ],
-				[ 15, 185, 171, 1, 100 ],
-				[ 15, 185, 171, 1, 100, 86 ],
-				[ 15, 185, 171, 1, 100, 86, 8 ]
+				[ 15, 185, 172 ],
+				[ 15, 185, 172, 2 ],
+				[ 15, 185, 172, 2, 100 ],
+				[ 15, 185, 172, 2, 100, 86 ],
+				[ 15, 185, 172, 2, 100, 86, 8 ]
 				]
 		}
 	],

+ 27 - 48
lib/BattleState.cpp

@@ -911,17 +911,17 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
 
 	//reading battleStartpos - add creatures AFTER random obstacles are generated
 	//TODO: parse once to some structure
-	std::vector< std::vector<int> > attackerLoose, defenderLoose, attackerTight, defenderTight, attackerCreBank, defenderCreBank;
+	std::vector< std::vector<int> > looseFormations[2], tightFormations[2], creBankFormations[2];
 	std::vector <int> commanderField, commanderBank;
 	const JsonNode config(ResourceID("config/battleStartpos.json"));
 	const JsonVector &positions = config["battle_positions"].Vector();
 
-	CGH::readBattlePositions(positions[0]["levels"], attackerLoose);
-	CGH::readBattlePositions(positions[1]["levels"], defenderLoose);
-	CGH::readBattlePositions(positions[2]["levels"], attackerTight);
-	CGH::readBattlePositions(positions[3]["levels"], defenderTight);
-	CGH::readBattlePositions(positions[4]["levels"], attackerCreBank);
-	CGH::readBattlePositions(positions[5]["levels"], defenderCreBank);
+	CGH::readBattlePositions(positions[0]["levels"], looseFormations[0]);
+	CGH::readBattlePositions(positions[1]["levels"], looseFormations[1]);
+	CGH::readBattlePositions(positions[2]["levels"], tightFormations[0]);
+	CGH::readBattlePositions(positions[3]["levels"], tightFormations[1]);
+	CGH::readBattlePositions(positions[4]["levels"], creBankFormations[0]);
+	CGH::readBattlePositions(positions[5]["levels"], creBankFormations[1]);
 
 	BOOST_FOREACH (auto position, config["commanderPositions"]["field"].Vector())
 	{
@@ -957,51 +957,30 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
 	//war machines added
 
 	//battleStartpos read
-	int k = 0; //stack serial
-	for(TSlots::const_iterator i = armies[0]->Slots().begin(); i!=armies[0]->Slots().end(); i++, k++)
-	{
-		int pos;
-		if(creatureBank)
-			pos = attackerCreBank[armies[0]->stacksCount()-1][k];
-		else if(armies[0]->formation)
-			pos = attackerTight[armies[0]->stacksCount()-1][k];
-		else
-			pos = attackerLoose[armies[0]->stacksCount()-1][k];
+	for(int side = 0; side < 2; side++)
+	{
+		int formationNo = armies[side]->stacksCount() - 1;
+		vstd::abetween(formationNo, 0, GameConstants::ARMY_SIZE - 1);
 
-		CStack * stack = curB->generateNewStack(*i->second, true, i->first, pos);
-		stacks.push_back(stack);
-	}
+		int k = 0; //stack serial
+		for(TSlots::const_iterator i = armies[side]->Slots().begin(); i != armies[side]->Slots().end(); i++, k++)
+		{
+			std::vector<int> *formationVector = nullptr;
+			if(creatureBank)
+				formationVector = &creBankFormations[side][formationNo];
+			else if(armies[side]->formation)
+				formationVector = &tightFormations[side][formationNo];
+			else
+				formationVector = &looseFormations[side][formationNo];
 
-	k = 0;
-	for(TSlots::const_iterator i = armies[1]->Slots().begin(); i!=armies[1]->Slots().end(); i++, k++)
-	{
-		int pos;
-		if(creatureBank)
-			pos = defenderCreBank[armies[1]->stacksCount()-1][k];
-		else if(armies[1]->formation)
-			pos = defenderTight[armies[1]->stacksCount()-1][k];
-		else
-			pos = defenderLoose[armies[1]->stacksCount()-1][k];
+			BattleHex pos = (k < formationVector->size() ? formationVector->at(k) : 0);
+			if(creatureBank && i->second->type->isDoubleWide())
+				pos += side ? BattleHex::LEFT : BattleHex::RIGHT;
 
-		CStack * stack = curB->generateNewStack(*i->second, false, i->first, pos);
-		stacks.push_back(stack);
+			CStack * stack = curB->generateNewStack(*i->second, !side, i->first, pos);
+			stacks.push_back(stack);
+		}
 	}
-	
-// 	//shifting positions of two-hex creatures
-// 	for(unsigned g=0; g<stacks.size(); ++g)
-// 	{
-// 		//we should do that for creature bank too
-// 		if(stacks[g]->doubleWide() && stacks[g]->attackerOwned)
-// 		{
-// 			stacks[g]->position += BattleHex::RIGHT;
-// 		}
-// 		else if(stacks[g]->doubleWide() && !stacks[g]->attackerOwned)
-// 		{
-// 			if (stacks[g]->position.getX() > 1)
-// 				stacks[g]->position += BattleHex::LEFT;
-// 		}
-// 	}
-
 
 	//adding commanders
 	for (int i = 0; i < 2; ++i)

+ 1 - 1
lib/CBattleCallback.cpp

@@ -348,7 +348,7 @@ bool CBattleInfoEssentials::battleCanSurrender(int player) const
 {
 	RETURN_IF_NOT_BATTLE(false);
 	//conditions like for fleeing + enemy must have a hero
-	return battleCanFlee(player) && battleGetFightingHero(!playerToSide(player));
+	return battleCanFlee(player) && battleHasHero(!playerToSide(player));
 }
 
 bool CBattleInfoEssentials::battleHasHero(ui8 side) const

+ 1 - 0
lib/CCreatureSet.cpp

@@ -322,6 +322,7 @@ CArmedInstance * CCreatureSet::castToArmyObj()
 
 void CCreatureSet::putStack(TSlot slot, CStackInstance *stack)
 {
+	assert(slot < GameConstants::ARMY_SIZE);
 	assert(!hasStackAtSlot(slot));
 	stacks[slot] = stack;
 	stack->setArmyObj(castToArmyObj());

+ 6 - 0
lib/NetPacks.h

@@ -185,6 +185,12 @@ struct StackLocation
 		army = const_cast<CArmedInstance*>(Army); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
 		slot = Slot;
 	}
+
+	bool validSlot() const
+	{
+		return slot >= 0  &&  slot < GameConstants::ARMY_SIZE;
+	}
+
 	DLL_LINKAGE const CStackInstance *getStack();
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 12 - 1
server/CGameHandler.cpp

@@ -2299,6 +2299,11 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
 		*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2].get());
 	const CCreatureSet &S1 = *s1, &S2 = *s2;
 	StackLocation sl1(s1, p1), sl2(s2, p2);
+	if(!sl1.validSlot()  ||  !sl2.validSlot())
+	{
+		complain("Invalid slot accessed!");
+		return false;
+	}
 
 	if(!isAllowedExchange(id1,id2))
 	{
@@ -5616,6 +5621,9 @@ bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, T
 	if(sl.army->hasStackAtSlot(sl.slot))
 		COMPLAIN_RET("Slot is already taken!");
 
+	if(!sl.validSlot())
+		COMPLAIN_RET("Cannot insert stack to that slot!");
+
 	InsertNewStack ins;
 	ins.sl = sl;
 	ins.stack = CStackBasicDescriptor(c, count);
@@ -5723,6 +5731,9 @@ bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst,
 	if(dst.army->hasStackAtSlot(dst.slot) && dst.army->getCreature(dst.slot) != src.army->getCreature(src.slot))
 		COMPLAIN_RET("Cannot move: stack of different type at destination pos!");
 
+	if(!dst.validSlot())
+		COMPLAIN_RET("Cannot move stack to that slot!");
+
 	if(count == -1)
 	{
 		count = src.army->getStackCount(src.slot);
@@ -5733,7 +5744,7 @@ bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst,
 		&& src.army->Slots().size() == 1 //from the last stack
 		&& src.army->needsLastStack()) //that must be left
 	{
-		COMPLAIN_RET("Cannot move away the alst creature!");
+		COMPLAIN_RET("Cannot move away the last creature!");
 	}
 
 	RebalanceStacks rs;