1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

Implemented Scuttle Boat and Dimension Door spells.

Fixed #417 and #418.
Moved / refactored some code. Minor fixes.
This commit is contained in:
Michał W. Urbańczyk 2010-03-20 22:17:19 +00:00
parent 047849a23e
commit 80f49badc9
27 changed files with 775 additions and 666 deletions

View File

@ -7,6 +7,7 @@
#include "lib/map.h"
#include "hch/CBuildingHandler.h"
#include "hch/CDefObjInfoHandler.h"
#include "hch/CGeneralTextHandler.h"
#include "hch/CHeroHandler.h"
#include "hch/CObjectHandler.h"
#include "lib/Connection.h"
@ -33,21 +34,7 @@
*
*/
static int gcd(int x, int y)
{
int temp;
if (y > x)
std::swap(x,y);
while (y != 0)
{
temp = y;
y = x-y;
x = temp;
if (y > x)
std::swap(x,y);
}
return x;
}
HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho)
:src(Src),dst(Dst),ho(Ho)
{
@ -186,12 +173,18 @@ const CGTownInstance * CCallback::getTownInfo(int val, bool mode) const //mode =
bool CCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown &dest ) const
{
const CGTownInstance *t = dynamic_cast<const CGTownInstance *>(town);
if(!t || !isVisible(t, player)) //it's not a town or it's not visible for layer
if(!isVisible(town, player)) //it's not a town or it's not visible for layer
return false;
bool detailed = hasAccess(town->tempOwner);
//TODO vision support, info about allies
dest.initFromTown(t, false);
if(town->ID == TOWNI_TYPE)
dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed);
else if(town->ID == 33 || town->ID == 219)
dest.initFromGarrison(static_cast<const CGGarrison *>(town), detailed);
else
return false;
return true;
}
@ -245,7 +238,7 @@ bool CCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest )
return false;
//TODO vision support, info about allies
dest.initFromHero(h, false);
dest.initFromHero(h, hasAccess(h->tempOwner));
return true;
}
@ -963,6 +956,11 @@ void CCallback::castSpell(const CGHeroInstance *hero, int spellID, const int3 &p
sendRequest(&cas);
}
bool CCallback::hasAccess(int playerId) const
{
return playerId == player || player < 0;
}
InfoAboutTown::InfoAboutTown()
{
tType = NULL;
@ -1004,3 +1002,24 @@ void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed )
}
}*/
}
void InfoAboutTown::initFromGarrison(const CGGarrison *garr, bool detailed)
{
obj = garr;
fortLevel = 0;
army = garr->army;
name = CGI->generaltexth->names[33]; // "Garrison"
owner = garr->tempOwner;
built = false;
tType = NULL;
// Show detailed info only to owning player.
if(detailed)
{
details = new InfoAboutTown::Details;
details->customRes = false;
details->garrisonedHero = false;
details->goldIncome = -1;
details->hallLevel = -1;
}
}

View File

@ -42,6 +42,7 @@ struct CPackForServer;
class CMapHeader;
struct CGPathNode;
struct CGPath;
class CGGarrison;
struct InfoAboutTown
{
@ -65,6 +66,7 @@ struct InfoAboutTown
InfoAboutTown();
~InfoAboutTown();
void initFromTown(const CGTownInstance *t, bool detailed);
void initFromGarrison(const CGGarrison *garr, bool detailed);
};
class ICallback
@ -201,6 +203,7 @@ private:
template <typename T> void sendRequest(const T*request);
protected:
bool hasAccess(int playerId) const;
int player;
public:

View File

@ -152,10 +152,7 @@ void AdventureMapButton::clickLeft(tribool down, bool previousState)
void AdventureMapButton::clickRight(tribool down, bool previousState)
{
if(down && helpBox.size()) //there is no point to show window with nothing inside...
if(LOCPLINT)
adventureInt->handleRightClick(helpBox,down,this);
else
GH.pushInt(new CRClickPopupInt(CMessage::genWindow(helpBox, 0),true));
CRClickPopup::createAndPush(helpBox);
}
void AdventureMapButton::hover (bool on)

View File

@ -27,6 +27,7 @@
#include <sstream>
#include "CPreGame.h"
#include "../lib/VCMI_Lib.h"
#include "../hch/CSpellHandler.h"
#ifdef _MSC_VER
#pragma warning (disable : 4355)
@ -272,7 +273,7 @@ void CMinimap::updateRadar()
void CMinimap::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(rcText,down,this);
adventureInt->handleRightClick(rcText,down);
}
void CMinimap::clickLeft(tribool down, bool previousState)
@ -473,96 +474,12 @@ void CTerrainRect::clickLeft(tribool down, bool previousState)
{
if ((down==false) || indeterminate(down))
return;
int3 mp = whichTileIsIt();
if (mp.x<0 || mp.y<0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
return;
std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp), //blocking objects at tile
vobjs = LOCPLINT->cb->getVisitableObjs(mp); //visitable objects
if (adventureInt->selection->ID != HEROI_TYPE) //hero is not selected (presumably town)
{
if(currentPath)
{
tlog2<<"Warning: Lost path?" << std::endl;
//delete currentPath;
currentPath = NULL;
}
for(size_t i=0; i < bobjs.size(); ++i)
{
if(bobjs[i]->ID == TOWNI_TYPE && bobjs[i]->getOwner() == LOCPLINT->playerID) //our town clicked
{
if(adventureInt->selection == (bobjs[i])) //selected town clicked
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(bobjs[i]));
else
adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i]));
return;
}
else if(bobjs[i]->ID == HEROI_TYPE && bobjs[i]->tempOwner == LOCPLINT->playerID) //hero clicked - select him
{
adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i]));
return;
}
}
}
else //hero is selected
{
bool townEntrance = false; //town entrance tile has been clicked?
const CGHeroInstance * currentHero = static_cast<const CGHeroInstance*>(adventureInt->selection);
for(size_t i=0; i < vobjs.size(); ++i)
{
if(vobjs[i]->ID == TOWNI_TYPE)
townEntrance = true;
}
if(!townEntrance) //not entrance - select town or open hero window
{
for(size_t i=0; i < bobjs.size(); ++i)
{
const CGObjectInstance *o = bobjs[i];
const CGPathNode *pn = LOCPLINT->cb->getPathInfo(mp);
if( ((o->ID == HEROI_TYPE && pn->turns == 255) //inaccessible hero
|| o->ID == TOWNI_TYPE) //or town
&& o->tempOwner == LOCPLINT->playerID) //but must belong to us
{
adventureInt->select(static_cast<const CArmedInstance*>(o));
return;
}
else if(o->ID == HEROI_TYPE //it's a hero
&& o->tempOwner == LOCPLINT->playerID //our hero (is this condition needed?)
&& currentHero == (o) ) //and selected one
{
LOCPLINT->openHeroWindow(currentHero);
return;
}
}
}
else if(currentHero == vobjs.back()) //selected hero is standing at the town entrance
{
LOCPLINT->openHeroWindow(currentHero);
return;
}
//still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
if (currentPath && currentPath->endPos() == mp)//we'll be moving
{
LOCPLINT->pim->unlock();
LOCPLINT->moveHero(currentHero,*currentPath);
LOCPLINT->pim->lock();
}
else if(mp.z == currentHero->pos.z) //remove old path and find a new one if we clicked on the map level on which hero is present
{
int3 bufpos = currentHero->getPosition(false);
CGPath &path = LOCPLINT->paths[currentHero];
currentPath = &path;
if(!LOCPLINT->cb->getPath2(mp, path))
LOCPLINT->eraseCurrentPathOf(currentHero);
}
} //end of hero is selected "case"
adventureInt->tileLClicked(mp);
}
void CTerrainRect::clickRight(tribool down, bool previousState)
{
@ -571,118 +488,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState)
if (!CGI->mh->map->isInTheMap(mp) || down != true)
return;
std::vector < const CGObjectInstance * > objs = LOCPLINT->cb->getBlockingObjs(mp);
if(!objs.size())
{
// Bare or undiscovered terrain
const TerrainTile * tile = LOCPLINT->cb->getTileInfo(mp);
if (tile)
{
std::string hlp;
CGI->mh->getTerrainDescr(mp, hlp, true);
CSimpleWindow * temp = CMessage::genWindow(hlp, LOCPLINT->playerID, true);
CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
GH.pushInt(rcpi);
}
return;
}
const CGObjectInstance * obj = objs.back();
switch(obj->ID)
{
case HEROI_TYPE:
{
if(!vstd::contains(graphics->heroWins,obj->subID) || obj->tempOwner != LOCPLINT->playerID)
{
InfoAboutHero iah;
if(LOCPLINT->cb->getHeroInfo(obj, iah))
{
SDL_Surface *iwin = graphics->drawHeroInfoWin(iah);
CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x-iwin->w,
GH.current->motion.y-iwin->h, true);
GH.pushInt(ip);
}
else
{
tlog3 << "Warning - no infowin for hero " << obj->id << std::endl;
}
}
else
{
CInfoPopup * ip = new CInfoPopup(graphics->heroWins[obj->subID],
GH.current->motion.x-graphics->heroWins[obj->subID]->w,
GH.current->motion.y-graphics->heroWins[obj->subID]->h,false
);
GH.pushInt(ip);
}
break;
}
case TOWNI_TYPE:
{
if(!vstd::contains(graphics->townWins,obj->id) || obj->tempOwner != LOCPLINT->playerID)
{
InfoAboutTown iah;
if(LOCPLINT->cb->getTownInfo(obj, iah))
{
SDL_Surface *iwin = graphics->drawTownInfoWin(iah);
CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x - iwin->w/2,
GH.current->motion.y - iwin->h/2, true);
GH.pushInt(ip);
}
else
{
tlog3 << "Warning - no infowin for town " << obj->id << std::endl;
}
}
else
{
CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id],
GH.current->motion.x - graphics->townWins[obj->id]->w/2,
GH.current->motion.y - graphics->townWins[obj->id]->h/2,false
);
GH.pushInt(ip);
}
break;
}
case 33: // Garrison
case 219:
{
const CGGarrison *garr = dynamic_cast<const CGGarrison *>(obj);
if (garr != NULL) {
InfoAboutTown iah;
iah.obj = garr;
iah.fortLevel = 0;
iah.army = garr->army;
iah.name = VLC->generaltexth->names[33]; // "Garrison"
iah.owner = garr->tempOwner;
iah.built = false;
iah.tType = NULL;
// Show detailed info only to owning player.
if (garr->tempOwner == LOCPLINT->playerID) {
iah.details = new InfoAboutTown::Details;
iah.details->customRes = false;
iah.details->garrisonedHero = false;
iah.details->goldIncome = -1;
iah.details->hallLevel = -1;
}
SDL_Surface *iwin = graphics->drawTownInfoWin(iah);
CInfoPopup * ip = new CInfoPopup(iwin,
GH.current->motion.x - iwin->w/2,
GH.current->motion.y - iwin->h/2, true);
GH.pushInt(ip);
}
break;
}
default:
{
adventureInt->handleRightClick(obj->getHoverText(),down,this);
break;
}
}
adventureInt->tileRClicked(mp);
}
void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
{
@ -700,163 +506,7 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
else
return;
std::vector<std::string> temp = LOCPLINT->cb->getObjDescriptions(pom);
if (temp.size())
{
boost::replace_all(temp.back(),"\n"," ");
adventureInt->statusbar.print(temp.back());
}
else
{
std::string hlp;
CGI->mh->getTerrainDescr(pom, hlp, false);
adventureInt->statusbar.print(hlp);
//adventureInt->statusbar.clear();
}
const CGPathNode *pnode = LOCPLINT->cb->getPathInfo(pom);
std::vector<const CGObjectInstance *> objs = LOCPLINT->cb->getBlockingObjs(pom);
const CGObjectInstance *obj = objs.size() ? objs.back() : NULL;
bool accessible = pnode->turns < 255;
int turns = pnode->turns;
amin(turns, 3);
if(adventureInt->selection)
{
if(adventureInt->selection->ID == TOWNI_TYPE)
{
if(obj && obj->tempOwner == LOCPLINT->playerID)
{
if(obj->ID == TOWNI_TYPE)
{
CGI->curh->changeGraphic(0, 3);
}
else if(obj->ID == HEROI_TYPE)
{
CGI->curh->changeGraphic(0, 2);
}
}
else
{
CGI->curh->changeGraphic(0, 0);
}
}
else if(adventureInt->selection->ID == HEROI_TYPE)
{
const CGHeroInstance *h = static_cast<const CGHeroInstance *>(adventureInt->selection);
if(obj)
{
if(obj->ID == HEROI_TYPE)
{
if(obj->tempOwner != LOCPLINT->playerID) //enemy hero TODO: allies
{
if(accessible)
CGI->curh->changeGraphic(0, 5 + turns*6);
else
CGI->curh->changeGraphic(0, 0);
}
else //our hero
{
if(adventureInt->selection == obj)
CGI->curh->changeGraphic(0, 2);
else if(accessible)
CGI->curh->changeGraphic(0, 8 + turns*6);
else
CGI->curh->changeGraphic(0, 2);
}
}
else if(obj->ID == TOWNI_TYPE)
{
if(obj->tempOwner != LOCPLINT->playerID) //enemy town TODO: allies
{
if(accessible) {
const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(obj);
// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
if (townObj && townObj->army.slots.empty())
CGI->curh->changeGraphic(0, 9 + turns*6);
else
CGI->curh->changeGraphic(0, 5 + turns*6);
} else {
CGI->curh->changeGraphic(0, 0);
}
}
else //our town
{
if(accessible)
CGI->curh->changeGraphic(0, 9 + turns*6);
else
CGI->curh->changeGraphic(0, 3);
}
}
else if(obj->ID == 54) //monster
{
if(accessible)
CGI->curh->changeGraphic(0, 5 + turns*6);
else
CGI->curh->changeGraphic(0, 0);
}
else if(obj->ID == 8) //boat
{
if(accessible)
CGI->curh->changeGraphic(0, 6 + turns*6);
else
CGI->curh->changeGraphic(0, 0);
}
else if (obj->ID == 33 || obj->ID == 219) // Garrison
{
if (accessible) {
const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(obj);
// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
if (garrObj && garrObj->tempOwner != LOCPLINT->playerID
&& !garrObj->army.slots.empty())
{
CGI->curh->changeGraphic(0, 5 + turns*6);
}
else
{
CGI->curh->changeGraphic(0, 9 + turns*6);
}
} else {
CGI->curh->changeGraphic(0, 0);
}
}
else
{
if(accessible)
{
if(pnode->land)
CGI->curh->changeGraphic(0, 9 + turns*6);
else
CGI->curh->changeGraphic(0, 28 + turns);
}
else
CGI->curh->changeGraphic(0, 0);
}
}
else //no objs
{
if(accessible)
{
if(pnode->land)
{
if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water)
CGI->curh->changeGraphic(0, 4 + turns*6);
else
CGI->curh->changeGraphic(0, 7 + turns*6); //anchor
}
else
CGI->curh->changeGraphic(0, 6 + turns*6);
}
else
CGI->curh->changeGraphic(0, 0);
}
}
}
//tlog1 << "Tile " << pom << ": Turns=" << (int)pnode->turns <<" Move:=" << pnode->moveRemains <</* " (from " << ")" << */std::endl;
adventureInt->tileHovered(curHoveredTile);
}
void CTerrainRect::hover(bool on)
{
@ -1321,6 +971,7 @@ CInfoBar::CInfoBar()
week2 = CDefHandler::giveDef("NEWWEEK2.DEF");
week3 = CDefHandler::giveDef("NEWWEEK3.DEF");
week4 = CDefHandler::giveDef("NEWWEEK4.DEF");
selInfoWin = NULL;
}
CInfoBar::~CInfoBar()
{
@ -1329,8 +980,12 @@ CInfoBar::~CInfoBar()
delete week2;
delete week3;
delete week4;
if(selInfoWin)
SDL_FreeSurface(selInfoWin);
}
void CInfoBar::draw(SDL_Surface * to, const CGObjectInstance * specific)
void CInfoBar::showAll(SDL_Surface * to)
{
if ((mode>=0) && mode<5)
{
@ -1340,24 +995,11 @@ void CInfoBar::draw(SDL_Surface * to, const CGObjectInstance * specific)
else if (mode==5)
{
mode = -1;
draw(to,adventureInt->selection);
}
if (!specific)
specific = adventureInt->selection;
if(!specific)
return;
if(specific->ID == HEROI_TYPE) //hero
if(selInfoWin)
{
if(graphics->heroWins.find(specific->subID)!=graphics->heroWins.end())
blitAt(graphics->heroWins[specific->subID],pos.x,pos.y,to);
}
else if (specific->ID == TOWNI_TYPE)
{
const CGTownInstance * t = static_cast<const CGTownInstance*>(specific);
if(graphics->townWins.find(t->id)!=graphics->townWins.end())
blitAt(graphics->townWins[t->id],pos.x,pos.y,to);
blitAt(selInfoWin, pos.x, pos.y, to);
}
}
@ -1450,7 +1092,7 @@ void CInfoBar::showComp(SComponent * comp, int time)
void CInfoBar::tick()
{
if((mode >= 0) && (mode < 5))
if(mode >= 0 && mode < 5)
{
pom++;
if (pom >= getAnim(mode)->ourImages.size())
@ -1458,20 +1100,19 @@ void CInfoBar::tick()
deactivateTimer();
toNextTick = -1;
mode = 5;
draw(screen2);
showAll(screen2);
return;
}
toNextTick = 150;
blitAnim(mode);
}
else if (mode == 6)
else if(mode == 6)
{
deactivateTimer();
toNextTick = -1;
mode = 5;
draw(screen2);
showAll(screen2);
}
}
void CInfoBar::show( SDL_Surface * to )
@ -1491,6 +1132,13 @@ void CInfoBar::deactivate()
deactivateTimer();
}
void CInfoBar::updateSelection(const CGObjectInstance *obj)
{
if(selInfoWin)
SDL_FreeSurface(selInfoWin);
selInfoWin = LOCPLINT->infoWin(obj);
}
CAdvMapInt::CAdvMapInt()
:statusbar(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG),
kingOverview(CGI->generaltexth->zelp[293].first,CGI->generaltexth->zelp[293].second,
@ -1526,6 +1174,7 @@ endTurn(CGI->generaltexth->zelp[302].first,CGI->generaltexth->zelp[302].second,
heroList(ADVOPT.hlistSize),
townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlistAD)//(5,&genRect(192,48,747,196),747,196,747,372),
{
spellBeingCasted = NULL;
player = 0;
pos.x = pos.y = 0;
pos.w = screen->w;
@ -1593,24 +1242,21 @@ void CAdvMapInt::fsleepWake()
{
}
void CAdvMapInt::fmoveHero()
{
if (selection->ID!=HEROI_TYPE)
return;
if (!terrain.currentPath)
{
const CGHeroInstance *h = curHero();
if (!h || !terrain.currentPath)
return;
LOCPLINT->pim->unlock();
LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(adventureInt->selection),*terrain.currentPath);
LOCPLINT->pim->lock();
LOCPLINT->moveHero(h, *terrain.currentPath);
}
void CAdvMapInt::fshowSpellbok()
{
if (selection->ID!=HEROI_TYPE) //checking necessary values
if (!curHero()) //checking necessary values
return;
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), (static_cast<const CGHeroInstance*>(adventureInt->selection)), LOCPLINT, false);
centerOn(selection);
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), curHero(), LOCPLINT, false);
GH.pushInt(spellWindow);
}
@ -1736,7 +1382,7 @@ void CAdvMapInt::showAll(SDL_Surface *to)
statusbar.show(to);
infoBar.draw(to);
infoBar.showAll(to);
LOCPLINT->cingconsole->show(to);
}
void CAdvMapInt::show(SDL_Surface *to)
@ -1802,10 +1448,6 @@ void CAdvMapInt::selectionChanged()
}
void CAdvMapInt::centerOn(int3 on)
{
// TODO:convertPosition should not belong to CGHeroInstance, and it
// should be split in 2 methods.
on = CGHeroInstance::convertPosition(on, false);
on.x -= CGI->mh->frameW;
on.y -= CGI->mh->frameH;
@ -1818,10 +1460,20 @@ void CAdvMapInt::centerOn(int3 on)
if(GH.topInt() == this)
underground.redraw();
}
void CAdvMapInt::centerOn(const CGObjectInstance *obj)
{
centerOn(obj->getSightCenter());
}
void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
{
ui8 Dir = 0;
int k = key.keysym.sym;
const CGHeroInstance *h = curHero(); //selected hero
const CGTownInstance *t = curTown(); //selected town
switch(k)
{
case SDLK_i:
@ -1834,7 +1486,6 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
return;
case SDLK_d:
{
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(selection);
if(h && isActive() && key.state == SDL_PRESSED)
LOCPLINT->tryDiggging(h);
return;
@ -1847,7 +1498,6 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
{
if(!isActive())
return;
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(selection);
if(h && key.state == SDL_PRESSED)
{
LOCPLINT->pim->unlock();
@ -1860,10 +1510,10 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
{
if(!isActive() || !selection || key.state != SDL_PRESSED)
return;
if(selection->ID == HEROI_TYPE)
LOCPLINT->openHeroWindow(static_cast<const CGHeroInstance*>(selection));
else if(selection->ID == TOWNI_TYPE)
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(selection));
if(h)
LOCPLINT->openHeroWindow(h);
else if(t)
LOCPLINT->openTownWindow(t);
return;
}
case SDLK_t:
@ -1919,12 +1569,12 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
if(k < 0 || k > 8 || key.state != SDL_PRESSED)
return;
if(!h)
break;
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(selection);
if(!h) break;
if(k == 4)
{
centerOn(h->getPosition(false));
centerOn(h);
return;
}
@ -1940,9 +1590,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
if(!path.nodes[0].turns)
{
LOCPLINT->pim->unlock();
LOCPLINT->moveHero(h, path);
LOCPLINT->pim->lock();
}
}
@ -1955,13 +1603,11 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
else
scrollingDir &= ~Dir;
}
void CAdvMapInt::handleRightClick(std::string text, tribool down, CIntObject * client)
void CAdvMapInt::handleRightClick(std::string text, tribool down)
{
if (down)
if(down)
{
CSimpleWindow * temp = CMessage::genWindow(text,LOCPLINT->playerID,true);
CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
GH.pushInt(rcpi);
CRClickPopup::createAndPush(text);
}
}
int3 CAdvMapInt::verifyPos(int3 ver)
@ -1981,12 +1627,12 @@ int3 CAdvMapInt::verifyPos(int3 ver)
return ver;
}
void CAdvMapInt::select(const CArmedInstance *sel )
void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
{
LOCPLINT->cb->setSelection(sel);
centerOn(sel->pos);
selection = sel;
if(centerView)
centerOn(sel);
terrain.currentPath = NULL;
if(sel->ID==TOWNI_TYPE)
@ -2009,7 +1655,8 @@ void CAdvMapInt::select(const CArmedInstance *sel )
}
townList.draw(screen);
heroList.draw(screen);
infoBar.draw(screen);
infoBar.updateSelection(sel);
infoBar.showAll(screen);
}
void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
@ -2090,10 +1737,317 @@ void CAdvMapInt::startTurn()
state = INGAME;
}
void CAdvMapInt::tileLClicked(const int3 &mp)
{
std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp), //blocking objects at tile
vobjs = LOCPLINT->cb->getVisitableObjs(mp); //visitable objects
const TerrainTile *tile = LOCPLINT->cb->getTileInfo(mp);
const CGObjectInstance *topBlocking = bobjs.size() ? bobjs.back() : NULL;
int3 selPos = selection->getSightCenter();
if(spellBeingCasted && isInScreenRange(selPos, mp))
{
const TerrainTile *heroTile = LOCPLINT->cb->getTileInfo(selPos);
switch(spellBeingCasted->id)
{
case Spells::SCUTTLE_BOAT: //Scuttle Boat
if(topBlocking && topBlocking->ID == 8)
leaveCastingMode(true, mp);
break;
case Spells::DIMENSION_DOOR:
if(!tile || tile->isClear(heroTile))
leaveCastingMode(true, mp);
break;
}
return;
}
if (selection->ID != HEROI_TYPE) //hero is not selected (presumably town)
{
assert(!terrain.currentPath); //path can be active only when hero is selected
if(selection == topBlocking) //selected town clicked
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(topBlocking));
else if(topBlocking && (topBlocking->ID == TOWNI_TYPE || topBlocking->ID == HEROI_TYPE) && topBlocking->tempOwner == LOCPLINT->playerID) //our town/hero clicked
select(static_cast<const CArmedInstance*>(topBlocking), false);
}
else if(const CGHeroInstance * currentHero = curHero()) //hero is selected
{
const CGPathNode *pn = LOCPLINT->cb->getPathInfo(mp);
if(currentHero == topBlocking) //clicked selected hero
{
LOCPLINT->openHeroWindow(currentHero);
}
else if(topBlocking && (topBlocking->ID == HEROI_TYPE || topBlocking->ID == TOWNI_TYPE) //clicked our town or hero
&& pn->turns == 255 && topBlocking->tempOwner == LOCPLINT->playerID) //at inaccessible tile
{
select(static_cast<const CArmedInstance*>(topBlocking), false);
}
else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
{
if (terrain.currentPath && terrain.currentPath->endPos() == mp)//we'll be moving
{
LOCPLINT->moveHero(currentHero,*terrain.currentPath);
}
else if(mp.z == currentHero->pos.z) //remove old path and find a new one if we clicked on the map level on which hero is present
{
CGPath &path = LOCPLINT->paths[currentHero];
terrain.currentPath = &path;
if(!LOCPLINT->cb->getPath2(mp, path)) //try getting path, erase if failed
LOCPLINT->eraseCurrentPathOf(currentHero);
}
}
} //end of hero is selected "case"
else
{
throw std::string("Nothing is selected...");
}
}
void CAdvMapInt::tileHovered(const int3 &tile)
{
std::vector<std::string> temp = LOCPLINT->cb->getObjDescriptions(tile);
if (temp.size())
{
boost::replace_all(temp.back(),"\n"," ");
statusbar.print(temp.back());
}
else
{
std::string hlp;
CGI->mh->getTerrainDescr(tile, hlp, false);
statusbar.print(hlp);
}
const CGPathNode *pnode = LOCPLINT->cb->getPathInfo(tile);
std::vector<const CGObjectInstance *> objs = LOCPLINT->cb->getBlockingObjs(tile);
const CGObjectInstance *objAtTile = objs.size() ? objs.back() : NULL;
bool accessible = pnode->turns < 255;
int turns = pnode->turns;
amin(turns, 3);
if(!selection) //may occur just at the start of game (fake move before full intiialization)
return;
if(spellBeingCasted)
{
switch(spellBeingCasted->id)
{
case Spells::SCUTTLE_BOAT:
if(objAtTile && objAtTile->ID == 8)
CGI->curh->changeGraphic(0, 42);
else
CGI->curh->changeGraphic(0, 0);
return;
case Spells::DIMENSION_DOOR:
{
const TerrainTile *t = LOCPLINT->cb->getTileInfo(tile);
int3 hpos = selection->getSightCenter();
if((!t || t->isClear(LOCPLINT->cb->getTileInfo(hpos))) && isInScreenRange(hpos, tile))
CGI->curh->changeGraphic(0, 41);
else
CGI->curh->changeGraphic(0, 0);
return;
}
}
}
if(selection->ID == TOWNI_TYPE)
{
if(objAtTile && objAtTile->tempOwner == LOCPLINT->playerID)
{
if(objAtTile->ID == TOWNI_TYPE)
CGI->curh->changeGraphic(0, 3);
else if(objAtTile->ID == HEROI_TYPE)
CGI->curh->changeGraphic(0, 2);
}
else
CGI->curh->changeGraphic(0, 0);
}
else if(const CGHeroInstance *h = curHero())
{
if(objAtTile)
{
if(objAtTile->ID == HEROI_TYPE)
{
if(objAtTile->tempOwner != LOCPLINT->playerID) //enemy hero TODO: allies
{
if(accessible)
CGI->curh->changeGraphic(0, 5 + turns*6);
else
CGI->curh->changeGraphic(0, 0);
}
else //our hero
{
if(selection == objAtTile)
CGI->curh->changeGraphic(0, 2);
else if(accessible)
CGI->curh->changeGraphic(0, 8 + turns*6);
else
CGI->curh->changeGraphic(0, 2);
}
}
else if(objAtTile->ID == TOWNI_TYPE)
{
if(objAtTile->tempOwner != LOCPLINT->playerID) //enemy town TODO: allies
{
if(accessible)
{
const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(objAtTile);
// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
if (townObj && townObj->army.slots.empty())
CGI->curh->changeGraphic(0, 9 + turns*6);
else
CGI->curh->changeGraphic(0, 5 + turns*6);
}
else
{
CGI->curh->changeGraphic(0, 0);
}
}
else //our town
{
if(accessible)
CGI->curh->changeGraphic(0, 9 + turns*6);
else
CGI->curh->changeGraphic(0, 3);
}
}
else if(objAtTile->ID == 54) //monster
{
if(accessible)
CGI->curh->changeGraphic(0, 5 + turns*6);
else
CGI->curh->changeGraphic(0, 0);
}
else if(objAtTile->ID == 8) //boat
{
if(accessible)
CGI->curh->changeGraphic(0, 6 + turns*6);
else
CGI->curh->changeGraphic(0, 0);
}
else if (objAtTile->ID == 33 || objAtTile->ID == 219) // Garrison
{
if (accessible)
{
const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(objAtTile); //TODO evil evil cast!
// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
if (garrObj && garrObj->tempOwner != LOCPLINT->playerID && !garrObj->army.slots.empty())
CGI->curh->changeGraphic(0, 5 + turns*6);
else
CGI->curh->changeGraphic(0, 9 + turns*6);
}
else
CGI->curh->changeGraphic(0, 0);
}
else
{
if(accessible)
{
if(pnode->land)
CGI->curh->changeGraphic(0, 9 + turns*6);
else
CGI->curh->changeGraphic(0, 28 + turns);
}
else
CGI->curh->changeGraphic(0, 0);
}
}
else //no objs
{
if(accessible)
{
if(pnode->land)
{
if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water)
CGI->curh->changeGraphic(0, 4 + turns*6);
else
CGI->curh->changeGraphic(0, 7 + turns*6); //anchor
}
else
CGI->curh->changeGraphic(0, 6 + turns*6);
}
else
CGI->curh->changeGraphic(0, 0);
}
}
}
void CAdvMapInt::tileRClicked(const int3 &mp)
{
if(spellBeingCasted)
{
leaveCastingMode();
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[731]); //Spell cancelled
return;
}
std::vector < const CGObjectInstance * > objs = LOCPLINT->cb->getBlockingObjs(mp);
if(!objs.size())
{
// Bare or undiscovered terrain
const TerrainTile * tile = LOCPLINT->cb->getTileInfo(mp);
if (tile)
{
std::string hlp;
CGI->mh->getTerrainDescr(mp, hlp, true);
CRClickPopup::createAndPush(hlp);
}
return;
}
const CGObjectInstance * obj = objs.back();
CRClickPopup::createAndPush(obj, GH.current->motion, CENTER);
}
void CAdvMapInt::enterCastingMode(const CSpell * sp)
{
using namespace Spells;
assert(sp->id == SCUTTLE_BOAT || sp->id == DIMENSION_DOOR);
spellBeingCasted = sp;
deactivate();
terrain.activate();
GH.fakeMouseMove();
}
void CAdvMapInt::leaveCastingMode(bool cast /*= false*/, int3 dest /*= int3(-1, -1, -1)*/)
{
assert(spellBeingCasted);
int id = spellBeingCasted->id;
spellBeingCasted = NULL;
terrain.deactivate();
activate();
LOCPLINT->cb->castSpell(curHero(), id, dest);
}
const CGHeroInstance * CAdvMapInt::curHero() const
{
if(selection && selection->ID == HEROI_TYPE)
return static_cast<const CGHeroInstance *>(selection);
else
return NULL;
}
const CGTownInstance * CAdvMapInt::curTown() const
{
if(selection && selection->ID == TOWNI_TYPE)
return static_cast<const CGTownInstance *>(selection);
else
return NULL;
}
CAdventureOptions::CAdventureOptions()
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
bg = new CPicture(BitmapHandler::loadBitmap("ADVOPTS.bmp"), 0, 0);
bg = new CPicture("ADVOPTS.bmp");
graphics->blueToPlayersAdv(bg->bg, LOCPLINT->playerID);
pos = bg->center();
exit = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
@ -2106,13 +2060,11 @@ CAdventureOptions::CAdventureOptions()
puzzle = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 81, "ADVPUZ.DEF");
puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT);
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
dig = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 139, "ADVDIG.DEF");
if(h)
if(const CGHeroInstance *h = adventureInt->curHero())
dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h);
else
dig->block(true);
}
CAdventureOptions::~CAdventureOptions()

View File

@ -13,6 +13,7 @@ class CAdvMapInt;
class CGHeroInstance;
class CGTownInstance;
class CHeroWindow;
class CSpell;
/*****************************/
/*
@ -116,18 +117,20 @@ public:
SComponent * current;
int mode;
int pom;
SDL_Surface *selInfoWin; //info box for selection
CInfoBar();
~CInfoBar();
void newDay(int Day); //start showing new day/week animation
void showComp(SComponent * comp, int time=5000);
void tick();
void draw(SDL_Surface * to, const CGObjectInstance * specific=NULL); // if specific==0 function draws info about selected hero/town
void showAll(SDL_Surface * to); // if specific==0 function draws info about selected hero/town
void blitAnim(int mode);//0 - day, 1 - week
CDefHandler * getAnim(int mode);
void show(SDL_Surface * to);
void activate();
void deactivate();
void updateSelection(const CGObjectInstance *obj);
};
/*****************************/
class CAdvMapInt : public CIntObject //adventure map interface
@ -166,13 +169,13 @@ public:
endTurn;//- end turn
CTerrainRect terrain; //visible terrain
CResDataBar resdatabar;
CHeroList heroList;
CTownList townList;
CInfoBar infoBar;
const CSpell *spellBeingCasted; //NULL if none
CHeroWindow * heroWindow;
const CArmedInstance *selection; //currently selected town/hero
@ -195,11 +198,12 @@ public:
void show(SDL_Surface * to); //redraws terrain
void showAll(SDL_Surface * to); //shows and activates adv. map interface
void select(const CArmedInstance *sel);
void select(const CArmedInstance *sel, bool centerView = true);
void selectionChanged();
void centerOn(int3 on);
void centerOn(const CGObjectInstance *obj);
int3 verifyPos(int3 ver);
void handleRightClick(std::string text, tribool down, CIntObject * client);
void handleRightClick(std::string text, tribool down);
void keyPressed(const SDL_KeyboardEvent & key);
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
bool isActive();
@ -207,6 +211,13 @@ public:
void setPlayer(int Player);
void startHotSeatWait(int Player);
void startTurn();
void tileLClicked(const int3 &mp);
void tileHovered(const int3 &tile);
void tileRClicked(const int3 &mp);
void enterCastingMode(const CSpell * sp);
void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1));
const CGHeroInstance * curHero() const;
const CGTownInstance * curTown() const;
};
extern CAdvMapInt *adventureInt;

View File

@ -164,7 +164,12 @@ void CCursorHandler::shiftPos( int &x, int &y )
y -= 16;
}
}
else if(number < 31)
else if(number == 41)
{
x -= 14;
y -= 16;
}
else if(number < 31 || number == 42)
{
x -= 20;
y -= 20;

View File

@ -77,6 +77,7 @@ std::queue<SDL_Event*> events;
boost::mutex eventsM;
static bool gOnlyAI = false;
static bool setResolution = false; //set by event handling thread after resolution is adjusted
void processCommand(const std::string &message);
static void setScreenRes(int w, int h, int bpp, bool fullscreen);
@ -483,6 +484,7 @@ static void listenForEvents()
else if(ev->type == SDL_USEREVENT && ev->user.code == 1)
{
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
setResolution = true;
delete ev;
continue;
}
@ -540,5 +542,11 @@ void startGame(StartInfo * options)
}
CGI->musich->stopMusic();
//allow event handling thread change resolution
eventsM.unlock();
while(!setResolution) boost::this_thread::sleep(boost::posix_time::milliseconds(50));
eventsM.lock();
client->connectionHandler = new boost::thread(&CClient::run, client);
}

View File

@ -133,14 +133,6 @@ CPlayerInterface::~CPlayerInterface()
cingconsole->deactivate();
delete cingconsole;
for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!= graphics->heroWins.end(); i++)
SDL_FreeSurface(i->second);
graphics->heroWins.clear();
for(std::map<int,SDL_Surface*>::iterator i=graphics->townWins.begin(); i!= graphics->townWins.end(); i++)
SDL_FreeSurface(i->second);
graphics->townWins.clear();
LOCPLINT = NULL;
}
void CPlayerInterface::init(ICallback * CB)
@ -149,13 +141,6 @@ void CPlayerInterface::init(ICallback * CB)
if(!adventureInt)
adventureInt = new CAdvMapInt();
std::vector<const CGTownInstance*> tt = cb->getTownsInfo(false);
for(int i=0;i<tt.size();i++)
{
SDL_Surface * pom = infoWin(tt[i]);
graphics->townWins.insert(std::pair<int,SDL_Surface*>(tt[i]->id,pom));
}
if(!towns.size() && !wanderingHeroes.size())
{
recreateHeroTownList();
@ -248,7 +233,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
const CGHeroInstance * ho = cb->getHeroInfo(details.id); //object representing this hero
int3 hp = details.start;
adventureInt->centerOn(ho->pos); //actualizing screen pos
adventureInt->centerOn(ho); //actualizing screen pos
adventureInt->minimap.draw(screen2);
adventureInt->heroList.draw(screen2);
@ -336,15 +321,12 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
graphics->heroWins.erase(hero->ID);
wanderingHeroes -= hero;
adventureInt->heroList.updateHList(hero);
}
void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(graphics->heroWins.find(hero->subID)==graphics->heroWins.end())
graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hero->subID,infoWin(hero)));
wanderingHeroes.push_back(hero);
adventureInt->heroList.updateHList();
}
@ -356,38 +338,31 @@ void CPlayerInterface::openTownWindow(const CGTownInstance * town)
SDL_Surface * CPlayerInterface::infoWin(const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
{
if (specific)
if(!specific)
specific = adventureInt->selection;
assert(specific);
switch(specific->ID)
{
switch (specific->ID)
case HEROI_TYPE:
{
case HEROI_TYPE:
return graphics->drawHeroInfoWin(dynamic_cast<const CGHeroInstance*>(specific));
break;
case TOWNI_TYPE:
return graphics->drawTownInfoWin(dynamic_cast<const CGTownInstance*>(specific));
break;
default:
return NULL;
break;
InfoAboutHero iah;
bool gotInfo = LOCPLINT->cb->getHeroInfo(specific, iah);
assert(gotInfo);
return graphics->drawHeroInfoWin(iah);
}
}
else
{
switch (adventureInt->selection->ID)
case TOWNI_TYPE:
case 33: // Garrison
case 219:
{
case HEROI_TYPE:
{
const CGHeroInstance * curh = (const CGHeroInstance *)adventureInt->selection;
return graphics->drawHeroInfoWin(curh);
}
case TOWNI_TYPE:
{
return graphics->drawTownInfoWin((const CGTownInstance *)adventureInt->selection);
}
default:
tlog1 << "Strange... selection is neither hero nor town\n";
return NULL;
InfoAboutTown iah;
bool gotInfo = LOCPLINT->cb->getTownInfo(specific, iah);
assert(gotInfo);
return graphics->drawTownInfoWin(iah);
}
default:
return NULL;
}
}
@ -408,12 +383,12 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
if(which >= PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4)
return;
boost::unique_lock<boost::recursive_mutex> un(*pim);
redrawHeroWin(hero);
updateInfo(hero);
}
void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
redrawHeroWin(hero);
updateInfo(hero);
}
void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
{
@ -439,10 +414,7 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std:
void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
//redraw infowindow
SDL_FreeSurface(graphics->townWins[town->id]);
graphics->townWins[town->id] = infoWin(town);
updateInfo(town);
if(town->garrisonHero && vstd::contains(wanderingHeroes,town->garrisonHero)) //wandering hero moved to the garrison
{
@ -479,30 +451,7 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn
void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(obj->ID == HEROI_TYPE) //hero
{
const CGHeroInstance * hh;
if(hh = dynamic_cast<const CGHeroInstance*>(obj))
{
SDL_FreeSurface(graphics->heroWins[hh->subID]);
graphics->heroWins[hh->subID] = infoWin(hh);
}
}
else if (obj->ID == TOWNI_TYPE) //town
{
const CGTownInstance * tt;
if(tt = static_cast<const CGTownInstance*>(obj))
{
SDL_FreeSurface(graphics->townWins[tt->id]);
graphics->townWins[tt->id] = infoWin(tt);
}
if(tt->visitingHero)
{
SDL_FreeSurface(graphics->heroWins[tt->visitingHero->subID]);
graphics->heroWins[tt->visitingHero->subID] = infoWin(tt->visitingHero);
}
}
updateInfo(obj);
bool wasGarrison = false;
for(std::list<IShowActivable*>::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++)
@ -530,12 +479,10 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
switch (buildingID)
{
case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 15:
{
SDL_FreeSurface(graphics->townWins[town->id]);
graphics->townWins[town->id] = infoWin(town);
break;
}
updateInfo(town);
break;
}
if(!castleInt)
return;
if(castleInt->town!=town)
@ -983,7 +930,7 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroB
{
if(bonus.type == HeroBonus::NONE) return;
boost::unique_lock<boost::recursive_mutex> un(*pim);
redrawHeroWin(hero);
updateInfo(hero);
}
template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version )
@ -1004,72 +951,63 @@ void CPlayerInterface::serialize( CISer<CLoadFile> &h, const int version )
firstCall = -1;
}
void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
{
if(!vstd::contains(graphics->heroWins,hero->subID))
{
tlog1 << "Cannot redraw infowindow for hero with subID=" << hero->subID << " - not present in our map\n";
return;
}
SDL_FreeSurface(graphics->heroWins[hero->subID]);
graphics->heroWins[hero->subID] = infoWin(hero);
if (adventureInt->selection == hero)
adventureInt->infoBar.draw(screen);
}
bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
{
if (!h)
return false; //can't find hero
pim->unlock();
bool result = false;
path.convert(0);
boost::unique_lock<boost::mutex> un(stillMoveHero.mx);
stillMoveHero.data = CONTINUE_MOVE;
enum TerrainTile::EterrainType currentTerrain = TerrainTile::border; // not init yet
enum TerrainTile::EterrainType newTerrain;
int sh = -1;
for(int i=path.nodes.size()-1; i>0 && stillMoveHero.data == CONTINUE_MOVE; i--)
{
//stop sending move requests if the next node can't be reached at the current turn (hero exhausted his move points)
if(path.nodes[i-1].turns)
{
stillMoveHero.data = STOP_MOVE;
break;
}
// Start a new sound for the hero movement or let the existing one carry on.
#if 0
// TODO
if (hero is flying && sh == -1)
sh = CGI->soundh->playSound(soundBase::horseFlying, -1);
#endif
{
newTerrain = cb->getTileInfo(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype;
path.convert(0);
boost::unique_lock<boost::mutex> un(stillMoveHero.mx);
stillMoveHero.data = CONTINUE_MOVE;
if (newTerrain != currentTerrain) {
CGI->soundh->stopSound(sh);
sh = CGI->soundh->playSound(CGI->soundh->horseSounds[newTerrain], -1);
currentTerrain = newTerrain;
enum TerrainTile::EterrainType currentTerrain = TerrainTile::border; // not init yet
enum TerrainTile::EterrainType newTerrain;
int sh = -1;
for(int i=path.nodes.size()-1; i>0 && stillMoveHero.data == CONTINUE_MOVE; i--)
{
//stop sending move requests if the next node can't be reached at the current turn (hero exhausted his move points)
if(path.nodes[i-1].turns)
{
stillMoveHero.data = STOP_MOVE;
break;
}
// Start a new sound for the hero movement or let the existing one carry on.
#if 0
// TODO
if (hero is flying && sh == -1)
sh = CGI->soundh->playSound(soundBase::horseFlying, -1);
#endif
{
newTerrain = cb->getTileInfo(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype;
if (newTerrain != currentTerrain) {
CGI->soundh->stopSound(sh);
sh = CGI->soundh->playSound(CGI->soundh->horseSounds[newTerrain], -1);
currentTerrain = newTerrain;
}
}
stillMoveHero.data = WAITING_MOVE;
int3 endpos(path.nodes[i-1].coord.x, path.nodes[i-1].coord.y, h->pos.z);
cb->moveHero(h,endpos);
eventsM.unlock();
while(stillMoveHero.data != STOP_MOVE && stillMoveHero.data != CONTINUE_MOVE)
stillMoveHero.cond.wait(un);
eventsM.lock();
}
stillMoveHero.data = WAITING_MOVE;
int3 endpos(path.nodes[i-1].coord.x, path.nodes[i-1].coord.y, h->pos.z);
cb->moveHero(h,endpos);
eventsM.unlock();
while(stillMoveHero.data != STOP_MOVE && stillMoveHero.data != CONTINUE_MOVE)
stillMoveHero.cond.wait(un);
eventsM.lock();
CGI->soundh->stopSound(sh);
cb->recalculatePaths();
}
CGI->soundh->stopSound(sh);
//stillMoveHero = false;
cb->recalculatePaths();
pim->lock();
return result;
}
@ -1905,15 +1843,6 @@ void CPlayerInterface::acceptTurn()
adventureInt->startTurn();
boost::unique_lock<boost::recursive_mutex> un(*pim);
for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!=graphics->heroWins.end();i++) //redraw hero infoboxes
SDL_FreeSurface(i->second);
graphics->heroWins.clear();
std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false);
for(int i=0;i<hh.size();i++)
{
SDL_Surface * pom = infoWin(hh[i]);
graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hh[i]->subID,pom));
}
/* TODO: This isn't quite right. First day in game should play
* NEWDAY. And we don't play NEWMONTH. */
@ -1952,3 +1881,10 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
cb->dig(h);
}
}
void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
{
adventureInt->infoBar.updateSelection(specific);
// if (adventureInt->selection == specific)
// adventureInt->infoBar.showAll(screen);
}

View File

@ -207,6 +207,7 @@ public:
void openTownWindow(const CGTownInstance * town); //shows townscreen
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero
void updateInfo(const CGObjectInstance * specific);
void init(ICallback * CB);
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components = std::vector<SComponent*>(), int soundID = 0);

View File

@ -2467,9 +2467,7 @@ void CBonusSelection::CRegion::clickRight( tribool down, bool previousState )
if( down && !CSDL_Ext::isTransparent(graphics[0], GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) &&
rclickText.size() )
{
CSimpleWindow * temp = CMessage::genWindow(rclickText, 0, true);
CRClickPopupInt *rcpi = new CRClickPopupInt(temp, true);
GH.pushInt(rcpi);
CRClickPopup::createAndPush(rclickText);
}
}

View File

@ -51,7 +51,7 @@ void SpellbookInteractiveArea::clickLeft(tribool down, bool previousState)
void SpellbookInteractiveArea::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(textOnRclick, down, this);
adventureInt->handleRightClick(textOnRclick, down);
}
void SpellbookInteractiveArea::hover(bool on)
@ -688,13 +688,14 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
}
else
{
using namespace Spells;
int spell = mySpell;
const CGHeroInstance *h = owner->myHero;
owner->fexitb();
switch(spell)
{
case 0: //summon boat
case SUMMON_BOAT:
{
int3 pos = h->bestLocation();
if(pos.x < 0)
@ -703,6 +704,21 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
return;
}
}
break;
case SCUTTLE_BOAT:
case DIMENSION_DOOR:
adventureInt->enterCastingMode(sp);
return;
case VISIONS:
case VIEW_EARTH:
case DISGUISE:
case VIEW_AIR:
case FLY:
case WATER_WALK:
case TOWN_PORTAL:
break;
default:
assert(0);
}
LOCPLINT->cb->castSpell(h, spell);

View File

@ -313,7 +313,10 @@ int CClient::getCurrentPlayer()
int CClient::getSelectedHero()
{
return IGameCallback::getSelectedHero(getCurrentPlayer())->id;
if(const CGHeroInstance *selHero = IGameCallback::getSelectedHero(getCurrentPlayer()))
return selHero->id;
else
return -1;
}
void CClient::newGame( CConnection *con, StartInfo *si )

View File

@ -71,6 +71,9 @@ struct Point
Point(const int3 &a)
:x(a.x),y(a.y)
{}
Point(const SDL_MouseMotionEvent &a)
:x(a.x),y(a.y)
{}
template<typename T>
Point operator+(const T &b) const
@ -365,6 +368,8 @@ public:
ui8 defActions; //which calls will be tried to be redirected to children
ui8 recActions; //which calls we allow te receive from parent
enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT};
void disable(); //deactivates if needed, blocks all automatic activity, allows only disposal
void enable(bool activation = true); //activates if needed, all activity enabled (Warning: may not be symetric with disable if recActions was limited!)
void defActivate();

View File

@ -770,21 +770,55 @@ void CRClickPopup::close()
GH.popIntTotally(this);
}
void CRClickPopup::createAndPush(const std::string &txt)
{
int player = LOCPLINT ? LOCPLINT->playerID : 1; //if no player, then use blue
CSimpleWindow * temp = CMessage::genWindow(txt,player,true);
CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
GH.pushInt(rcpi);
}
void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment /*= BOTTOMRIGHT*/)
{
SDL_Surface *iWin = LOCPLINT->infoWin(obj); //try get custom infowindow for this obj
if(iWin)
GH.pushInt(new CInfoPopup(iWin, p, alignment, true));
else
CRClickPopup::createAndPush(obj->getHoverText());
}
CRClickPopup::CRClickPopup()
{
}
CRClickPopup::~CRClickPopup()
{
}
CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free)
:free(Free),bitmap(Bitmap)
{
CGI->curh->hide();
init(x, y);
}
pos.x = x;
pos.y = y;
pos.h = bitmap->h;
pos.w = bitmap->w;
// Put the window back on screen if necessary
amax(pos.x, 0);
amax(pos.y, 0);
amin(pos.x, conf.cc.resx - bitmap->w);
amin(pos.y, conf.cc.resy - bitmap->h);
CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free/*=false*/)
: free(Free),bitmap(Bitmap)
{
switch(alignment)
{
case BOTTOMRIGHT:
init(p.x - Bitmap->w, p.y - Bitmap->h);
break;
case CENTER:
init(p.x - Bitmap->w/2, p.y - Bitmap->h/2);
break;
case TOPLEFT:
init(p.x, p.y);
break;
default:
assert(0); //not implemented
}
}
CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free)
@ -818,6 +852,22 @@ CInfoPopup::~CInfoPopup()
CGI->curh->show();
}
void CInfoPopup::init(int x, int y)
{
CGI->curh->hide();
pos.x = x;
pos.y = y;
pos.h = bitmap->h;
pos.w = bitmap->w;
// Put the window back on screen if necessary
amax(pos.x, 0);
amax(pos.y, 0);
amin(pos.x, conf.cc.resx - bitmap->w);
amin(pos.y, conf.cc.resy - bitmap->h);
}
void SComponent::init(Etype Type, int Subtype, int Val)
{
std::ostringstream oss;
@ -961,7 +1011,7 @@ SDL_Surface * SComponent::getImg()
void SComponent::clickRight(tribool down, bool previousState)
{
if(description.size())
adventureInt->handleRightClick(description,down,this);
adventureInt->handleRightClick(description,down);
}
void SComponent::activate()
{
@ -1277,7 +1327,7 @@ void CHeroList::select(int which)
adventureInt->selection = NULL;
adventureInt->terrain.currentPath = NULL;
draw(screen);
adventureInt->infoBar.draw(screen);
adventureInt->infoBar.showAll(screen);
}
if (which>=LOCPLINT->wanderingHeroes.size())
return;
@ -1397,11 +1447,11 @@ void CHeroList::clickRight(tribool down, bool previousState)
/***************************ARROWS*****************************************/
if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y) && from>0)
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down,this);
adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down);
}
else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y) && (LOCPLINT->wanderingHeroes.size()-from>5))
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down,this);
adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down);
}
else
{
@ -1413,21 +1463,11 @@ void CHeroList::clickRight(tribool down, bool previousState)
if ((ny>SIZE || ny<0) || (from+ny>=LOCPLINT->wanderingHeroes.size()))
{
return;
}
} //show popup
//show popup
CInfoPopup * ip = new CInfoPopup(graphics->heroWins[LOCPLINT->wanderingHeroes[from+ny]->subID],
GH.current->motion.x-graphics->heroWins[LOCPLINT->wanderingHeroes[from+ny]->subID]->w,
GH.current->motion.y-graphics->heroWins[LOCPLINT->wanderingHeroes[from+ny]->subID]->h,
false);
GH.pushInt(ip);
CRClickPopup::createAndPush(LOCPLINT->wanderingHeroes[from+ny], GH.current->motion);
}
}
else
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down,this);
adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down,this);
}
}
void CHeroList::hover (bool on)
@ -1692,11 +1732,11 @@ void CTownList::clickRight(tribool down, bool previousState)
/***************************ARROWS*****************************************/
if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y) && from>0)
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down,this);
adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down);
}
else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y) && (LOCPLINT->towns.size()-from>5))
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down,this);
adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down);
}
//if not buttons then towns
int hx = GH.current->motion.x, hy = GH.current->motion.y;
@ -1709,17 +1749,7 @@ void CTownList::clickRight(tribool down, bool previousState)
}
//show popup
CInfoPopup * ip = new CInfoPopup(
graphics->townWins[LOCPLINT->towns[from+ny]->id],
GH.current->motion.x-graphics->townWins[LOCPLINT->towns[from+ny]->id]->w,
GH.current->motion.y-graphics->townWins[LOCPLINT->towns[from+ny]->id]->h,
false);
GH.pushInt(ip);
}
else
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down,this);
adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down,this);
CRClickPopup::createAndPush(LOCPLINT->towns[from+ny], GH.current->motion);
}
}
@ -3912,7 +3942,7 @@ void LRClickableAreaWText::clickLeft(tribool down, bool previousState)
}
void LRClickableAreaWText::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(text, down, this);
adventureInt->handleRightClick(text, down);
}
void LRClickableAreaWText::activate()
{
@ -3950,7 +3980,7 @@ void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState)
}
void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(text, down, this);
adventureInt->handleRightClick(text, down);
}
void LRClickableAreaWTextComp::activate()
{

View File

@ -63,6 +63,7 @@ class CArtifact;
class CArtifactsOfHero;
class CResDataBar;
struct SPuzzleInfo;
class CGGarrison;
extern SDL_Color tytulowy, tlo, zwykly ;
@ -103,7 +104,12 @@ public:
virtual void deactivate();
virtual void close();
void clickRight(tribool down, bool previousState);
virtual ~CRClickPopup(){}; //d-tor
CRClickPopup();
virtual ~CRClickPopup(); //d-tor
static void createAndPush(const std::string &txt);
static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
};
class CRClickPopupInt : public CRClickPopup //popup displayed on R-click
@ -125,7 +131,10 @@ public:
void close();
void show(SDL_Surface * to);
CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free=false); //c-tor
CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free=false); //c-tor
CInfoPopup(SDL_Surface *Bitmap = NULL, bool Free = false); //default c-tor
void init(int x, int y);
~CInfoPopup(); //d-tor
};
@ -265,7 +274,7 @@ class CLabel
: public virtual CIntObject
{
public:
enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT} alignment;
EAlignment alignment;
EFonts font;
SDL_Color color;
std::string text;

View File

@ -64,8 +64,6 @@ public:
CDefEssential *luck22, *luck30, *luck42, *luck82,
*morale22, *morale30, *morale42, *morale82,
*halls, *forts, *bigTownPic;
std::map<int,SDL_Surface*> heroWins; //hero_ID => infobox
std::map<int,SDL_Surface*> townWins; //town_ID => infobox
CDefEssential * artDefs; //artifacts
std::vector<SDL_Surface *> portraitSmall; //48x32 px portraits of heroes
std::vector<SDL_Surface *> portraitLarge; //58x64 px portraits of heroes

View File

@ -1013,11 +1013,13 @@ void CSDL_Ext::setPlayerColor(SDL_Surface * sur, unsigned char player)
return;
if(sur->format->BitsPerPixel==8)
{
if(player != 255)
*(sur->format->palette->colors+5) = graphics->playerColors[player];
else
*(sur->format->palette->colors+5) = *graphics->neutralColor;
SDL_Color *color = (player == 255
? graphics->neutralColor
: &graphics->playerColors[player]);
SDL_SetColors(sur, color, 5, 1);
}
else
tlog3 << "Warning, setPlayerColor called on not 8bpp surface!\n";
}
int readNormalNr (std::istream &in, int bytCon)
{

View File

@ -23,6 +23,7 @@
#include "../lib/map.h"
#include <sstream>
#include <SDL_stdinc.h>
#include <boost/foreach.hpp>
using namespace boost::assign;
/*
@ -1238,7 +1239,7 @@ int CGHeroInstance::getBoatType() const
case 2:
return 2;
default:
assert(0);
throw std::string("Wrong alignment!");
}
}
@ -1254,6 +1255,17 @@ int CGHeroInstance::getSpellCost(const CSpell *sp) const
return sp->costs[getSpellSchoolLevel(sp)];
}
int CGHeroInstance::getBonusesCount(int from, int id) const
{
int ret = 0;
BOOST_FOREACH(const HeroBonus &hb, bonuses)
if(hb.source == from && hb.id == id)
ret++;
return ret;
}
void CGDwelling::initObj()
{
switch(ID)

View File

@ -313,6 +313,7 @@ public:
const BonusList *ownerBonuses() const;
const HeroBonus *getBonus(int from, int id) const;
int getBonusesCount(int from, int id) const;
int valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any
bool hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const; //determines if hero has a bonus of given type (and optionally subtype)
void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1) const; //out: pairs<modifier value, modifier description>

View File

@ -194,6 +194,15 @@ static bool startsWithX(const std::string &s)
return s.size() && s[0] == 'x';
}
bool DLL_EXPORT isInScreenRange(const int3 &center, const int3 &pos)
{
int3 diff = pos - center;
if(diff.x >= -9 && diff.x <= 9 && diff.y >= -8 && diff.y <= 8)
return true;
else
return false;
}
void CSpellHandler::loadSpells()
{
std::string buf = bitmaph->getTextFile("SPTRAITS.TXT"), pom;

View File

@ -51,6 +51,13 @@ public:
}
};
namespace Spells
{
enum {SUMMON_BOAT=0, SCUTTLE_BOAT, VISIONS, VIEW_EARTH, DISGUISE, VIEW_AIR, FLY, WATER_WALK, DIMENSION_DOOR, TOWN_PORTAL};
}
bool DLL_EXPORT isInScreenRange(const int3 &center, const int3 &pos); //for spells like Dimension Door
class DLL_EXPORT CSpellHandler
{
public:

View File

@ -1988,12 +1988,16 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
return false;
int3 hpos = hero->getPosition(false);
tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all
if (!hero->canWalkOnSea())
blockLandSea = (map->getTile(hpos).tertype != TerrainTile::water); //block land if hero is on water and vice versa
else
blockLandSea = boost::logic::indeterminate;
bool flying = false; //hero is under flying effect TODO
bool waterWalking = false; //hero is on land and can walk on water TODO
bool onLand = map->getTile(hpos).tertype != TerrainTile::water;
// tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all
//
// if (!hero->canWalkOnSea())
// blockLandSea = (map->getTile(hpos).tertype != TerrainTile::water); //block land if hero is on water and vice versa
// else
// blockLandSea = boost::logic::indeterminate;
const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap;
@ -2016,9 +2020,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
node.coord.y = j;
node.coord.z = dest.z;
if ((tinfo->tertype == TerrainTile::rock) //it's rock
|| ((blockLandSea) && (tinfo->tertype == TerrainTile::water)) //it's sea and we cannot walk on sea
|| ((!blockLandSea) && (tinfo->tertype != TerrainTile::water)) //it's land and we cannot walk on land
if(!tinfo->entrableTerrain(onLand, flying || waterWalking)
|| !FoW[i][j][src.z] //tile is covered by the FoW
)
{
@ -2039,7 +2041,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
d.accessible = true; //for allowing visiting objects
}
if(blockLandSea && t->tertype == TerrainTile::water) //hero can walk only on land and dst lays on the water
if(onLand && t->tertype == TerrainTile::water) //hero can walk only on land and dst lays on the water
{
size_t i = 0;
for(; i < t->visitableObjects.size(); i++)
@ -2048,7 +2050,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
d.accessible = (i < t->visitableObjects.size()); //dest is accessible only if there is boat/hero
}
else if(!blockLandSea && t->tertype != TerrainTile::water) //hero is moving by water
else if(!onLand && t->tertype != TerrainTile::water) //hero is moving by water
{
d.accessible = (t->siodmyTajemniczyBajt & 64) && !t->blocked; //tile is accessible if it's coastal and not blocked
}

View File

@ -56,7 +56,7 @@ struct DLL_EXPORT HeroBonus
FREE_SHIP_BOARDING //movement points preserved with ship boarding and landing
};
enum BonusDuration{PERMANENT, ONE_BATTLE, ONE_DAY, ONE_WEEK};
enum BonusSource{ARTIFACT, OBJECT};
enum BonusSource{ARTIFACT, OBJECT, CASTED_SPELL};
ui8 duration; //uses BonusDuration values
ui8 type; //uses BonusType values - says to what is this bonus

View File

@ -476,7 +476,7 @@ struct TryMoveHero : public CPackForClient //501
ui32 id, movePoints;
ui8 result; //uses EResult
int3 start, end;
int3 start, end; //h3m format
std::set<int3> fowRevealed; //revealed tiles
bool humanKnows; //used locally during applying to client

View File

@ -2129,3 +2129,19 @@ CVictoryCondition::CVictoryCondition()
obj = NULL;
ID = allowNormalVictory = appliesToAI = count = 0;
}
bool TerrainTile::entrableTerrain(const TerrainTile *from /*= NULL*/) const
{
return entrableTerrain(from ? from->tertype != water : true, from ? from->tertype == water : true);
}
bool TerrainTile::entrableTerrain(bool allowLand, bool allowSea) const
{
return tertype != rock
&& (allowSea && tertype == water || allowLand && tertype != water);
}
bool TerrainTile::isClear(const TerrainTile *from /*= NULL*/) const
{
return entrableTerrain(from) && !blocked;
}

View File

@ -95,6 +95,10 @@ struct DLL_EXPORT TerrainTile
//these flags (and obj vectors) will be restored in map serialization
}
}
bool entrableTerrain(const TerrainTile *from = NULL) const; //checks if terrain is not a rock. If from is water/land, same type is also required.
bool entrableTerrain(bool allowLand, bool allowSea) const; //checks if terrain is not a rock. If from is water/land, same type is also required.
bool isClear(const TerrainTile *from = NULL) const; //checks for blocking objs and terraint type (water / land)
};
struct DLL_EXPORT SheroName //name of starting hero
{

View File

@ -4213,9 +4213,10 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
if(s->combatSpell)
COMPLAIN_RET("This function can be used only for adventure map spells!");
using namespace Spells;
switch(spellID)
{
case 0: //Summon Boat
case SUMMON_BOAT: //Summon Boat
{
//check if spell works at all
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
@ -4277,15 +4278,79 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p
break;
}
case 1: //Scuttle Boat
case 2: //Visions
case 3: //View Earth
case 4: //Disguise
case 5: //View Air
case 6: //Fly
case 7: //Water Walk
case 8: //Dimension Door
case 9: //Town Portal
case SCUTTLE_BOAT: //Scuttle Boat
{
//check if spell works at all
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
iw.text.addReplacement(h->name);
sendAndApply(&iw);
return true; //TODO? or should it be false? request was correct and realized, but spell failed...
}
//TODO: test range, visibility
const TerrainTile *t = &gs->map->getTile(pos);
if(!t->visitableObjects.size() || t->visitableObjects.back()->ID != 8)
COMPLAIN_RET("There is no boat to scuttle!");
RemoveObject ro;
ro.id = t->visitableObjects.back()->id;
sendAndApply(&ro);
break;
}
case DIMENSION_DOOR: //Dimension Door
{
const TerrainTile *dest = getTile(pos);
const TerrainTile *curr = getTile(h->getSightCenter());
if(!dest)
COMPLAIN_RET("Destination tile doesn't exist!");
if(!h->movement)
COMPLAIN_RET("Hero needs movement points to cast Dimension Door!");
if(h->getBonusesCount(HeroBonus::CASTED_SPELL, Spells::DIMENSION_DOOR) >= s->powers[schoolLevel]) //limit casts per turn
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today.
iw.text.addReplacement(h->name);
sendAndApply(&iw);
break;
}
GiveBonus gb;
gb.id = h->id;
gb.bonus = HeroBonus(HeroBonus::ONE_DAY, HeroBonus::NONE, HeroBonus::CASTED_SPELL, 0, Spells::DIMENSION_DOOR);
sendAndApply(&gb);
if(!dest->isClear(curr)) //wrong dest tile
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 70); //Dimension Door failed!
sendAndApply(&iw);
break;
}
TryMoveHero tmh;
tmh.id = h->id;
tmh.movePoints = std::max<int>(0, h->movement - 300);
tmh.result = TryMoveHero::TELEPORTATION;
tmh.start = h->pos;
tmh.end = pos;
getTilesInRange(tmh.fowRevealed, pos, h->getSightRadious(), h->tempOwner,1);
sendAndApply(&tmh);
}
break;
case VISIONS: //Visions
case VIEW_EARTH: //View Earth
case DISGUISE: //Disguise
case VIEW_AIR: //View Air
case FLY: //Fly
case WATER_WALK: //Water Walk
case TOWN_PORTAL: //Town Portal
default:
COMPLAIN_RET("This spell is not implemented yet!");
}