From 5c86d329037f9e6abe09e7c62928906e3778caf4 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sat, 18 Feb 2012 17:39:47 +0000 Subject: [PATCH] Cloned stack dissapear when killed. Fixed #864 --- client/BattleInterface/CBattleInterface.cpp | 38 +++++++++++++-------- client/BattleInterface/CBattleInterface.h | 1 + client/CPlayerInterface.cpp | 9 ++--- client/NetPacksClient.cpp | 3 +- lib/BattleState.cpp | 4 +-- lib/NetPacks.h | 11 ++++-- lib/NetPacksLib.cpp | 9 ++++- 7 files changed, 48 insertions(+), 27 deletions(-) diff --git a/client/BattleInterface/CBattleInterface.cpp b/client/BattleInterface/CBattleInterface.cpp index d00b6dff6..06ee7b2d7 100644 --- a/client/BattleInterface/CBattleInterface.cpp +++ b/client/BattleInterface/CBattleInterface.cpp @@ -946,18 +946,21 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent) { if ((int)creatureSpellToCast > -1) //use randomized spell (Faerie Dragon), or only avaliable spell (Archangel) { - const CSpell * spell = CGI->spellh->spells[creatureSpellToCast]; - if (curInt->cb->battleCanCastThisSpell(spell, BattleHex(myNumber)) == ESpellCastProblem::OK) + if (shere != sactive) //can't cast on itself { - if ((!spell->isNegative() && ourStack) || (!spell->isPositive() && !ourStack)) + const CSpell * spell = CGI->spellh->spells[creatureSpellToCast]; + if (curInt->cb->battleCanCastThisSpell(spell, BattleHex(myNumber)) == ESpellCastProblem::OK) { - CCS->curh->changeGraphic(3, 0); - stackCastsSpell = true; - std::string buf = CGI->generaltexth->allTexts[27]; //cast %s on &s - boost::replace_first (buf, "%s", spell->name); - boost::replace_first (buf, "%s", shere->getName()); - console->alterTxt = buf; - console->whoSetAlter = 0; + if ((!spell->isNegative() && ourStack) || (!spell->isPositive() && !ourStack)) + { + CCS->curh->changeGraphic(3, 0); + stackCastsSpell = true; + std::string buf = CGI->generaltexth->allTexts[27]; //cast %s on &s + boost::replace_first (buf, "%s", spell->name); + boost::replace_first (buf, "%s", shere->getName()); + console->alterTxt = buf; + console->whoSetAlter = 0; + } } } } @@ -1503,7 +1506,7 @@ void CBattleInterface::bConsoleDownf() void CBattleInterface::newStack(const CStack * stack) { - Point coords = CClickableHex::getXYUnitAnim(stack->position, stack->owner == attackingHeroInstance->tempOwner, stack, this);; + Point coords = CClickableHex::getXYUnitAnim(stack->position, stack->owner == attackingHeroInstance->tempOwner, stack, this); if(stack->position < 0) //turret { @@ -1538,6 +1541,7 @@ void CBattleInterface::newStack(const CStack * stack) creAnims[stack->ID]->setType(CCreatureAnim::HOLDING); creAnims[stack->ID]->pos = Rect(coords.x, coords.y, creAnims[stack->ID]->fullWidth, creAnims[stack->ID]->fullHeight); creDir[stack->ID] = stack->attackerOwned; + } void CBattleInterface::stackRemoved(int stackID) @@ -1551,7 +1555,8 @@ void CBattleInterface::stackActivated(const CStack * stack) //TODO: check it all { //givenCommand = NULL; stackToActivate = stack; - if(pendingAnims.size() == 0) + waitForAnims(); + //if(pendingAnims.size() == 0) activateStack(); } @@ -1563,9 +1568,10 @@ void CBattleInterface::stackMoved(const CStack * stack, std::vector d void CBattleInterface::stacksAreAttacked(std::vector attackedInfos) { - for(size_t h = 0; h < attackedInfos.size(); ++h) + for (size_t h = 0; h < attackedInfos.size(); ++h) { - addNewAnim(new CDefenceAnimation(attackedInfos[h], this)); + if (!attackedInfos[h].cloneKilled) //FIXME: play dead animation for cloned creature before it vanishes + addNewAnim(new CDefenceAnimation(attackedInfos[h], this)); if (attackedInfos[h].rebirth) { displayEffect(50, attackedInfos[h].defender->position); //TODO: play reverse death animation @@ -1580,6 +1586,8 @@ void CBattleInterface::stacksAreAttacked(std::vector attacked killed += attackedInfos[h].killed; damage += attackedInfos[h].dmg; } + if (attackedInfos.front().cloneKilled) //FIXME: cloned stack is already removed + return; if (targets > 1) printConsoleAttacked(attackedInfos.front().defender, damage, killed, attackedInfos.front().attacker, true); //creatures perish else @@ -1589,6 +1597,8 @@ void CBattleInterface::stacksAreAttacked(std::vector attacked { if (attackedInfos[h].rebirth) creAnims[attackedInfos[h].defender->ID]->setType(CCreatureAnim::HOLDING); + if (attackedInfos[h].cloneKilled) + stackRemoved(attackedInfos[h].defender->ID); } } diff --git a/client/BattleInterface/CBattleInterface.h b/client/BattleInterface/CBattleInterface.h index a1705e646..6e53d3ca8 100644 --- a/client/BattleInterface/CBattleInterface.h +++ b/client/BattleInterface/CBattleInterface.h @@ -62,6 +62,7 @@ struct StackAttackedInfo bool byShooting; //if true, stack has been attacked by shooting bool killed; //if true, stack has been killed bool rebirth; //if true, play rebirth animation after all + bool cloneKilled; }; /// Struct for battle effect animation e.g. morale, prayer, armageddon, bless,... diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 06fbe9fb0..cd607e397 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -640,10 +640,8 @@ void CPlayerInterface::battleNewStackAppeared(const CStack * stack) { //another local interface should do this return; } - - //changing necessary things in battle interface + //boost::unique_lock un(*pim); battleInt->newStack(stack); - //battleInt->addNewAnim(new CDummyAnim(battleInt, 2)); //wait a moment } void CPlayerInterface::battleObstaclesRemoved(const std::set & removedObstacles) @@ -686,7 +684,7 @@ void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr) return; } - //boost::unique_lock un(*pim); //fixme: this one caused deadlock + boost::unique_lock un(*pim); //fixme: this one caused deadlock for(std::set::const_iterator it = bsr.stackIDs.begin(); it != bsr.stackIDs.end(); ++it) //for each removed stack { battleInt->stackRemoved(*it); @@ -820,9 +818,8 @@ void CPlayerInterface::battleStacksAttacked(const std::vectorisSecondary()) battleInt->displayEffect(i->effect, defender->position); } - StackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed(), i->willRebirth()}; + StackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed(), i->willRebirth(), i->cloneKilled()}; arg.push_back(to_put); - } if(bsa.begin()->isEffect() && bsa.begin()->effect == 12) //for armageddon - I hope this condition is enough diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 57500e70e..4bb814e4f 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -603,7 +603,8 @@ void BattleStackMoved::applyFirstCl( CClient *cl ) BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStackMoved,movedStack,tilesToMove,distance); } -void BattleStackAttacked::applyCl( CClient *cl ) +//void BattleStackAttacked::( CClient *cl ) +void BattleStackAttacked::applyFirstCl( CClient *cl ) { std::vector bsa; bsa.push_back(*this); diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index d71df6586..3cb312627 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -1299,7 +1299,7 @@ si8 BattleInfo::hasWallPenalty( const CStack* stack, BattleHex destHex ) const if (stackLeft && destRight) //shooting from outside to inside { int row = (stack->position + destHex) / (2 * GameConstants::BFIELD_WIDTH); - if (stack->position > destHex && ((destHex & GameConstants::BFIELD_WIDTH - stack->position % GameConstants::BFIELD_WIDTH) < 2)) //shooting up high + if (stack->position > destHex && ((destHex % GameConstants::BFIELD_WIDTH - stack->position % GameConstants::BFIELD_WIDTH) < 2)) //shooting up high row -= 2; int wallPos = lineToWallHex(row); if (hexToWallPart(wallPos) != -1) //wall still exists or is indestructible @@ -2732,7 +2732,7 @@ void CStack::prepareAttacked(BattleStackAttacked &bsa) const if (bsa.damageAmount && vstd::contains(state, EBattleStackState::CLONED)) // block ability should not kill clone (0 damage) { bsa.killedAmount = count; - bsa.flags |= BattleStackAttacked::KILLED; + bsa.flags |= BattleStackAttacked::CLONE_KILLED; return; // no rebirth I believe } diff --git a/lib/NetPacks.h b/lib/NetPacks.h index ba87dbbed..e5ff86a00 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1270,12 +1270,13 @@ struct StacksHealedOrResurrected : public CPackForClient //3013 struct BattleStackAttacked : public CPackForClient//3005 { BattleStackAttacked(){flags = 0; type = 3005;}; - void applyCl(CClient *cl); + void applyFirstCl(CClient * cl); + //void applyCl(CClient *cl); DLL_LINKAGE void applyGs(CGameState *gs); ui32 stackAttacked, attackerID; ui32 newAmount, newHP, killedAmount, damageAmount; - enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4, REBIRTH = 8}; + enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4, REBIRTH = 8, CLONE_KILLED = 16}; ui8 flags; //uses EFlags (above) ui32 effect; //set only if flag EFFECT is set std::vector healedStacks; //used when life drain @@ -1283,7 +1284,11 @@ struct BattleStackAttacked : public CPackForClient//3005 bool killed() const//if target stack was killed { - return flags & KILLED; + return flags & KILLED || flags & CLONE_KILLED; + } + bool cloneKilled() const + { + return flags & CLONE_KILLED; } bool isEffect() const//if stack has been attacked by a spell { diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 0bda9af43..cdb42faff 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -972,6 +972,12 @@ DLL_LINKAGE void BattleStackAttacked::applyGs( CGameState *gs ) at->casts--; at->state.insert(EBattleStackState::ALIVE); //hmm? } + if (cloneKilled()) + { + BattleStacksRemoved bsr; //remove body + bsr.stackIDs.insert(at->ID); + bsr.applyGs(gs); + } } DLL_LINKAGE void BattleAttack::applyGs( CGameState *gs ) @@ -1006,7 +1012,8 @@ DLL_LINKAGE void BattleAttack::applyGs( CGameState *gs ) for(std::vector::const_iterator it = bsa.begin(); it != bsa.end(); ++it) { CStack * stack = gs->curB->getStack(it->stackAttacked, false); - stack->getBonusList().remove_if(Bonus::UntilBeingAttacked); + if (stack) //cloned stack is already gone + stack->getBonusList().remove_if(Bonus::UntilBeingAttacked); } }