mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
* 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
This commit is contained in:
parent
838c226a31
commit
6530e7a1e1
@ -159,7 +159,7 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
|
|||||||
|
|
||||||
if (!(bitmap = loadBitmapFromDir("DATA/", fname, setKey)) &&
|
if (!(bitmap = loadBitmapFromDir("DATA/", fname, setKey)) &&
|
||||||
!(bitmap = loadBitmapFromDir("SPRITES/", 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;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,12 @@ void CArmyTooltip::init(const InfoAboutArmy &army)
|
|||||||
|
|
||||||
BOOST_FOREACH(auto & slot, army.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);
|
new CAnimImage("CPRSMALL", slot.second.type->idNumber + 2, 0, slotsPos[slot.first].x, slotsPos[slot.first].y);
|
||||||
|
|
||||||
std::string subtitle;
|
std::string subtitle;
|
||||||
|
@ -71,11 +71,11 @@
|
|||||||
"levels": [
|
"levels": [
|
||||||
[ 15 ],
|
[ 15 ],
|
||||||
[ 15, 185 ],
|
[ 15, 185 ],
|
||||||
[ 15, 185, 171 ],
|
[ 15, 185, 172 ],
|
||||||
[ 15, 185, 171, 1 ],
|
[ 15, 185, 172, 2 ],
|
||||||
[ 15, 185, 171, 1, 100 ],
|
[ 15, 185, 172, 2, 100 ],
|
||||||
[ 15, 185, 171, 1, 100, 86 ],
|
[ 15, 185, 172, 2, 100, 86 ],
|
||||||
[ 15, 185, 171, 1, 100, 86, 8 ]
|
[ 15, 185, 172, 2, 100, 86, 8 ]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -911,17 +911,17 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
|
|||||||
|
|
||||||
//reading battleStartpos - add creatures AFTER random obstacles are generated
|
//reading battleStartpos - add creatures AFTER random obstacles are generated
|
||||||
//TODO: parse once to some structure
|
//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;
|
std::vector <int> commanderField, commanderBank;
|
||||||
const JsonNode config(ResourceID("config/battleStartpos.json"));
|
const JsonNode config(ResourceID("config/battleStartpos.json"));
|
||||||
const JsonVector &positions = config["battle_positions"].Vector();
|
const JsonVector &positions = config["battle_positions"].Vector();
|
||||||
|
|
||||||
CGH::readBattlePositions(positions[0]["levels"], attackerLoose);
|
CGH::readBattlePositions(positions[0]["levels"], looseFormations[0]);
|
||||||
CGH::readBattlePositions(positions[1]["levels"], defenderLoose);
|
CGH::readBattlePositions(positions[1]["levels"], looseFormations[1]);
|
||||||
CGH::readBattlePositions(positions[2]["levels"], attackerTight);
|
CGH::readBattlePositions(positions[2]["levels"], tightFormations[0]);
|
||||||
CGH::readBattlePositions(positions[3]["levels"], defenderTight);
|
CGH::readBattlePositions(positions[3]["levels"], tightFormations[1]);
|
||||||
CGH::readBattlePositions(positions[4]["levels"], attackerCreBank);
|
CGH::readBattlePositions(positions[4]["levels"], creBankFormations[0]);
|
||||||
CGH::readBattlePositions(positions[5]["levels"], defenderCreBank);
|
CGH::readBattlePositions(positions[5]["levels"], creBankFormations[1]);
|
||||||
|
|
||||||
BOOST_FOREACH (auto position, config["commanderPositions"]["field"].Vector())
|
BOOST_FOREACH (auto position, config["commanderPositions"]["field"].Vector())
|
||||||
{
|
{
|
||||||
@ -957,52 +957,31 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
|
|||||||
//war machines added
|
//war machines added
|
||||||
|
|
||||||
//battleStartpos read
|
//battleStartpos read
|
||||||
int k = 0; //stack serial
|
for(int side = 0; side < 2; side++)
|
||||||
for(TSlots::const_iterator i = armies[0]->Slots().begin(); i!=armies[0]->Slots().end(); i++, k++)
|
|
||||||
{
|
{
|
||||||
int pos;
|
int formationNo = armies[side]->stacksCount() - 1;
|
||||||
if(creatureBank)
|
vstd::abetween(formationNo, 0, GameConstants::ARMY_SIZE - 1);
|
||||||
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];
|
|
||||||
|
|
||||||
CStack * stack = curB->generateNewStack(*i->second, true, i->first, pos);
|
int k = 0; //stack serial
|
||||||
stacks.push_back(stack);
|
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];
|
||||||
|
|
||||||
|
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, !side, i->first, pos);
|
||||||
|
stacks.push_back(stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
|
||||||
|
|
||||||
CStack * stack = curB->generateNewStack(*i->second, false, 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
|
//adding commanders
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +348,7 @@ bool CBattleInfoEssentials::battleCanSurrender(int player) const
|
|||||||
{
|
{
|
||||||
RETURN_IF_NOT_BATTLE(false);
|
RETURN_IF_NOT_BATTLE(false);
|
||||||
//conditions like for fleeing + enemy must have a hero
|
//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
|
bool CBattleInfoEssentials::battleHasHero(ui8 side) const
|
||||||
|
@ -322,6 +322,7 @@ CArmedInstance * CCreatureSet::castToArmyObj()
|
|||||||
|
|
||||||
void CCreatureSet::putStack(TSlot slot, CStackInstance *stack)
|
void CCreatureSet::putStack(TSlot slot, CStackInstance *stack)
|
||||||
{
|
{
|
||||||
|
assert(slot < GameConstants::ARMY_SIZE);
|
||||||
assert(!hasStackAtSlot(slot));
|
assert(!hasStackAtSlot(slot));
|
||||||
stacks[slot] = stack;
|
stacks[slot] = stack;
|
||||||
stack->setArmyObj(castToArmyObj());
|
stack->setArmyObj(castToArmyObj());
|
||||||
|
@ -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!
|
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;
|
slot = Slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validSlot() const
|
||||||
|
{
|
||||||
|
return slot >= 0 && slot < GameConstants::ARMY_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
DLL_LINKAGE const CStackInstance *getStack();
|
DLL_LINKAGE const CStackInstance *getStack();
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
@ -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());
|
*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2].get());
|
||||||
const CCreatureSet &S1 = *s1, &S2 = *s2;
|
const CCreatureSet &S1 = *s1, &S2 = *s2;
|
||||||
StackLocation sl1(s1, p1), sl2(s2, p2);
|
StackLocation sl1(s1, p1), sl2(s2, p2);
|
||||||
|
if(!sl1.validSlot() || !sl2.validSlot())
|
||||||
|
{
|
||||||
|
complain("Invalid slot accessed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!isAllowedExchange(id1,id2))
|
if(!isAllowedExchange(id1,id2))
|
||||||
{
|
{
|
||||||
@ -5616,6 +5621,9 @@ bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, T
|
|||||||
if(sl.army->hasStackAtSlot(sl.slot))
|
if(sl.army->hasStackAtSlot(sl.slot))
|
||||||
COMPLAIN_RET("Slot is already taken!");
|
COMPLAIN_RET("Slot is already taken!");
|
||||||
|
|
||||||
|
if(!sl.validSlot())
|
||||||
|
COMPLAIN_RET("Cannot insert stack to that slot!");
|
||||||
|
|
||||||
InsertNewStack ins;
|
InsertNewStack ins;
|
||||||
ins.sl = sl;
|
ins.sl = sl;
|
||||||
ins.stack = CStackBasicDescriptor(c, count);
|
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))
|
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!");
|
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)
|
if(count == -1)
|
||||||
{
|
{
|
||||||
count = src.army->getStackCount(src.slot);
|
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->Slots().size() == 1 //from the last stack
|
||||||
&& src.army->needsLastStack()) //that must be left
|
&& 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;
|
RebalanceStacks rs;
|
||||||
|
Loading…
Reference in New Issue
Block a user