mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
* fixed crash on saving when some objects havebeen removed
* support for multi-target attacks/spells in the protocol * version bumped to 0.7d
This commit is contained in:
parent
0cf1b2588d
commit
b2c4f3e0fd
@ -97,9 +97,9 @@ void CGeniusAI::battleAttack(BattleAttack *ba)
|
||||
/**
|
||||
* called when stack receives damage (after battleAttack())
|
||||
*/
|
||||
void CGeniusAI::battleStackAttacked(BattleStackAttacked * bsa)
|
||||
void CGeniusAI::battleStacksAttacked(std::set<BattleStackAttacked> & bsa)
|
||||
{
|
||||
MsgBox("\t\t\tCGeniusAI::battleStackAttacked");
|
||||
MsgBox("\t\t\tCGeniusAI::battleStacksAttacked");
|
||||
}
|
||||
/**
|
||||
* called by engine when battle starts; side=0 - left, side=1 - right
|
||||
|
@ -197,7 +197,7 @@ public:
|
||||
virtual void actionFinished(const BattleAction *action);//occurs AFTER every action taken by any stack or by the hero
|
||||
virtual void actionStarted(const BattleAction *action);//occurs BEFORE every action taken by any stack or by the hero
|
||||
virtual void battleAttack(BattleAttack *ba); //called when stack is performing attack
|
||||
virtual void battleStackAttacked(BattleStackAttacked * bsa); //called when stack receives damage (after battleAttack())
|
||||
virtual void battleStacksAttacked(std::set<BattleStackAttacked> & bsa); //called when stack receives damage (after battleAttack())
|
||||
virtual void battleEnd(BattleResult *br);
|
||||
virtual void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
virtual void battleStackMoved(int ID, int dest);
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
virtual void actionStarted(const BattleAction *action){};//occurs BEFORE every action taken by any stack or by the hero
|
||||
virtual BattleAction activeStack(int stackID)=0; //called when it's turn of that stack
|
||||
virtual void battleAttack(BattleAttack *ba){}; //called when stack is performing attack
|
||||
virtual void battleStackAttacked(BattleStackAttacked * bsa){}; //called when stack receives damage (after battleAttack())
|
||||
virtual void battleStacksAttacked(std::set<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
|
||||
virtual void battleEnd(BattleResult *br){};
|
||||
virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
virtual void battleStackMoved(int ID, int dest, int distance){};
|
||||
|
@ -2288,18 +2288,24 @@ void CPlayerInterface::battleSpellCasted(SpellCasted *sc)
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
battleInt->spellCasted(sc);
|
||||
}
|
||||
void CPlayerInterface::battleStackAttacked(BattleStackAttacked * bsa)
|
||||
void CPlayerInterface::battleStacksAttacked(std::set<BattleStackAttacked> & bsa)
|
||||
{
|
||||
tlog5 << "CPlayerInterface::battleStackAttacked - locking...";
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
tlog5 << "done!\n";
|
||||
if(bsa->isEffect())
|
||||
{
|
||||
battleInt->displayEffect(bsa->effect, cb->battleGetStackByID(bsa->stackAttacked)->position);
|
||||
}
|
||||
|
||||
|
||||
std::vector<CBattleInterface::SStackAttackedInfo> arg;
|
||||
CBattleInterface::SStackAttackedInfo to_put = {bsa->stackAttacked, bsa->damageAmount, bsa->killedAmount, LOCPLINT->curAction->stackNumber, LOCPLINT->curAction->actionType==7, bsa->killed()};
|
||||
arg.push_back(to_put);
|
||||
for(std::set<BattleStackAttacked>::iterator i = bsa.begin(); i != bsa.end(); i++)
|
||||
{
|
||||
if(i->isEffect())
|
||||
{
|
||||
battleInt->displayEffect(i->effect, cb->battleGetStackByID(i->stackAttacked)->position);
|
||||
}
|
||||
CBattleInterface::SStackAttackedInfo to_put = {i->stackAttacked, i->damageAmount, i->killedAmount, LOCPLINT->curAction->stackNumber, LOCPLINT->curAction->actionType==7, i->killed()};
|
||||
arg.push_back(to_put);
|
||||
}
|
||||
|
||||
battleInt->stacksAreAttacked(arg);
|
||||
}
|
||||
void CPlayerInterface::battleAttack(BattleAttack *ba)
|
||||
@ -2307,7 +2313,7 @@ void CPlayerInterface::battleAttack(BattleAttack *ba)
|
||||
tlog5 << "CPlayerInterface::battleAttack - locking...";
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
tlog5 << "done!\n";
|
||||
if(ba->bsa.lucky()) //lucky hit
|
||||
if(ba->lucky()) //lucky hit
|
||||
{
|
||||
CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
|
||||
std::string hlp = CGI->generaltexth->allTexts[45];
|
||||
@ -2315,8 +2321,13 @@ void CPlayerInterface::battleAttack(BattleAttack *ba)
|
||||
battleInt->console->addText(hlp);
|
||||
battleInt->displayEffect(18,stack->position);
|
||||
}
|
||||
//TODO: bad luck?
|
||||
|
||||
if(ba->shot())
|
||||
battleInt->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
|
||||
{
|
||||
for(std::set<BattleStackAttacked>::iterator i = ba->bsa.begin(); i != ba->bsa.end(); i++)
|
||||
battleInt->stackIsShooting(ba->stackAttacking,cb->battleGetPos(i->stackAttacked));
|
||||
}
|
||||
else
|
||||
{
|
||||
CStack * attacker = cb->battleGetStackByID(ba->stackAttacking);
|
||||
|
@ -495,7 +495,7 @@ public:
|
||||
void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
void battleStackMoved(int ID, int dest, int distance);
|
||||
void battleSpellCasted(SpellCasted *sc);
|
||||
void battleStackAttacked(BattleStackAttacked * bsa);
|
||||
void battleStacksAttacked(std::set<BattleStackAttacked> & bsa);
|
||||
void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
|
||||
|
||||
|
@ -335,11 +335,11 @@ void BattleStackMoved::applyFirstCl( CClient *cl )
|
||||
|
||||
void BattleStackAttacked::applyCl( CClient *cl )
|
||||
{
|
||||
std::set<BattleStackAttacked> bsa;
|
||||
bsa.insert(*this);
|
||||
|
||||
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side1]->battleStackAttacked(this);
|
||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side2]->battleStackAttacked(this);
|
||||
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStacksAttacked,bsa);
|
||||
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStacksAttacked,bsa);
|
||||
}
|
||||
|
||||
void BattleAttack::applyFirstCl( CClient *cl )
|
||||
@ -352,10 +352,8 @@ void BattleAttack::applyFirstCl( CClient *cl )
|
||||
|
||||
void BattleAttack::applyCl( CClient *cl )
|
||||
{
|
||||
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side1]->battleStackAttacked(&bsa);
|
||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side2]->battleStackAttacked(&bsa);
|
||||
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStacksAttacked,bsa);
|
||||
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStacksAttacked,bsa);
|
||||
}
|
||||
|
||||
void StartAction::applyFirstCl( CClient *cl )
|
||||
@ -381,11 +379,14 @@ void SetStackEffect::applyCl( CClient *cl )
|
||||
sc.id = effect.id;
|
||||
sc.side = 3; //doesn't matter
|
||||
sc.skill = effect.level;
|
||||
sc.tile = GS(cl)->curB->getStack(stack)->position;
|
||||
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side1]->battleSpellCasted(&sc);
|
||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side2]->battleSpellCasted(&sc);
|
||||
BOOST_FOREACH(ui32 stack, stacks)
|
||||
{
|
||||
sc.tile = GS(cl)->curB->getStack(stack)->position;
|
||||
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side1]->battleSpellCasted(&sc);
|
||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side2]->battleSpellCasted(&sc);
|
||||
}
|
||||
}
|
||||
|
||||
CGameState* CPackForClient::GS( CClient *cl )
|
||||
|
2
global.h
2
global.h
@ -19,7 +19,7 @@ typedef boost::int8_t si8; //signed int 8 bits (1 byte)
|
||||
#define THC
|
||||
#endif
|
||||
|
||||
#define NAME_VER ("VCMI 0.7c")
|
||||
#define NAME_VER ("VCMI 0.7d")
|
||||
#define CONSOLE_LOGGING_LEVEL 5
|
||||
#define FILE_LOGGING_LEVEL 6
|
||||
|
||||
|
@ -665,7 +665,7 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
|
||||
ui32 stackAttacked;
|
||||
ui32 newAmount, newHP, killedAmount, damageAmount;
|
||||
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown; 4 - lucky hit
|
||||
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown;
|
||||
ui32 effect; //set only if flag 2 is present
|
||||
|
||||
bool killed() //if target stack was killed
|
||||
@ -676,14 +676,14 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
{
|
||||
return flags & 2;
|
||||
}
|
||||
bool lucky()
|
||||
{
|
||||
return flags & 4;
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount & effect;
|
||||
}
|
||||
bool operator<(const BattleStackAttacked &b) const
|
||||
{
|
||||
return stackAttacked < b.stackAttacked;
|
||||
}
|
||||
};
|
||||
|
||||
struct BattleAttack : public CPackForClient//3006
|
||||
@ -693,7 +693,7 @@ struct BattleAttack : public CPackForClient//3006
|
||||
DLL_EXPORT void applyGs(CGameState *gs);
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
BattleStackAttacked bsa;
|
||||
std::set<BattleStackAttacked> bsa;
|
||||
ui32 stackAttacking;
|
||||
ui8 flags;
|
||||
|
||||
@ -705,10 +705,19 @@ struct BattleAttack : public CPackForClient//3006
|
||||
{
|
||||
return flags & 2;
|
||||
}
|
||||
bool killed() //if target stack was killed
|
||||
bool lucky()
|
||||
{
|
||||
return bsa.killed();
|
||||
return flags & 4;
|
||||
}
|
||||
bool unlucky()
|
||||
{
|
||||
//TODO: support?
|
||||
return flags & 8;
|
||||
}
|
||||
//bool killed() //if target stack was killed
|
||||
//{
|
||||
// return bsa.killed();
|
||||
//}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & bsa & stackAttacking & flags;
|
||||
@ -761,11 +770,11 @@ struct SetStackEffect : public CPackForClient //3010
|
||||
DLL_EXPORT void applyGs(CGameState *gs);
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
ui32 stack;
|
||||
std::set<ui32> stacks;
|
||||
CStack::StackEffect effect;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & stack & effect;
|
||||
h & stacks & effect;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -428,7 +428,8 @@ DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
|
||||
attacker->counterAttacks--;
|
||||
if(shot())
|
||||
attacker->shots--;
|
||||
bsa.applyGs(gs);
|
||||
BOOST_FOREACH(BattleStackAttacked &stackAttacked, bsa)
|
||||
stackAttacked.applyGs(gs);
|
||||
}
|
||||
|
||||
DLL_EXPORT void StartAction::applyGs( CGameState *gs )
|
||||
@ -464,8 +465,14 @@ DLL_EXPORT void SpellCasted::applyGs( CGameState *gs )
|
||||
|
||||
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
||||
{
|
||||
CStack *s = gs->curB->getStack(stack);
|
||||
s->effects.push_back(effect);
|
||||
BOOST_FOREACH(ui32 id, stacks)
|
||||
{
|
||||
CStack *s = gs->curB->getStack(id);
|
||||
if(s)
|
||||
s->effects.push_back(effect);
|
||||
else
|
||||
tlog1 << "Cannot find stack " << id << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
|
||||
|
13
map.h
13
map.h
@ -389,11 +389,14 @@ struct DLL_EXPORT Mapa : public CMapHeader
|
||||
CGObjectInstance *&obj = objects[i];
|
||||
h & obj;
|
||||
|
||||
si32 shlp;
|
||||
//definfo
|
||||
h & (h.saving ? (shlp=obj->defInfo->serial) : shlp); //read / write pos of definfo in defs vector
|
||||
if(!h.saving)
|
||||
obj->defInfo = defy[shlp];
|
||||
if (obj)
|
||||
{
|
||||
si32 shlp;
|
||||
//definfo
|
||||
h & (h.saving ? (shlp=obj->defInfo->serial) : shlp); //read / write pos of definfo in defs vector
|
||||
if(!h.saving)
|
||||
obj->defInfo = defy[shlp];
|
||||
}
|
||||
}
|
||||
|
||||
if(!h.saving)
|
||||
|
@ -485,14 +485,16 @@ void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def)
|
||||
void CGameHandler::prepareAttack(BattleAttack &bat, CStack *att, CStack *def)
|
||||
{
|
||||
bat.stackAttacking = att->ID;
|
||||
bat.bsa.stackAttacked = def->ID;
|
||||
bat.bsa.damageAmount = BattleInfo::calculateDmg(att, def, gs->getHero(att->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), gs->getHero(def->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), bat.shot());//counting dealt damage
|
||||
std::set<BattleStackAttacked>::iterator bsa = bat.bsa.insert(BattleStackAttacked()).first;
|
||||
|
||||
bsa->stackAttacked = def->ID;
|
||||
bsa->damageAmount = BattleInfo::calculateDmg(att, def, gs->getHero(att->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), gs->getHero(def->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), bat.shot());//counting dealt damage
|
||||
if(att->Luck() > 0 && rand()%24 < att->Luck())
|
||||
{
|
||||
bat.bsa.damageAmount *= 2;
|
||||
bat.bsa.flags |= 4;
|
||||
bsa->damageAmount *= 2;
|
||||
bsa->flags |= 4;
|
||||
}
|
||||
prepareAttacked(bat.bsa,def);
|
||||
prepareAttacked(*bsa,def);
|
||||
}
|
||||
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
||||
{
|
||||
@ -2226,7 +2228,7 @@ void CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
#define SPELL_CAST_TEMPLATE_1(NUMBER, DURATION) SetStackEffect sse; \
|
||||
if(getSchoolLevel(h,s) < 3) /*not expert */ \
|
||||
{ \
|
||||
sse.stack = gs->curB->getStackT(ba.destinationTile)->ID; \
|
||||
sse.stacks.insert(gs->curB->getStackT(ba.destinationTile)->ID); \
|
||||
sse.effect.id = (NUMBER); \
|
||||
sse.effect.level = getSchoolLevel(h,s); \
|
||||
sse.effect.turnsRemain = (DURATION); /*! - any duration */ \
|
||||
@ -2241,7 +2243,7 @@ if(getSchoolLevel(h,s) < 3) /*not expert */ \
|
||||
||(VLC->spellh->spells[ba.additionalInfo].positiveness <= 0 && gs->curB->stacks[it]->owner != h->tempOwner ) \
|
||||
) \
|
||||
{ \
|
||||
sse.stack = gs->curB->stacks[it]->ID; \
|
||||
sse.stacks.insert(gs->curB->stacks[it]->ID); \
|
||||
sse.effect.id = (NUMBER); \
|
||||
sse.effect.level = getSchoolLevel(h,s); \
|
||||
sse.effect.turnsRemain = (DURATION); \
|
||||
|
Loading…
Reference in New Issue
Block a user