mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Second part of sailing support:
* boat graphics and appropriate flags are used * disembarking possible * new objects supported: - Flotsam - Shipwreck Survivor - Sea Chest
This commit is contained in:
parent
2ca7cc5b5c
commit
9272f501cd
@ -282,7 +282,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
||||
int3 hp = details.start;
|
||||
if (details.result != TryMoveHero::SUCCESS) //hero failed to move
|
||||
{
|
||||
if(details.result == TryMoveHero::BLOCKING_VISIT)
|
||||
if(details.result != TryMoveHero::FAILED)
|
||||
{
|
||||
adventureInt->paths.erase(ho);
|
||||
adventureInt->terrain.currentPath = NULL;
|
||||
@ -290,6 +290,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
||||
|
||||
ho->isStanding = true;
|
||||
stillMoveHero.setn(STOP_MOVE);
|
||||
LOCPLINT->totalRedraw();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1573,6 +1574,12 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath path )
|
||||
|
||||
for(int i=path.nodes.size()-1; i>0 && stillMoveHero.data == CONTINUE_MOVE; i--)
|
||||
{
|
||||
//stop sending move requests if hero exhausted all his move points
|
||||
if(!h->movement)
|
||||
{
|
||||
stillMoveHero.data = STOP_MOVE;
|
||||
break;
|
||||
}
|
||||
// Start a new sound for the hero movement or let the existing one carry on.
|
||||
#if 0
|
||||
// TODO
|
||||
|
@ -368,19 +368,20 @@ void Graphics::loadHeroFlags(std::pair<std::vector<CDefEssential *> Graphics::*,
|
||||
rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12);
|
||||
for(int q=0; q<8; ++q)
|
||||
{
|
||||
for(size_t o=0; o<(this->*pr.first)[q]->ourImages.size(); ++o)
|
||||
std::vector<Cimage> &curImgs = (this->*pr.first)[q]->ourImages;
|
||||
for(size_t o=0; o<curImgs.size(); ++o)
|
||||
{
|
||||
for(size_t p=0;p<rotations.size();p++)
|
||||
{
|
||||
if((this->*pr.first)[q]->ourImages[o].groupNumber==rotations[p].first)
|
||||
if(curImgs[o].groupNumber==rotations[p].first)
|
||||
{
|
||||
for(int e=0; e<8; ++e)
|
||||
{
|
||||
Cimage nci;
|
||||
nci.bitmap = CSDL_Ext::rotate01((this->*pr.first)[q]->ourImages[o+e].bitmap);
|
||||
nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
|
||||
nci.groupNumber = rotations[p].second;
|
||||
nci.imName = std::string();
|
||||
(this->*pr.first)[q]->ourImages.push_back(nci);
|
||||
curImgs.push_back(nci);
|
||||
}
|
||||
o+=8;
|
||||
}
|
||||
@ -388,50 +389,50 @@ void Graphics::loadHeroFlags(std::pair<std::vector<CDefEssential *> Graphics::*,
|
||||
}
|
||||
if (mode)
|
||||
{
|
||||
for(size_t o=0; o<flags4[q]->ourImages.size(); ++o)
|
||||
for(size_t o=0; o<curImgs.size(); ++o)
|
||||
{
|
||||
if(flags4[q]->ourImages[o].groupNumber==1)
|
||||
if(curImgs[o].groupNumber==1)
|
||||
{
|
||||
for(int e=0; e<8; ++e)
|
||||
{
|
||||
Cimage nci;
|
||||
nci.bitmap = CSDL_Ext::rotate01(flags4[q]->ourImages[o+e].bitmap);
|
||||
nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
|
||||
nci.groupNumber = 13;
|
||||
nci.imName = std::string();
|
||||
flags4[q]->ourImages.push_back(nci);
|
||||
curImgs.push_back(nci);
|
||||
}
|
||||
o+=8;
|
||||
}
|
||||
if(flags4[q]->ourImages[o].groupNumber==2)
|
||||
if(curImgs[o].groupNumber==2)
|
||||
{
|
||||
for(int e=0; e<8; ++e)
|
||||
{
|
||||
Cimage nci;
|
||||
nci.bitmap = CSDL_Ext::rotate01(flags4[q]->ourImages[o+e].bitmap);
|
||||
nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
|
||||
nci.groupNumber = 14;
|
||||
nci.imName = std::string();
|
||||
flags4[q]->ourImages.push_back(nci);
|
||||
curImgs.push_back(nci);
|
||||
}
|
||||
o+=8;
|
||||
}
|
||||
if(flags4[q]->ourImages[o].groupNumber==3)
|
||||
if(curImgs[o].groupNumber==3)
|
||||
{
|
||||
for(int e=0; e<8; ++e)
|
||||
{
|
||||
Cimage nci;
|
||||
nci.bitmap = CSDL_Ext::rotate01(flags4[q]->ourImages[o+e].bitmap);
|
||||
nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
|
||||
nci.groupNumber = 15;
|
||||
nci.imName = std::string();
|
||||
flags4[q]->ourImages.push_back(nci);
|
||||
curImgs.push_back(nci);
|
||||
}
|
||||
o+=8;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(size_t ff=0; ff<(this->*pr.first)[q]->ourImages.size(); ++ff)
|
||||
for(size_t ff=0; ff<curImgs.size(); ++ff)
|
||||
{
|
||||
SDL_SetColorKey((this->*pr.first)[q]->ourImages[ff].bitmap, SDL_SRCCOLORKEY,
|
||||
SDL_MapRGB((this->*pr.first)[q]->ourImages[ff].bitmap->format, 0, 255, 255)
|
||||
SDL_SetColorKey(curImgs[ff].bitmap, SDL_SRCCOLORKEY,
|
||||
SDL_MapRGB(curImgs[ff].bitmap->format, 0, 255, 255)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -456,9 +457,9 @@ void Graphics::loadHeroFlags()
|
||||
("AF05.DEF"),("AF06.DEF"),("AF07.DEF");
|
||||
boost::thread_group grupa;
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[3]),true));
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[2]),false));
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[1]),false));
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[0]),false));
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[2]),true));
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[1]),true));
|
||||
grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[0]),true));
|
||||
grupa.join_all();
|
||||
tlog0 << "Loading and transforming heroes' flags: "<<th.getDif()<<std::endl;
|
||||
}
|
||||
|
@ -140,16 +140,25 @@ void RemoveObject::applyCl( CClient *cl )
|
||||
|
||||
void TryMoveHero::applyFirstCl( CClient *cl )
|
||||
{
|
||||
if(result == TELEPORTATION || result == EMBARK)
|
||||
CGI->mh->removeObject(GS(cl)->getHero(id));
|
||||
CGHeroInstance *h = GS(cl)->getHero(id);
|
||||
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK)
|
||||
CGI->mh->removeObject(h);
|
||||
|
||||
|
||||
if(result == DISEMBARK)
|
||||
CGI->mh->printObject(h->boat);
|
||||
}
|
||||
|
||||
void TryMoveHero::applyCl( CClient *cl )
|
||||
{
|
||||
const CGHeroInstance *h = cl->getHero(id);
|
||||
|
||||
if(result == TELEPORTATION || result == EMBARK)
|
||||
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK)
|
||||
CGI->mh->printObject(h);
|
||||
|
||||
if(result == EMBARK)
|
||||
CGI->mh->hideObject(h->boat);
|
||||
|
||||
int player = h->tempOwner;
|
||||
|
||||
if(vstd::contains(cl->playerint,player))
|
||||
|
@ -2200,6 +2200,60 @@ void CGPickable::initObj()
|
||||
val1 = val2 * 100;
|
||||
type = ran()%6; //given resource
|
||||
break;
|
||||
case 29: //floatsam
|
||||
switch(type = ran()%4)
|
||||
{
|
||||
case 0:
|
||||
val1 = val2 = 0;
|
||||
break;
|
||||
case 1:
|
||||
val1 = 5;
|
||||
val2 = 0;
|
||||
break;
|
||||
case 2:
|
||||
val1 = 5;
|
||||
val2 = 200;
|
||||
break;
|
||||
case 3:
|
||||
val1 = 10;
|
||||
val2 = 500;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 82: //sea chest
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
if(hlp < 20)
|
||||
{
|
||||
val1 = 0;
|
||||
type = 0;
|
||||
}
|
||||
else if(hlp < 90)
|
||||
{
|
||||
val1 = 1500;
|
||||
type = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
val1 = 1000;
|
||||
val2 = VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id;
|
||||
type = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 86: //Shipwreck Survivor
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
if(hlp < 55)
|
||||
val1 = VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id;
|
||||
else if(hlp < 75)
|
||||
val1 = VLC->arth->minors[ran()%VLC->arth->minors.size()]->id;
|
||||
else if(hlp < 95)
|
||||
val1 = VLC->arth->majors[ran()%VLC->arth->majors.size()]->id;
|
||||
else
|
||||
val1 = VLC->arth->relics[ran()%VLC->arth->relics.size()]->id;
|
||||
}
|
||||
break;
|
||||
case 101: //treasure chest
|
||||
{
|
||||
int hlp = ran()%100;
|
||||
@ -2247,6 +2301,57 @@ void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->showInfoDialog(&iw);
|
||||
break;
|
||||
}
|
||||
case 29: //flotsam
|
||||
{
|
||||
cb->giveResource(h->tempOwner,0,val1); //wood
|
||||
cb->giveResource(h->tempOwner,6,val2);//gold
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::GENIE;
|
||||
iw.player = h->tempOwner;
|
||||
if(val1)
|
||||
iw.components.push_back(Component(2,0,val1,0));
|
||||
if(val2)
|
||||
iw.components.push_back(Component(2,6,val2,0));
|
||||
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 51+type);
|
||||
cb->showInfoDialog(&iw);
|
||||
break;
|
||||
}
|
||||
case 82: //Sea Chest
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::chest;
|
||||
iw.player = h->tempOwner;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 116 + type);
|
||||
|
||||
if(val1) //there is gold
|
||||
{
|
||||
iw.components.push_back(Component(2,6,val1,0));
|
||||
cb->giveResource(h->tempOwner,6,val1);
|
||||
}
|
||||
if(type == 1) //art
|
||||
{
|
||||
//TODO: what if no space in backpack?
|
||||
iw.components.push_back(Component(4, val2, 1, 0));
|
||||
iw.text.addReplacement(MetaString::ART_NAMES, val2);
|
||||
cb->giveHeroArtifact(val2,h->id,-2);
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
break;
|
||||
}
|
||||
case 86: //Shipwreck Survivor
|
||||
{
|
||||
//TODO: what if no space in backpack?
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::experience;
|
||||
iw.player = h->tempOwner;
|
||||
iw.components.push_back(Component(4,val1,1,0));
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 125);
|
||||
iw.text.addReplacement(MetaString::ART_NAMES, val1);
|
||||
cb->giveHeroArtifact(val1,h->id,-2);
|
||||
cb->showInfoDialog(&iw);
|
||||
break;
|
||||
}
|
||||
case 101: //treasure chest
|
||||
{
|
||||
if (subID) //not OH3 treasure chest
|
||||
|
@ -581,7 +581,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_EXPORT CGPickable : public CGObjectInstance //campfire, treasure chest
|
||||
class DLL_EXPORT CGPickable : public CGObjectInstance //campfire, treasure chest, Flotsam, Shipwreck Survivor, Sea Chest
|
||||
{
|
||||
public:
|
||||
ui32 type, val1, val2;
|
||||
|
@ -288,6 +288,9 @@ void TryMoveHero::applyGs( CGameState *gs )
|
||||
CGHeroInstance *h = gs->getHero(id);
|
||||
h->movement = movePoints;
|
||||
|
||||
if(result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK)
|
||||
h->moveDir = getDir(start,end);
|
||||
|
||||
if(result == EMBARK) //hero enters boat at dest tile
|
||||
{
|
||||
const TerrainTile &tt = gs->map->getTile(CGHeroInstance::convertPosition(end, false));
|
||||
@ -298,19 +301,26 @@ void TryMoveHero::applyGs( CGameState *gs )
|
||||
h->boat = boat;
|
||||
boat->hero = h;
|
||||
}
|
||||
else if(result == DISEMBARK) //hero leaves boat to dest tile
|
||||
{
|
||||
h->boat->direction = h->moveDir;
|
||||
h->boat->pos = start;
|
||||
h->boat->hero = NULL;
|
||||
gs->map->addBlockVisTiles(h->boat);
|
||||
h->boat = NULL;
|
||||
}
|
||||
|
||||
if(start!=end && (result == SUCCESS || result == TELEPORTATION || result == EMBARK))
|
||||
if(start!=end && (result == SUCCESS || result == TELEPORTATION || result == EMBARK || result == DISEMBARK))
|
||||
{
|
||||
gs->map->removeBlockVisTiles(h);
|
||||
h->pos = end;
|
||||
if(h->boat)
|
||||
h->boat->pos = end;
|
||||
gs->map->addBlockVisTiles(h);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(int3 t, fowRevealed)
|
||||
gs->getPlayer(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1;
|
||||
|
||||
if(result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK)
|
||||
h->moveDir = getDir(start,end);
|
||||
}
|
||||
|
||||
DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )
|
||||
|
@ -1498,7 +1498,10 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
|
||||
break;
|
||||
}
|
||||
case 12: //campfire
|
||||
case 101: //treasure chest
|
||||
case 29: //Flotsam
|
||||
case 82: //Sea Chest
|
||||
case 86: //Shipwreck Survivor
|
||||
case 101://treasure chest
|
||||
{
|
||||
nobj = new CGPickable();
|
||||
break;
|
||||
|
@ -784,10 +784,29 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st
|
||||
SDL_Surface * tb;
|
||||
if(themp->type==NULL)
|
||||
continue;
|
||||
|
||||
//pick graphics of hero (or boat if hero is sailing)
|
||||
std::vector<Cimage> & iv = (themp->boat)
|
||||
? graphics->boatAnims[themp->boat->subID]->ourImages
|
||||
: graphics->heroAnims[themp->type->heroType]->ourImages;
|
||||
|
||||
//pick appropriate flag set
|
||||
std::vector<CDefEssential *> Graphics::*flg = NULL;
|
||||
if(themp->boat)
|
||||
{
|
||||
switch (themp->boat->subID)
|
||||
{
|
||||
case 0: flg = &Graphics::flags1; break;
|
||||
case 1: flg = &Graphics::flags2; break;
|
||||
case 2: flg = &Graphics::flags3; break;
|
||||
default: tlog1 << "Not supported boat subtype: " << themp->boat->subID << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flg = &Graphics::flags4;
|
||||
}
|
||||
|
||||
if(!themp->isStanding) //hero is moving
|
||||
{
|
||||
size_t gg;
|
||||
@ -802,7 +821,7 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr);
|
||||
pp.y+=imgVal*2-32;
|
||||
sr.y-=16;
|
||||
SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[gg+heroAnim%imgVal+35].bitmap, &pp, extSurf, &sr);
|
||||
SDL_BlitSurface((graphics->*flg)[themp->getOwner()]->ourImages[gg+heroAnim%imgVal+35].bitmap, &pp, extSurf, &sr);
|
||||
}
|
||||
else //hero stands still
|
||||
{
|
||||
@ -825,7 +844,7 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st
|
||||
bufr.h = 64;
|
||||
bufr.w = 96;
|
||||
if(bufr.x-extRect->x>-64)
|
||||
SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[ getHeroFrameNum(themp->moveDir, !themp->isStanding) *8+(heroAnim/4)%imgVal].bitmap, NULL, extSurf, &bufr);
|
||||
SDL_BlitSurface((graphics->*flg)[themp->getOwner()]->ourImages[ getHeroFrameNum(themp->moveDir, !themp->isStanding) *8+(heroAnim/4)%imgVal].bitmap, NULL, extSurf, &bufr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1167,7 +1167,10 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
||||
if((t.tertype == TerrainTile::rock || (t.blocked && !t.visitable))
|
||||
&& complain("Cannot move hero, destination tile is blocked!")
|
||||
|| (!h->boat && !h->canWalkOnSea() && t.tertype == TerrainTile::water && (t.visitableObjects.size() != 1 || t.visitableObjects.front()->ID != 8))
|
||||
&& complain("Cannot move hero, destination tile is on water!"))
|
||||
&& complain("Cannot move hero, destination tile is on water!")
|
||||
|| (h->boat && t.tertype != TerrainTile::water && t.blocked)
|
||||
&& complain("Cannot disembark hero, tile is blocked!")
|
||||
|| !h->movement && complain("Hero don't have any movement points left!"))
|
||||
{
|
||||
//send info about movement failure
|
||||
sendAndApply(&tmh);
|
||||
@ -1185,11 +1188,22 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
||||
sendAndApply(&tmh);
|
||||
return true;
|
||||
}
|
||||
//hero leaves the boat
|
||||
else if(h->boat && t.tertype != TerrainTile::water && !t.blocked)
|
||||
{
|
||||
tmh.result = TryMoveHero::DISEMBARK;
|
||||
tmh.movePoints = 0; //disembarking takes all move points
|
||||
//TODO: check for bonus that removes that penalty
|
||||
|
||||
getTilesInRange(tmh.fowRevealed,h->getSightCenter()+(tmh.end-tmh.start),h->getSightRadious(),h->tempOwner,1);
|
||||
sendAndApply(&tmh);
|
||||
return true;
|
||||
}
|
||||
|
||||
//checks for standard movement
|
||||
if(!instant)
|
||||
{
|
||||
if( (distance(h->pos,dst)>=1.5) //tiles are not neighouring
|
||||
if( (distance(h->pos,dst)>=1.5) //tiles are not neighbouring
|
||||
|| (h->movement < cost && h->movement < 100) //lack of movement points
|
||||
)
|
||||
{
|
||||
@ -1308,6 +1322,7 @@ int CGameHandler::getCurrentPlayer()
|
||||
|
||||
void CGameHandler::giveResource(int player, int which, int val)
|
||||
{
|
||||
if(!val) return; //don't waste time on empty call
|
||||
SetResource sr;
|
||||
sr.player = player;
|
||||
sr.resid = which;
|
||||
|
Loading…
x
Reference in New Issue
Block a user