mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-07 00:58:39 +02:00
Partially implemented #481
This commit is contained in:
@ -712,7 +712,6 @@ void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr)
|
|||||||
for(auto & elem : bsr.stackIDs) //for each removed stack
|
for(auto & elem : bsr.stackIDs) //for each removed stack
|
||||||
{
|
{
|
||||||
battleInt->stackRemoved(elem);
|
battleInt->stackRemoved(elem);
|
||||||
//battleInt->stackRemoved(LOCPLINT->cb->battleGetStackByID(*it));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,6 +1010,7 @@ void CBattleInterface::stackRemoved(int stackID)
|
|||||||
delete creAnims[stackID];
|
delete creAnims[stackID];
|
||||||
creAnims.erase(stackID);
|
creAnims.erase(stackID);
|
||||||
creDir.erase(stackID);
|
creDir.erase(stackID);
|
||||||
|
//FIXME: what if currently removed stack is active one (Sacrifice)?
|
||||||
|
|
||||||
redrawBackgroundWithHexes(activeStack);
|
redrawBackgroundWithHexes(activeStack);
|
||||||
queue->update();
|
queue->update();
|
||||||
|
@ -145,7 +145,7 @@ private:
|
|||||||
const CStack * mouseHoveredStack; // stack below mouse pointer, used for border animation
|
const CStack * mouseHoveredStack; // stack below mouse pointer, used for border animation
|
||||||
const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; nullptr of none
|
const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; nullptr of none
|
||||||
const CStack * selectedStack; //for Teleport / Sacrifice
|
const CStack * selectedStack; //for Teleport / Sacrifice
|
||||||
void activateStack(); //sets activeStack to stackToActivate etc.
|
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
|
||||||
std::vector<BattleHex> occupyableHexes, //hexes available for active stack
|
std::vector<BattleHex> occupyableHexes, //hexes available for active stack
|
||||||
attackableHexes; //hexes attackable by active stack
|
attackableHexes; //hexes attackable by active stack
|
||||||
bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
|
bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
|
||||||
|
@ -5333,6 +5333,61 @@ void CGBonusingObject::initObj()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGMagicSpring::setPropertyDer(ui8 what, ui32 val)
|
||||||
|
{
|
||||||
|
CGVisitableOPW::setPropertyDer (what, val); //set visitable if applicable
|
||||||
|
if (what == ObjProperty::LEFT_VISITED)
|
||||||
|
{
|
||||||
|
if (visitedTile == RIGHT)
|
||||||
|
visited = true; //both field were used, object is not available this week
|
||||||
|
else
|
||||||
|
visitedTile = LEFT;
|
||||||
|
}
|
||||||
|
else if (what == ObjProperty::RIGHT_VISITED)
|
||||||
|
{
|
||||||
|
if (visitedTile == LEFT)
|
||||||
|
visited = true;
|
||||||
|
else
|
||||||
|
visitedTile = RIGHT;
|
||||||
|
}
|
||||||
|
else if (what == ObjProperty::LEFTRIGHT_CLEAR)
|
||||||
|
visitedTile = CLEAR;
|
||||||
|
}
|
||||||
|
std::vector<int3> CGMagicSpring::getVisitableOffsets() const
|
||||||
|
{
|
||||||
|
std::vector <int3> visitableTiles;
|
||||||
|
|
||||||
|
for(int y = 0; y < 6; y++)
|
||||||
|
for (int x = 0; x < 8; x++) //starting from left
|
||||||
|
if((defInfo->visitMap[5-y] >> x) & 1)
|
||||||
|
visitableTiles.push_back (int3(x, y , 0));
|
||||||
|
|
||||||
|
return visitableTiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int3 CGMagicSpring::getVisitableOffset() const
|
||||||
|
{
|
||||||
|
//FIXME: this also shoudl stop AI from passing through already visited spring, is that ok?
|
||||||
|
auto visitableTiles = getVisitableOffsets();
|
||||||
|
|
||||||
|
if (visitableTiles.size() < 2)
|
||||||
|
{
|
||||||
|
logGlobal->warnStream() << "Warning: Magic Spring should have at least two visitable offsets!";
|
||||||
|
return int3(-1,-1,-1);
|
||||||
|
}
|
||||||
|
if (visited)
|
||||||
|
return int3(-1,-1,-1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (visitedTile == RIGHT)
|
||||||
|
return visitableTiles[0]; //visit teh other one now
|
||||||
|
else if (visitedTile == LEFT)
|
||||||
|
return visitableTiles[1];
|
||||||
|
else
|
||||||
|
return visitableTiles[0]; //only left one?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGMagicSpring::onHeroVisit(const CGHeroInstance * h) const
|
void CGMagicSpring::onHeroVisit(const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
int messageID;
|
int messageID;
|
||||||
@ -5344,17 +5399,39 @@ void CGMagicSpring::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
messageID = 74;
|
messageID = 74;
|
||||||
cb->setManaPoints (h->id, 2 * h->manaLimit());
|
cb->setManaPoints (h->id, 2 * h->manaLimit());//TODO: mark left or right tile visited
|
||||||
|
if (visitedTile) //visitng the second tile
|
||||||
cb->setObjProperty (id, ObjProperty::VISITED, true);
|
cb->setObjProperty (id, ObjProperty::VISITED, true);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto visitableTiles = getVisitableOffsets();
|
||||||
|
assert (visitableTiles.size() >= 2);
|
||||||
|
if (h->getPosition() == pos - visitableTiles[0])
|
||||||
|
cb->setObjProperty (id, ObjProperty::LEFT_VISITED, true);
|
||||||
|
else if (h->getPosition() == pos - visitableTiles[1])
|
||||||
|
cb->setObjProperty (id, ObjProperty::RIGHT_VISITED, true);
|
||||||
|
else
|
||||||
|
logGlobal->warnStream() << "Warning: hero is not on any Magic Spring visitable offsets!";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
messageID = 75;
|
messageID = 75;
|
||||||
showInfoDialog(h,messageID,soundBase::GENIE);
|
showInfoDialog(h,messageID,soundBase::GENIE);
|
||||||
}
|
}
|
||||||
|
void CGMagicSpring::newTurn() const
|
||||||
|
{
|
||||||
|
CGVisitableOPW::newTurn();
|
||||||
|
if (cb->getDate(Date::DAY_OF_WEEK) == 1)
|
||||||
|
{
|
||||||
|
cb->setObjProperty(id, ObjProperty::LEFTRIGHT_CLEAR, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string & CGMagicSpring::getHoverText() const
|
const std::string & CGMagicSpring::getHoverText() const
|
||||||
{
|
{
|
||||||
|
//TODO: change hover text depending on hovered tile
|
||||||
hoverName = VLC->generaltexth->names[ID] + " " + visitedTxt(visited);
|
hoverName = VLC->generaltexth->names[ID] + " " + visitedTxt(visited);
|
||||||
return hoverName;
|
return hoverName;
|
||||||
}
|
}
|
||||||
|
@ -193,8 +193,8 @@ public:
|
|||||||
void setOwner(PlayerColor ow);
|
void setOwner(PlayerColor ow);
|
||||||
int getWidth() const; //returns width of object graphic in tiles
|
int getWidth() const; //returns width of object graphic in tiles
|
||||||
int getHeight() const; //returns height of object graphic in tiles
|
int getHeight() const; //returns height of object graphic in tiles
|
||||||
bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
|
virtual bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
|
||||||
int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos)
|
virtual int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos)
|
||||||
int3 visitablePos() const;
|
int3 visitablePos() const;
|
||||||
bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles)
|
bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles)
|
||||||
bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles)
|
bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles)
|
||||||
@ -1036,7 +1036,7 @@ public:
|
|||||||
|
|
||||||
bool wasVisited(PlayerColor player) const;
|
bool wasVisited(PlayerColor player) const;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void newTurn() const override;
|
virtual void newTurn() const override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -1079,14 +1079,24 @@ public:
|
|||||||
|
|
||||||
class DLL_LINKAGE CGMagicSpring : public CGVisitableOPW
|
class DLL_LINKAGE CGMagicSpring : public CGVisitableOPW
|
||||||
{///unfortunately, this one is quite different than others
|
{///unfortunately, this one is quite different than others
|
||||||
|
enum EVisitedEntrance
|
||||||
|
{
|
||||||
|
CLEAR = 0, LEFT = 1, RIGHT
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
|
EVisitedEntrance visitedTile; //only one entrance was visited - there are two
|
||||||
|
|
||||||
|
std::vector<int3> getVisitableOffsets() const;
|
||||||
|
int3 getVisitableOffset() const override;
|
||||||
|
void setPropertyDer(ui8 what, ui32 val) override;
|
||||||
|
void newTurn() const override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
const std::string & getHoverText() const override;
|
const std::string & getHoverText() const override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CGObjectInstance&>(*this);
|
h & static_cast<CGObjectInstance&>(*this);
|
||||||
h & visited;
|
h & visitedTile & visited;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "mapping/CCampaignHandler.h" //for CCampaignState
|
#include "mapping/CCampaignHandler.h" //for CCampaignState
|
||||||
#include "rmg/CMapGenerator.h" // for CMapGenOptions
|
#include "rmg/CMapGenerator.h" // for CMapGenOptions
|
||||||
|
|
||||||
const ui32 version = 742;
|
const ui32 version = 743;
|
||||||
|
|
||||||
class CConnection;
|
class CConnection;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
|
@ -1190,7 +1190,10 @@ namespace ObjProperty
|
|||||||
|
|
||||||
//creature-bank specific
|
//creature-bank specific
|
||||||
BANK_DAYCOUNTER, BANK_CLEAR_ARTIFACTS, BANK_ADD_ARTIFACT, BANK_MULTIPLIER, BANK_CONFIG_PRESET,
|
BANK_DAYCOUNTER, BANK_CLEAR_ARTIFACTS, BANK_ADD_ARTIFACT, BANK_MULTIPLIER, BANK_CONFIG_PRESET,
|
||||||
BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET
|
BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET,
|
||||||
|
|
||||||
|
//magic spring
|
||||||
|
LEFT_VISITED, RIGHT_VISITED, LEFTRIGHT_CLEAR
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4236,6 +4236,27 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
|
|||||||
sendAndApply(&shr);
|
sendAndApply(&shr);
|
||||||
if (spellID == SpellID::SACRIFICE) //remove victim
|
if (spellID == SpellID::SACRIFICE) //remove victim
|
||||||
{
|
{
|
||||||
|
if (selectedStack == gs->curB->activeStack)
|
||||||
|
//set another active stack than the one removed, or bad things will happen
|
||||||
|
//TODO: make that part of BattleStacksRemoved? what about client update?
|
||||||
|
{
|
||||||
|
//makeStackDoNothing(gs->curB->getStack (selectedStack));
|
||||||
|
|
||||||
|
BattleSetActiveStack sas;
|
||||||
|
|
||||||
|
//std::vector<const CStack *> hlp;
|
||||||
|
//battleGetStackQueue(hlp, 1, selectedStack); //next after this one
|
||||||
|
|
||||||
|
//if(hlp.size())
|
||||||
|
//{
|
||||||
|
// sas.stack = hlp[0]->ID;
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
// complain ("No new stack to activate!");
|
||||||
|
sas.stack = gs->curB->getNextStack()->ID; //why the hell next stack has same ID as current?
|
||||||
|
sendAndApply(&sas);
|
||||||
|
|
||||||
|
}
|
||||||
BattleStacksRemoved bsr;
|
BattleStacksRemoved bsr;
|
||||||
bsr.stackIDs.insert (selectedStack); //somehow it works for teleport?
|
bsr.stackIDs.insert (selectedStack); //somehow it works for teleport?
|
||||||
sendAndApply(&bsr);
|
sendAndApply(&bsr);
|
||||||
@ -4491,7 +4512,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
ECastingMode::HERO_CASTING, nullptr, ba.selectedStack);
|
ECastingMode::HERO_CASTING, nullptr, ba.selectedStack);
|
||||||
|
|
||||||
sendAndApply(&end_action);
|
sendAndApply(&end_action);
|
||||||
if( !gs->curB->battleGetStackByID(gs->curB->activeStack, false)->alive() )
|
if( !gs->curB->battleGetStackByID(gs->curB->activeStack, true))
|
||||||
{
|
{
|
||||||
battleMadeAction.setn(true);
|
battleMadeAction.setn(true);
|
||||||
}
|
}
|
||||||
@ -6052,7 +6073,7 @@ void CGameHandler::runBattle()
|
|||||||
sendAndApply(&sas);
|
sendAndApply(&sas);
|
||||||
boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
|
boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
|
||||||
battleMadeAction.data = false;
|
battleMadeAction.data = false;
|
||||||
while (next->alive() &&
|
while (next->alive() && //next is invalid after sacrificing current stack :?
|
||||||
(!battleMadeAction.data && !battleResult.get())) //active stack hasn't made its action and battle is still going
|
(!battleMadeAction.data && !battleResult.get())) //active stack hasn't made its action and battle is still going
|
||||||
battleMadeAction.cond.wait(lock);
|
battleMadeAction.cond.wait(lock);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user