1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* new spell: remove obstacle

* minor changes
This commit is contained in:
mateuszb 2009-08-19 10:59:42 +00:00
parent af1a55e063
commit c4b0bd9d7e
13 changed files with 122 additions and 12 deletions

View File

@ -120,6 +120,7 @@ public:
virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
virtual void battleNewStackAppeared(int stackID){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles){}; //called when a certain set of obstacles is removed from batlefield; IDs of them are given
};
class CAIHandler
{

View File

@ -848,7 +848,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
//get dead stack if we cast resurrection or animate dead
const CStack * stackUnder = LOCPLINT->cb->battleGetStackByPos(myNumber, spellToCast->additionalInfo != 38 && spellToCast->additionalInfo != 39);
if(stackUnder && spellToCast->additionalInfo == 39 && !stackUnder->hasFeatureOfType(StackFeature::UNDEAD)) //animate dead can be cast only on living creatures
if(stackUnder && spellToCast->additionalInfo == 39 && !stackUnder->hasFeatureOfType(StackFeature::UNDEAD)) //animate dead can be cast only on undead creatures
stackUnder = NULL;
bool whichCase; //for cases 1, 2 and 3
@ -896,6 +896,14 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
}
break;
case 4: //TODO: implement this case
if( blockedByObstacle(myNumber) )
{
CGI->curh->changeGraphic(3, 0);
}
else
{
CGI->curh->changeGraphic(1, 0);
}
break;
}
}
@ -1520,6 +1528,19 @@ bool CBattleInterface::isTileAttackable(const int & number) const
return false;
}
bool CBattleInterface::blockedByObstacle(int hex) const
{
std::vector<CObstacleInstance> obstacles = LOCPLINT->cb->battleGetAllObstacles();
std::set<int> coveredHexes;
for(int b = 0; b < obstacles.size(); ++b)
{
std::vector<int> blocked = CGI->heroh->obstacles[obstacles[b].ID].getBlocked(obstacles[b].pos);
for(int w = 0; w < blocked.size(); ++w)
coveredHexes.insert(blocked[w]);
}
return vstd::contains(coveredHexes, hex);
}
void CBattleInterface::handleEndOfMove(int stackNumber, int destinationTile)
{
const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackNumber);
@ -1575,7 +1596,9 @@ void CBattleInterface::hexLclicked(int whichOne)
if(!LOCPLINT->cb->battleGetStackByPos(whichOne, onlyAlive))
allowCasting = false;
break;
case 4: //TODO: implement this case
case 4:
if(!blockedByObstacle(whichOne))
allowCasting = false;
break;
}
//destination checked
@ -1971,6 +1994,10 @@ void CBattleInterface::castThisSpell(int spellID)
spellSelMode = -1;
}
}
if(CGI->spellh->spells[spellID].attributes.find("OBSTACLE_TARGET") != std::string::npos) //spell to be cast on an obstacle
{
spellSelMode = 4;
}
if(spellSelMode == -1) //user does not have to select location
{
spellToCast->destinationTile = -1;

View File

@ -214,6 +214,7 @@ private:
void projectileShowHelper(SDL_Surface * to); //prints projectiles present on the battlefield
void giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional=-1);
bool isTileAttackable(const int & number) const; //returns true if tile 'number' is neighbouring any tile from active stack's range or is one of these tiles
bool blockedByObstacle(int hex) const;
void handleEndOfMove(int stackNumber, int destinationTile); //helper function
@ -237,7 +238,7 @@ public:
int getAnimSpeed() const; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
CBattleHex bfield[BFIELD_SIZE]; //11 lines, 17 hexes on each
std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
//std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
SDL_Surface * cellBorder, * cellShade;
CondSh<BattleAction *> *givenCommand; //data != NULL if we have i.e. moved current unit
bool myTurn; //if true, interface is active (commands can be ordered

View File

@ -981,6 +981,23 @@ void CPlayerInterface::battleNewStackAppeared(int stackID)
battleInt->newStack(stackID);
}
void CPlayerInterface::battleObstaclesRemoved(const std::set<si32> & removedObstacles)
{
for(std::set<si32>::const_iterator it = removedObstacles.begin(); it != removedObstacles.end(); ++it)
{
for(std::map< int, CDefHandler * >::iterator itBat = battleInt->idToObstacle.begin(); itBat != battleInt->idToObstacle.end(); ++itBat)
{
if(itBat->first == *it) //remove this obstacle
{
battleInt->idToObstacle.erase(itBat);
break;
}
}
}
//update accessible hexes
battleInt->redrawBackgroundWithHexes(battleInt->activeStack);
}
void CPlayerInterface::battleNewRound(int round) //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
{
boost::unique_lock<boost::recursive_mutex> un(*pim);

View File

@ -179,6 +179,7 @@ public:
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks); //called when stacks are healed / resurrected
void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
void battleObstaclesRemoved(const std::set<si32> & removedObstacles); //called when a certain set of obstacles is removed from batlefield; IDs of them are given
//-------------//
void heroKilled(const CGHeroInstance* hero);

View File

@ -2,7 +2,7 @@
#define __FONTBASE_H__
/*
* Graphics.h, part of VCMI engine
* FontBase.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*

View File

@ -462,6 +462,13 @@ void StacksHealedOrResurrected::applyCl( CClient *cl )
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleStacksHealedRes, shiftedHealed);
}
void ObstaclesRemoved::applyCl( CClient *cl )
{
//inform interfaces about removed obstacles
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, battleObstaclesRemoved, obstacles);
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, battleObstaclesRemoved, obstacles);
}
CGameState* CPackForClient::GS( CClient *cl )
{
return cl->gs;

View File

@ -4035,10 +4035,11 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
{
if (!hasVisited (h->getOwner()) )
if (!hasVisited (h->getOwner()) ) //if hero has not visited yet this cartographer
{
if (cb->getResource(h->tempOwner, 6) >= 1000)
if (cb->getResource(h->tempOwner, 6) >= 1000) //if he can afford a map
{
//ask if he wants to buy one
int text;
if (cb->getTile(pos)->tertype == 8) //water
text = 25;
@ -4055,7 +4056,7 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
bd.text.addTxt (MetaString::ADVOB_TXT, text);
cb->showBlockingDialog (&bd, boost::bind (&CCartographer::buyMap, this, h, _1));
}
else
else //if he cannot afford
{
InfoWindow iw;
iw.player = h->getOwner();
@ -4064,7 +4065,7 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
cb->showInfoDialog (&iw);
}
}
else
else //if he already visited carographer
{
InfoWindow iw;
iw.player = h->getOwner();
@ -4073,9 +4074,10 @@ void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
cb->showInfoDialog (&iw);
}
}
void CCartographer::buyMap (const CGHeroInstance *h, ui32 accept) const
{
if (accept)
if (accept) //if hero wants to buy map
{
cb->giveResource (h->tempOwner, 6, -1000);
FoWChange fw;
@ -4090,8 +4092,9 @@ void CCartographer::buyMap (const CGHeroInstance *h, ui32 accept) const
else
floor = 2;
//reveal apropriate tiles
cb->getAllTiles (fw.tiles, h->tempOwner, floor, surface);
cb->sendAndApply (&fw);
cb->setObjProperty (id, 10, h->tempOwner);
}
}
}

View File

@ -96,11 +96,12 @@ public:
struct DLL_EXPORT CObstacleInstance
{
int ID; //ID of obstacle
int uniqueID;
int ID; //ID of obstacle (defines type of it)
int pos; //position on battlefield
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ID & pos;
h & ID & pos & uniqueID;
}
};

View File

@ -977,6 +977,21 @@ struct StacksHealedOrResurrected : public CPackForClient //3013
}
};
struct ObstaclesRemoved : public CPackForClient //3014
{
ObstaclesRemoved(){type = 3014;}
DLL_EXPORT void applyGs(CGameState *gs);
void applyCl(CClient *cl);
std::set<si32> obstacles; //uniqueIDs of removed obstacles
template <typename Handler> void serialize(Handler &h, const int version)
{
h & obstacles;
}
};
struct ShowInInfobox : public CPackForClient //107
{
ShowInInfobox(){type = 107;};

View File

@ -1013,6 +1013,24 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
}
}
DLL_EXPORT void ObstaclesRemoved::applyGs( CGameState *gs )
{
if(gs->curB) //if there is a battle
{
for(std::set<si32>::const_iterator it = obstacles.begin(); it != obstacles.end(); ++it)
{
for(int i=0; i<gs->curB->obstacles.size(); ++i)
{
if(gs->curB->obstacles[i].uniqueID == *it) //remove this obstacle
{
gs->curB->obstacles.erase(gs->curB->obstacles.begin() + i);
break;
}
}
}
}
}
DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
{
gs->currentPlayer = player;

View File

@ -104,6 +104,7 @@ void registerTypes2(Serializer &s)
s.template registerType<StacksInjured>();
s.template registerType<BattleResultsApplied>();
s.template registerType<StacksHealedOrResurrected>();
s.template registerType<ObstaclesRemoved>();
s.template registerType<ShowInInfobox>();
s.template registerType<OpenWindow>();
s.template registerType<NewObject>();

View File

@ -1014,6 +1014,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
while(toBlock>0)
{
CObstacleInstance coi;
coi.uniqueID = curB->obstacles.size();
coi.ID = possibleObstacles[rand()%possibleObstacles.size()];
coi.pos = rand()%BFIELD_SIZE;
std::vector<int> block = VLC->heroh->obstacles[coi.ID].getBlocked(coi.pos);
@ -2869,6 +2870,23 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
sendAndApply(&shr);
break;
}
case 64: //remove obstacle
{
ObstaclesRemoved obr;
for(int g=0; g<gs->curB->obstacles.size(); ++g)
{
std::vector<int> blockedHexes = VLC->heroh->obstacles[gs->curB->obstacles[g].ID].getBlocked(gs->curB->obstacles[g].pos);
if(vstd::contains(blockedHexes, ba.destinationTile)) //this obstacle covers given hex
{
obr.obstacles.insert(gs->curB->obstacles[g].uniqueID);
}
}
if(!obr.obstacles.empty())
sendAndApply(&obr);
break;
}
}
sendAndApply(&EndAction());
return true;