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

* fixed crashes with paths when fastly switching heroes

* fixed and improved slider behavior
* fixed possible thread access conflicts
* support for attacking town with visiting hero
* fixed dwellings saving
* minor improvements
This commit is contained in:
Michał W. Urbańczyk 2009-09-12 22:17:23 +00:00
parent a939e134a1
commit efb1049860
15 changed files with 92 additions and 45 deletions

View File

@ -738,6 +738,13 @@ void CCallback::setSelection(const CArmedInstance * obj)
ss.player = player;
ss.id = obj->id;
sendRequest(&ss);
if(obj->ID == HEROI_TYPE)
{
cl->gs->calculatePaths(static_cast<const CGHeroInstance *>(obj), *cl->pathInfo);
//nasty workaround. TODO: nice workaround
cl->gs->getPlayer(player)->currentSelection = obj->id;
}
}
void CCallback::recruitHero(const CGTownInstance *town, const CGHeroInstance *hero)

View File

@ -91,6 +91,7 @@ AdventureMapButton::AdventureMapButton ()
ourObj=NULL;
state=0;
blocked = actOnDown = false;
used = LCLICK | RCLICK | HOVER | KEYBOARD;
}
//AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ, std::vector<std::string> * add, bool playerColoredButton)
//{
@ -435,10 +436,9 @@ void CHighlightableButtonsGroup::block( ui8 on )
void CSlider::sliderClicked()
{
if(!moving)
if(!(active & MOVE))
{
activateMouseMove();
moving = true;
}
}
@ -527,26 +527,24 @@ void CSlider::clickLeft(tribool down, bool previousState)
float rw = 0;
if(horizontal)
{
pw = GH.current->motion.x-pos.x-16;
pw = GH.current->motion.x-pos.x-25;
rw = pw / ((float)(pos.w-48));
}
else
{
pw = GH.current->motion.y-pos.y-16;
pw = GH.current->motion.y-pos.y-24;
rw = pw / ((float)(pos.h-48));
}
if(pw < 0 || pw > (horizontal ? pos.w : pos.h) - 32)
if(pw < -8 || pw > (horizontal ? pos.w : pos.h) - 40)
return;
// if (rw>1) return;
// if (rw<0) return;
slider->clickLeft(true, slider->pressedL);
moveTo(rw * positions + 0.5f);
return;
}
if(moving)
{
if(active & MOVE)
deactivateMouseMove();
moving = false;
}
}
CSlider::~CSlider()
@ -561,7 +559,6 @@ CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int
setAmount(amount);
used = LCLICK;
moving = false;
strongInterest = true;

View File

@ -120,7 +120,7 @@ public:
amount, //how many elements
positions, //number of highest position (0 if there is only one)
value; //first active element
bool horizontal, moving;
bool horizontal;
CDefEssential *imgs ;
boost::function<void(int)> moved;

View File

@ -1896,13 +1896,17 @@ void CAdvMapInt::select(const CArmedInstance *sel )
{
int pos = vstd::findPos(townList.items,sel);
townList.selected = pos;
townList.fixPos();
}
else //hero selected
{
const CGHeroInstance *h = static_cast<const CGHeroInstance*>(sel);
if(LOCPLINT->getWHero(heroList.selected) != h)
{
heroList.selected = heroList.getPosOfHero(h);
heroList.fixPos();
}
if(vstd::contains(paths,h)) //hero has assigned path
{

View File

@ -1504,12 +1504,14 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
GH.pushInt(new CExchangeWindow(hero2, hero1));
}
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
{
//redraw minimap if owner changed
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(sop->what == 1)
{
const CGObjectInstance * obj = cb->getObjectInfo(sop->id);

View File

@ -104,9 +104,9 @@ public:
void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(int obj, int heroID){};
void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
void setAmount(int objid, ui32 val){};
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;};
void giveHeroBonus(GiveBonus * bonus){};

View File

@ -1126,6 +1126,20 @@ CList::CList(int Size)
{
}
void CList::fixPos()
{
int oldFrom = from;
if(selected < 0) //no selection, do nothing
return;
if(selected < from) //scroll up
from = selected;
else if(from + SIZE <= selected)
from = selected - SIZE + 1;
amin(from, size() - SIZE);
amax(from, 0);
}
CHeroList::CHeroList(int Size)
:CList(Size), heroes(LOCPLINT->wanderingHeroes)
{
@ -1422,6 +1436,12 @@ void CHeroList::show( SDL_Surface * to )
{
}
int CHeroList::size()
{
return heroes.size();
}
CTownList::~CTownList()
{
delete arrup;
@ -1659,6 +1679,11 @@ void CTownList::show( SDL_Surface * to )
}
int CTownList::size()
{
return items.size();
}
CCreaturePic::CCreaturePic(const CCreature *cre, bool Big)
:c(cre),big(Big)
{

View File

@ -272,6 +272,8 @@ public:
virtual void genList()=0;
virtual void select(int which)=0;
virtual void draw(SDL_Surface * to)=0;
virtual int size() = 0; //how many elements do we have
void fixPos(); //scrolls list, so the selection will be visible
};
class CHeroList
: public CList
@ -295,6 +297,7 @@ public:
void draw(SDL_Surface * to);
void show(SDL_Surface * to);
void init();
int size(); //how many elements do we have
};
class CTownList
@ -316,6 +319,7 @@ public:
void keyPressed (const SDL_KeyboardEvent & key); //call-in
void draw(SDL_Surface * to);
void show(SDL_Surface * to);
int size(); //how many elements do we have
};
class CCreaturePic //draws picture with creature on background, use nextFrame=true to get animation

View File

@ -547,7 +547,7 @@ void SetSelection::applyCl(CClient *cl)
if(!h)
return;
CPackForClient::GS(cl)->calculatePaths(h, *cl->pathInfo);
//CPackForClient::GS(cl)->calculatePaths(h, *cl->pathInfo);
}
void ShowInInfobox::applyCl(CClient *cl)

View File

@ -777,10 +777,12 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
//exchange
cb->heroExchange(id, h->id);
}
else
else //battle
{
//battle
cb->startBattleI(h, this, false);
if(visitedTown) //we're in town
visitedTown->onHeroVisit(h); //town will handle attacking
else
cb->startBattleI(h, this);
}
}
else if(ID == 62) //prison
@ -1350,7 +1352,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const
{
if(answer)
cb->startBattleI(h, this, false, boost::bind(&CGDwelling::fightOver, this, h, _1));
cb->startBattleI(h, this, boost::bind(&CGDwelling::fightOver, this, h, _1));
}
void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const
@ -1503,7 +1505,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
if(getOwner() != h->getOwner())
{
//TODO ally check
if(army)
if(army || visitingHero)
{
const CGHeroInstance *defendingHero = NULL;
if(visitingHero)
@ -2226,7 +2228,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
void CGCreature::fight( const CGHeroInstance *h ) const
{
cb->startBattleI(h, this, false, boost::bind(&CGCreature::endBattle,this,_1));
cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1));
}
void CGCreature::flee( const CGHeroInstance * h ) const
@ -2362,7 +2364,7 @@ void CGResource::collectRes( int player ) const
void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const
{
if(agreed)
cb->startBattleI(h, this, false, boost::bind(&CGResource::endBattle,this,_1,h));
cb->startBattleI(h, this, boost::bind(&CGResource::endBattle,this,_1,h));
}
void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -2614,7 +2616,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const
void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const
{
if(agreed)
cb->startBattleI(h, this, false, boost::bind(&CGArtifact::endBattle,this,_1,h));
cb->startBattleI(h, this, boost::bind(&CGArtifact::endBattle,this,_1,h));
}
void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -3118,7 +3120,7 @@ void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const
iw.player = h->tempOwner;
iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw);
cb->startBattleI(h, this, false, boost::bind(&CGPandoraBox::endBattle, this, h, _1)); //grants things after battle
cb->startBattleI(h, this, boost::bind(&CGPandoraBox::endBattle, this, h, _1)); //grants things after battle
}
else if (message.size() == 0 && resources.size() == 0
&& primskills.size() == 0 && abilities.size() == 0
@ -3415,7 +3417,7 @@ void CGEvent::activated( const CGHeroInstance * h ) const
else
iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw);
cb->startBattleI(h, this, false, boost::bind(&CGEvent::endBattle,this,h,_1));
cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1));
}
else
{
@ -3623,7 +3625,7 @@ void CGGarrison::onHeroVisit (const CGHeroInstance *h) const
{
if (h->tempOwner != tempOwner && army) {
//TODO: Find a way to apply magic garrison effects in battle.
cb->startBattleI(h, this, false, boost::bind(&CGGarrison::fightOver, this, h, _1));
cb->startBattleI(h, this, boost::bind(&CGGarrison::fightOver, this, h, _1));
return;
}
@ -4026,7 +4028,7 @@ void CBank::fightGuards (const CGHeroInstance * h, ui32 accept) const
if (accept)
{
cb->setObjProperty (id, 17, ran()); //get army
cb->startBattleI (h, this, true, boost::bind (&CBank::endBattle, this, h, _1));
cb->startBattleI (h, this, boost::bind (&CBank::endBattle, this, h, _1), true);
}
}
void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) const

View File

@ -1485,16 +1485,22 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
//init visiting and garrisoned heroes
for(unsigned int l=0; l<k->second.heroes.size();l++)
{
CGHeroInstance *h = k->second.heroes[l];
for(unsigned int m=0; m<k->second.towns.size();m++)
{
int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
if(vistile == k->second.heroes[l]->pos || k->second.heroes[l]->pos==k->second.towns[m]->pos)
CGTownInstance *t = k->second.towns[m];
int3 vistile = t->pos; vistile.x--; //tile next to the entrance
if(vistile == h->pos || h->pos==t->pos)
{
k->second.towns[m]->visitingHero = k->second.heroes[l];
k->second.heroes[l]->visitedTown = k->second.towns[m];
k->second.heroes[l]->inTownGarrison = false;
if(k->second.heroes[l]->pos==k->second.towns[m]->pos)
k->second.heroes[l]->pos.x -= 1;
t->visitingHero = h;
h->visitedTown = t;
h->inTownGarrison = false;
if(h->pos == t->pos) //visiting hero placed in the editor has same pos as the town - we need to correct it
{
map->removeBlockVisTiles(h);
h->pos.x -= 1;
map->addBlockVisTiles(h);
}
break;
}
}

View File

@ -80,9 +80,9 @@ public:
virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0;
virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function<void(BattleResult*)> cb = 0)=0; //if any of armies is hero, hero will be used
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army
virtual void setAmount(int objid, ui32 val)=0;
virtual bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;

View File

@ -25,6 +25,7 @@ void registerTypes1(Serializer &s)
s.template registerType<CTownBonus>();
s.template registerType<CGPandoraBox>();
s.template registerType<CGEvent>();
s.template registerType<CGDwelling>();
s.template registerType<CGVisitableOPH>();
s.template registerType<CGVisitableOPW>();
s.template registerType<CGTeleport>();

View File

@ -1501,7 +1501,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
return true;
}
//TODO: check for ally
startBattleI(h, dh, false);
startBattleI(h, dh);
return true;
}
}
@ -1670,7 +1670,7 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc
boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb, town));
}
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function<void(BattleResult*)> cb )
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb, bool creatureBank )
{
startBattleI(army1, army2, tile,
army1->ID == HEROI_TYPE ? static_cast<const CGHeroInstance*>(army1) : NULL,
@ -1678,9 +1678,9 @@ void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstan
creatureBank, cb);
}
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function<void(BattleResult*)> cb)
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb, bool creatureBank)
{
startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), creatureBank, cb);
startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb, creatureBank);
}
//void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army

View File

@ -122,10 +122,9 @@ public:
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
void moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int hid, int pos);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function<void(BattleResult*)> cb);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val);
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);
void giveHeroBonus(GiveBonus * bonus);