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

* mostly done Events objects handling

* some moving hero code improvements
* fixed Blacksmith
* minor changes
This commit is contained in:
Michał W. Urbańczyk 2009-04-20 22:57:07 +00:00
parent 408411d8c3
commit c8b6858716
14 changed files with 460 additions and 170 deletions

View File

@ -414,8 +414,11 @@ void CTerrainRect::clickLeft(tribool down)
int3 mp = whichTileIsIt();
if ((mp.x<0) || (mp.y<0))
return;
std::vector < const CGObjectInstance * > objs;
if (LOCPLINT->adventureInt->selection->ID != HEROI_TYPE)
std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp), //blocking objects at tile
vobjs = LOCPLINT->cb->getVisitableObjs(mp); //visitable objects
if (LOCPLINT->adventureInt->selection->ID != HEROI_TYPE) //hero is not selected (presumably town)
{
if(currentPath)
{
@ -423,91 +426,83 @@ void CTerrainRect::clickLeft(tribool down)
delete currentPath;
currentPath = NULL;
}
objs = LOCPLINT->cb->getBlockingObjs(mp);
for(size_t i=0; i < objs.size(); ++i)
for(size_t i=0; i < bobjs.size(); ++i)
{
if(objs[i]->ID == TOWNI_TYPE && objs[i]->tempOwner == LOCPLINT->playerID) //town
if(bobjs[i]->ID == TOWNI_TYPE && bobjs[i]->getOwner() == LOCPLINT->playerID) //our town clicked
{
if(LOCPLINT->adventureInt->selection == (objs[i]))
{
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(objs[i]));
}
if(LOCPLINT->adventureInt->selection == (bobjs[i])) //selected town clicked
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(bobjs[i]));
else
{
LOCPLINT->adventureInt->select(static_cast<const CArmedInstance*>(objs[i]));
LOCPLINT->adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i]));
return;
}
}
else if(objs[i]->ID == HEROI_TYPE && objs[i]->tempOwner == LOCPLINT->playerID)
else if(bobjs[i]->ID == HEROI_TYPE && bobjs[i]->tempOwner == LOCPLINT->playerID) //hero clicked - select him
{
LOCPLINT->adventureInt->select(static_cast<const CArmedInstance*>(objs[i]));
return;
}
}
return;
}
else
{
objs = LOCPLINT->cb->getVisitableObjs(mp);
for(size_t i=0; i < objs.size(); ++i)
{
if(objs[i]->ID == TOWNI_TYPE)
goto endchkpt;
}
objs = LOCPLINT->cb->getBlockingObjs(mp);
for(size_t i=0; i < objs.size(); ++i)
{
if(objs[i]->ID == TOWNI_TYPE && objs[i]->tempOwner == LOCPLINT->playerID) //town
{
LOCPLINT->adventureInt->select(static_cast<const CArmedInstance*>(objs[i]));
return;
}
else if(objs[i]->ID == HEROI_TYPE && objs[i]->tempOwner == LOCPLINT->playerID && LOCPLINT->adventureInt->selection == (objs[i]))
{
LOCPLINT->openHeroWindow(static_cast<const CGHeroInstance*>(objs[i]));
LOCPLINT->adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i]));
return;
}
}
}
endchkpt:
bool mres =true;
else //hero is selected
{
bool townEntrance = false; //town entrance tile has been clicked?
const CGHeroInstance * currentHero = static_cast<const CGHeroInstance*>(LOCPLINT->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)
{
if(bobjs[i]->ID == TOWNI_TYPE && bobjs[i]->tempOwner == LOCPLINT->playerID) //town - switch selection to it
{
LOCPLINT->adventureInt->select(static_cast<const CArmedInstance*>(bobjs[i]));
return;
}
else if(bobjs[i]->ID == HEROI_TYPE //it's a hero
&& bobjs[i]->tempOwner == LOCPLINT->playerID //our hero (is this condition needed?)
&& currentHero == (bobjs[i]) ) //and selected one
{
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)
{
if ( (currentPath->endPos()) == mp)
{ //move
CPath sended(*currentPath); //temporary path - engine will operate on it
if (currentPath->endPos() == mp) //we'll be moving
{
LOCPLINT->pim->unlock();
mres = LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(LOCPLINT->adventureInt->selection),&sended);
LOCPLINT->moveHero(currentHero,*currentPath);
LOCPLINT->pim->lock();
if(mres)
}
else //remove an old path
{
delete currentPath;
currentPath=NULL;
LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.getPosOfHero(LOCPLINT->adventureInt->selection)].second = NULL;
}
}
else
{
delete currentPath;
currentPath=NULL;
LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.getPosOfHero(LOCPLINT->adventureInt->selection)].second = NULL;
}
}
const CGHeroInstance * currentHero = (LOCPLINT->adventureInt->heroList.items.size())?(LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.selected].first):(NULL);
if(currentHero)
else //remove old path and find a new one
{
int3 bufpos = currentHero->getPosition(false);
if (mres)
{
CPath *& pathForCurhero = LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.selected].second;
if(pathForCurhero)
delete pathForCurhero;
currentPath = pathForCurhero = LOCPLINT->cb->getPath(bufpos, mp, currentHero);;
}
return;
}
} //end of hero is selected "case"
}
void CTerrainRect::clickRight(tribool down)
{
@ -1318,9 +1313,9 @@ void CAdvMapInt::fmoveHero()
return;
if (!terrain.currentPath)
return;
CPath sended(*(terrain.currentPath)); //temporary path - engine will operate on it
LOCPLINT->pim->unlock();
LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(LOCPLINT->adventureInt->selection),&sended);
LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(LOCPLINT->adventureInt->selection),*terrain.currentPath);
LOCPLINT->pim->lock();
}
void CAdvMapInt::fshowSpellbok()

View File

@ -25,7 +25,6 @@
#ifdef max
#undef max
#endif
extern CSharedCond<std::set<CPack*> > mess;
/*
* CCallback.cpp, part of VCMI engine
@ -67,21 +66,6 @@ bool CCallback::moveHero(const CGHeroInstance *h, int3 dst) const
{
MoveHero pack(dst,h->id);
*cl->serv << &pack;
{//wait till there is server answer
boost::unique_lock<boost::mutex> lock(*mess.mx);
while(std::find_if(mess.res->begin(),mess.res->end(),&isType<501>) == mess.res->end())
mess.cv->wait(lock);
std::set<CPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),&isType<501>);
TryMoveHero *tmh = dynamic_cast<TryMoveHero*>(*itr);
mess.res->erase(itr);
if(!tmh->result)
{
delete tmh;
return false;
}
delete tmh;
}
return true;
}
void CCallback::selectionMade(int selection, int asker)
@ -343,9 +327,6 @@ const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj) const
int CCallback::swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)
{
if(s1->tempOwner != player || s2->tempOwner != player)
return -1;
ArrangeStacks pack(1,p1,p2,s1->id,s2->id,0);
*cl->serv << &pack;
return 0;
@ -353,20 +334,12 @@ int CCallback::swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2,
int CCallback::mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)
{
if ((s1->tempOwner!= player || s2->tempOwner!=player))
{
return -1;
}
ArrangeStacks pack(2,p1,p2,s1->id,s2->id,0);
*cl->serv << &pack;
return 0;
}
int CCallback::splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val)
{
if (s1->tempOwner!= player || s2->tempOwner!=player || (!val))
{
return -1;
}
ArrangeStacks pack(3,p1,p2,s1->id,s2->id,val);
*cl->serv << &pack;
return 0;

View File

@ -581,8 +581,8 @@ void CCastleInterface::buildingClicked(int building)
bool possible = (LOCPLINT->cb->getResourceAmount(6) >= price);
if(vstd::contains(hero->artifWorn,ui16(aid+9))) //hero already has machine
possible = false;
deactivate();
(new CBlacksmithDialog(possible,CArtHandler::convertMachineID(aid,false),aid,hero->id))->activate();
LOCPLINT->pushInt(new CBlacksmithDialog(possible,CArtHandler::convertMachineID(aid,false),aid,hero->id));
break;
}
default:

View File

@ -898,9 +898,6 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
if(map->objects[no]->ID==26)
{
map->objects[no]->defInfo->handler=NULL;
map->removeBlockVisTiles(map->objects[no]);
map->objects[no]->defInfo->blockMap[5] = 255;
map->addBlockVisTiles(map->objects[no]);
}
map->objects[no]->hoverName = VLC->generaltexth->names[map->objects[no]->ID];
}

View File

@ -508,8 +508,11 @@ ComponentResolved::ComponentResolved( SComponent *Comp )
std::vector<std::string> * brtext = CMessage::breakText(comp->subtitle,11,true,true); //text
txt = CMessage::drawText(brtext,GEOR13);
delete brtext;
comp->pos.w = img->w;
comp->pos.h = img->h + COMPONENT_TO_SUBTITLE + CMessage::getMaxSizes(txt).second;
//calculate dimensions
std::pair<int,int> textSize = CMessage::getMaxSizes(txt);
comp->pos.w = std::max(textSize.first, img->w); //bigger of: subtitle width and image width
comp->pos.h = img->h + COMPONENT_TO_SUBTITLE + textSize.second;
}
ComponentResolved::~ComponentResolved()
@ -537,16 +540,18 @@ ComponentsToBlit::ComponentsToBlit(std::vector<SComponent*> & SComps, int maxw,
comps.resize(1);
int curw = 0;
int curr = 0;
int curr = 0; //current row
for(size_t i=0;i<SComps.size();i++)
{
int toadd = (SComps[i]->getImg()->w + 12 + (_or ? _or->w : 0));
ComponentResolved *cur = new ComponentResolved(SComps[i]);
int toadd = (cur->comp->pos.w + 12 + (_or ? _or->w : 0));
if (curw + toadd > maxw)
{
curr++;
amax(w,curw);
curw = SComps[i]->getImg()->w;
curw = cur->comp->pos.w;
comps.resize(curr+1);
}
else
@ -554,13 +559,13 @@ ComponentsToBlit::ComponentsToBlit(std::vector<SComponent*> & SComps, int maxw,
curw += toadd;
}
comps[curr].push_back(new ComponentResolved(SComps[i]));
comps[curr].push_back(cur);
}
for(size_t i=0;i<comps.size();i++)
{
int maxh = 0;
for(size_t j=0;j<comps.size();j++)
for(size_t j=0;j<comps[i].size();j++)
amax(maxh,comps[i][j]->comp->pos.h);
h += maxh + BETWEEN_COMPS_ROWS;
}
@ -575,7 +580,7 @@ void ComponentsToBlit::blitCompsOnSur( SDL_Surface * _or, int inter, int &curh,
{
ComponentResolved *cur = (comps)[i][j];
totalw += cur->comp->pos.w;
amax(maxh,cur->comp->pos.h);
amax(maxh,cur->comp->pos.h+BETWEEN_COMPS_ROWS);
}
if(_or)
{
@ -594,7 +599,7 @@ void ComponentsToBlit::blitCompsOnSur( SDL_Surface * _or, int inter, int &curh,
//blit img
int hlp = curh-(cur->comp->pos.h)/2;
blitAt(cur->img,curw,hlp,ret);
blitAt(cur->img, curw + (cur->comp->pos.w - cur->comp->getImg()->w)/2, hlp, ret);
cur->comp->pos.x = curw;
cur->comp->pos.y = hlp;
@ -603,7 +608,7 @@ void ComponentsToBlit::blitCompsOnSur( SDL_Surface * _or, int inter, int &curh,
CMessage::blitTextOnSur(cur->txt, hlp, ret, cur->comp->pos.x + cur->comp->pos.w/2 );
//if there is subsequent component blit "or"
curw += cur->img->w;
curw += cur->comp->pos.w;
if(j<((comps)[i].size()-1))
{
if(_or)

View File

@ -59,12 +59,15 @@
using namespace boost::assign;
using namespace CSDL_Ext;
extern TTF_Font * GEOR16;
CPlayerInterface * LOCPLINT;
extern std::queue<SDL_Event*> events;
extern boost::mutex eventsM;
void processCommand(const std::string &message, CClient *&client);
extern TTF_Font * GEOR16;
extern std::queue<SDL_Event*> events;
extern boost::mutex eventsM;
CPlayerInterface * LOCPLINT;
enum EMoveState {STOP_MOVE, WAITING_MOVE, CONTINUE_MOVE, DURING_MOVE};
CondSh<EMoveState> stillMoveHero; //used during hero movement
struct OCM_HLP_CGIN
{
@ -465,7 +468,7 @@ void CGarrisonInt::createSlots()
new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1,
&CGI->creh->creatures[i->second.first],i->second.second);
}
for(int i=0; i<sup->size(); i++)
for(int i=0; i<sdown->size(); i++)
if((*sdown)[i] == NULL)
(*sdown)[i] = new CGarrisonSlot(this, pos.x + (i*(58+interx)), pos.y + 64 + intery,i,1, NULL, 0);
}
@ -680,8 +683,21 @@ void SComponent::init(Etype Type, int Subtype, int Val)
subtitle = CGI->arth->artifacts[Subtype].Name();
break;
case primskill:
oss << ((Val>0)?("+"):("-")) << Val << " ";
if(Subtype < 4)
{
description = CGI->generaltexth->arraytxt[2+Subtype];
oss << ((Val>0)?("+"):("-")) << Val << " " << CGI->generaltexth->primarySkillNames[Subtype];
oss << CGI->generaltexth->primarySkillNames[Subtype];
}
else if(Subtype == 5) //spell points
{
description = CGI->generaltexth->allTexts[149];
oss << CGI->generaltexth->allTexts[387];
}
else
{
tlog1 << "Wrong subtype=" << Subtype << std::endl;
}
subtitle = oss.str();
break;
case secskill44: case secskill:
@ -697,6 +713,9 @@ void SComponent::init(Etype Type, int Subtype, int Val)
description = CGI->spellh->spells[Subtype].descriptions[Val];
subtitle = CGI->spellh->spells[Subtype].name;
break;
case creature:
subtitle = boost::lexical_cast<std::string>(Val) + " " + CGI->creh->creatures[Subtype].*(val != 1 ? &CCreature::namePl : &CCreature::nameSing);
break;
case experience:
description = CGI->generaltexth->allTexts[241];
oss << Val ;
@ -774,11 +793,14 @@ SDL_Surface * SComponent::getImg()
case spell:
return graphics->spellscr->ourImages[subtype].bitmap;
break;
case creature:
return graphics->bigImgs[subtype];
}
return NULL;
}
void SComponent::clickRight (tribool down)
{
if(description.size())
LOCPLINT->adventureInt->handleRightClick(description,down,this);
}
void SComponent::activate()
@ -1291,6 +1313,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
adventureInt->centerOn(details.ho->pos); //actualizing screen pos
adventureInt->minimap.draw(screen2);
adventureInt->heroList.draw(screen2);
if(details.style>0 || details.src == details.dst)
return;
@ -1303,19 +1326,27 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
if(ho->movement > 50)
ho->moveDir = getDir(details.src,details.dst);
ho->isStanding = true;
//adventureInt->heroList.draw();
if (adventureInt->terrain.currentPath && ho->movement>145) //TODO: better condition on movement - check cost of endtile
if(ho->movement)
{
delete adventureInt->terrain.currentPath;
adventureInt->terrain.currentPath = NULL;
adventureInt->heroList.items[adventureInt->heroList.getPosOfHero(ho)].second = NULL;
}
stillMoveHero.setn(STOP_MOVE);
return;
}
if (adventureInt->terrain.currentPath) //&& hero is moving
{
adventureInt->terrain.currentPath->nodes.erase(adventureInt->terrain.currentPath->nodes.end()-1);
if(!adventureInt->terrain.currentPath->nodes.size())
{
delete adventureInt->terrain.currentPath;
adventureInt->terrain.currentPath = NULL;
adventureInt->heroList.items[adventureInt->heroList.getPosOfHero(ho)].second = NULL;
}
}
@ -1767,16 +1798,20 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
switch(ev->type)
{
case SDL_MOUSEBUTTONDOWN:
stillMoveHero = false;
stillMoveHero.setn(STOP_MOVE);
break;
case SDL_KEYDOWN:
if(ev->key.keysym.sym < SDLK_F1)
stillMoveHero = false;
stillMoveHero.setn(STOP_MOVE);
break;
}
delete ev;
}
}
if(stillMoveHero.get() == 1)
stillMoveHero.setn(DURING_MOVE);
}
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{
@ -2145,11 +2180,10 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
void CPlayerInterface::battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side) //called by engine when battle starts; side=0 - left, side=1 - right
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
while(showingDialog->get())
SDL_Delay(20);
boost::unique_lock<boost::recursive_mutex> un(*pim);
battleInt = new CBattleInterface(army1, army2, hero1, hero2, genRect(600, 800, (conf.cc.resx - 800)/2, (conf.cc.resy - 600)/2));
pushInt(battleInt);
}
@ -2370,8 +2404,17 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components)
{
{
boost::unique_lock<boost::mutex> un(showingDialog->mx);
while(showingDialog->data)
showingDialog->cond.wait(un);
}
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement
stillMoveHero.setn(STOP_MOVE); //after showing dialog movement will be stopped
std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
CInfoWindow * temp = new CInfoWindow(text,playerID,36,components,pom);
@ -2480,9 +2523,9 @@ void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town )
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(castleInt)
{
//CFortScreen *fs = dynamic_cast<CFortScreen*>();
//if(fs)
// fs->draw(castleInt,false);
CFortScreen *fs = dynamic_cast<CFortScreen*>(listInt.front());
if(fs)
fs->draw(castleInt,false);
}
}
@ -2523,26 +2566,26 @@ void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
adventureInt->infoBar.draw(screen);
}
bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath * path )
bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath path )
{
if (!h || !path)
if (!h)
return false; //can't find hero
bool result = false;
path->convert(0);
stillMoveHero = true;
path.convert(0);
boost::unique_lock<boost::mutex> un(stillMoveHero.mx);
stillMoveHero.data = CONTINUE_MOVE;
for(int i=path->nodes.size()-1; i>0; i--)
for(int i=path.nodes.size()-1; i>0 && stillMoveHero.data == CONTINUE_MOVE; i--)
{
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(!stillMoveHero)
return result;
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);
while(stillMoveHero.data != STOP_MOVE && stillMoveHero.data != CONTINUE_MOVE)
stillMoveHero.cond.wait(un);
}
int3 endpos(path->nodes[i-1].coord.x, path->nodes[i-1].coord.y, h->pos.z);
result = cb->moveHero(h,endpos);
}
stillMoveHero = false;
//stillMoveHero = false;
return result;
}
@ -2553,6 +2596,19 @@ bool CPlayerInterface::shiftPressed() const
void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd )
{
{
boost::unique_lock<boost::mutex> un(showingDialog->mx);
while(showingDialog->data)
showingDialog->cond.wait(un);
}
boost::unique_lock<boost::recursive_mutex> un(*pim);
while(dialogs.size())
{
pim->unlock();
SDL_Delay(20);
pim->lock();
}
CGarrisonWindow *cgw = new CGarrisonWindow(up,down);
cgw->quit->callback += onEnd;
pushInt(cgw);
@ -2621,6 +2677,12 @@ void CPlayerInterface::totalRedraw()
objsToBlit.back()->showAll(screen);
}
void CPlayerInterface::requestRealized( PackageApplied *pa )
{
if(stillMoveHero.get() == DURING_MOVE)
stillMoveHero.setn(CONTINUE_MOVE);
}
CStatusBar::CStatusBar(int x, int y, std::string name, int maxw)
{
bg=BitmapHandler::loadBitmap(name);

View File

@ -559,7 +559,6 @@ public:
CCallback * cb; //to communicate with engine
const BattleAction *curAction; //during the battle - action currently performed by active stack (or NULL)
bool stillMoveHero; //during hero movement - setting this flag to false will stop movement
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
std::list<IShowActivable *> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
@ -603,6 +602,7 @@ public:
void yourTurn();
void availableCreaturesChanged(const CGTownInstance *town);
void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
void requestRealized(PackageApplied *pa);
void serialize(COSer<CSaveFile> &h, const int version); //saving
void serialize(CISer<CLoadFile> &h, const int version); //loading
@ -638,7 +638,7 @@ public:
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);
void showYesNoDialog(const std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
bool moveHero(const CGHeroInstance *h, CPath * path);
bool moveHero(const CGHeroInstance *h, CPath path);
CPlayerInterface(int Player, int serial);//c-tor
~CPlayerInterface();//d-tor

View File

@ -32,8 +32,6 @@
*
*/
CSharedCond<std::set<CPack*> > mess(new std::set<CPack*>);
void SetResources::applyCl( CClient *cl )
{
cl->playerint[player]->receivedResource(-1,-1);
@ -168,15 +166,6 @@ void TryMoveHero::applyCl( CClient *cl )
i->second->heroMoved(hmd);
}
}
//add info for callback
if(result<2)
{
mess.mx->lock();
mess.res->insert(new TryMoveHero(*this));
mess.mx->unlock();
mess.cv->notify_all();
}
}
void SetGarrisons::applyCl( CClient *cl )

View File

@ -670,8 +670,12 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentMoraleModifie
//various morale bonuses (from buildings, artifacts, etc)
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
{
if(i->type == HeroBonus::MORALE || i->type == HeroBonus::MORALE_AND_LUCK)
{
ret.push_back(std::make_pair(i->val, i->description));
}
}
//leadership
if(getSecSkillLevel(6))
@ -2223,24 +2227,259 @@ void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
activated(h);
}
void CGEvent::endBattle( BattleResult *result ) const
void CGEvent::endBattle( const CGHeroInstance *h, BattleResult *result ) const
{
if(result->winner)
return;
//give
giveContents(h,true);
}
void CGEvent::activated( const CGHeroInstance * h ) const
{
if(army)
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text << message;
cb->showInfoDialog(&iw);
if(guarders)
cb->startBattleI(h->id,guarders,pos,boost::bind(&CGEvent::endBattle,this,_1));
cb->startBattleI(h->id,army,pos,boost::bind(&CGEvent::endBattle,this,h,_1));
}
else
{
giveContents(h,false);
}
}
void CGEvent::giveContents( const CGHeroInstance *h, bool afterBattle ) const
{
InfoWindow iw;
iw.player = h->getOwner();
bool changesPrimSkill = false;
for (int i = 0; i < primskills.size(); i++)
{
if(primskills[i])
{
changesPrimSkill = true;
break;
}
}
if(gainedExp || changesPrimSkill || abilities.size())
{
getText(iw,afterBattle,175,h);
if(gainedExp)
iw.components.push_back(Component(Component::EXPERIENCE,0,gainedExp,0));
for(int i=0; i<primskills.size(); i++)
if(primskills[i])
iw.components.push_back(Component(Component::PRIM_SKILL,i,primskills[i],0));
for(int i=0; i<abilities.size(); i++)
iw.components.push_back(Component(Component::SEC_SKILL,abilities[i],abilityLevels[i],0));
cb->showInfoDialog(&iw);
//give exp
if(gainedExp)
cb->changePrimSkill(h->id,5,gainedExp,false);
//give prim skills
for(int i=0; i<primskills.size(); i++)
if(primskills[i])
cb->changePrimSkill(h->id,i,primskills[i],false);
//give sec skills
for(int i=0; i<abilities.size(); i++)
{
int curLev = h->getSecSkillLevel(abilities[i]);
if(curLev && curLev < abilityLevels[i]
|| h->secSkills.size() < SKILL_PER_HERO )
{
cb->changeSecSkill(h->id,abilities[i],abilityLevels[i],true);
}
}
}
if(manaDiff)
{
getText(iw,afterBattle,luckDiff,176,177,h);
iw.components.push_back(Component(Component::PRIM_SKILL,5,manaDiff,0));
cb->showInfoDialog(&iw);
cb->setManaPoints(h->id, h->mana + manaDiff);
}
if(moraleDiff)
{
getText(iw,afterBattle,luckDiff,178,179,h);
iw.components.push_back(Component(Component::MORALE,0,moraleDiff,0));
cb->showInfoDialog(&iw);
GiveBonus gb;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::MORALE,HeroBonus::OBJECT,moraleDiff,id,"");
gb.hid = h->id;
cb->giveHeroBonus(&gb);
}
if(luckDiff)
{
getText(iw,afterBattle,luckDiff,180,181,h);
iw.components.push_back(Component(Component::LUCK,0,luckDiff,0));
cb->showInfoDialog(&iw);
GiveBonus gb;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::LUCK,HeroBonus::OBJECT,luckDiff,id,"");
gb.hid = h->id;
cb->giveHeroBonus(&gb);
}
iw.components.clear();
iw.text.clear();
for(int i=0; i<resources.size(); i++)
{
if(resources[i] < 0)
iw.components.push_back(Component(Component::RESOURCE,i,resources[i],0));
}
if(iw.components.size())
{
getText(iw,afterBattle,182,h);
cb->showInfoDialog(&iw);
}
iw.components.clear();
iw.text.clear();
for(int i=0; i<resources.size(); i++)
{
if(resources[i] > 0)
iw.components.push_back(Component(Component::RESOURCE,i,resources[i],0));
}
if(iw.components.size())
{
getText(iw,afterBattle,183,h);
cb->showInfoDialog(&iw);
}
iw.components.clear();
for(int i=0; i<artifacts.size(); i++)
{
iw.components.push_back(Component(Component::ARTIFACT,artifacts[i],0,0));
}
if(iw.components.size())
{
cb->showInfoDialog(&iw);
}
for(int i=0; i<resources.size(); i++)
if(resources[i])
cb->giveResource(h->getOwner(),i,resources[i]);
for(int i=0; i<artifacts.size(); i++)
cb->giveHeroArtifact(artifacts[i],h->id,-2);
//show dialog with given creatures
iw.components.clear();
iw.text.clear();
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = creatures.slots.begin(); i != creatures.slots.end(); i++)
{
iw.components.push_back(Component(Component::CREATURE,i->second.first,i->second.second,0));
}
if(iw.components.size())
{
if(afterBattle)
{
if(iw.components.front().val == 1)
{
iw.text.addTxt(MetaString::ADVOB_TXT,185);//A %s joins %s's army.
iw.text.replacements.push_back(VLC->creh->creatures[iw.components.front().subtype].nameSing);
}
else
{
iw.text.addTxt(MetaString::ADVOB_TXT,186);//%s join %s's army.
iw.text.replacements.push_back(VLC->creh->creatures[iw.components.front().subtype].namePl);
}
iw.text.replacements.push_back(h->name);
}
else
{
iw.text << message;
afterBattle = true;
}
cb->showInfoDialog(&iw);
}
//check if creatures can be moved to hero army
CCreatureSet heroArmy = h->army;
CCreatureSet ourArmy = creatures;
while(ourArmy)
{
int slot = heroArmy.getSlotFor(ourArmy.slots.begin()->second.first);
if(slot < 0)
break;
heroArmy.slots[slot].first = ourArmy.slots.begin()->second.first;
heroArmy.slots[slot].second += ourArmy.slots.begin()->second.second;
ourArmy.slots.erase(ourArmy.slots.begin());
}
if(!ourArmy) //all creatures can be moved to hero army - do that
{
SetGarrisons sg;
sg.garrs[h->id] = heroArmy;
cb->sendAndApply(&sg);
}
else //show garrison window and let player pick creatures
{
SetGarrisons sg;
sg.garrs[id] = creatures;
cb->sendAndApply(&sg);
if(removeAfterVisit)
cb->showGarrisonDialog(id,h->id,boost::bind(&IGameCallback::removeObject,cb,id));
else
cb->showGarrisonDialog(id,h->id,0);
return;
}
if(!afterBattle)
{
iw.text << message;
cb->showInfoDialog(&iw);
}
if(removeAfterVisit)
cb->removeObject(id);
}
void CGEvent::getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const
{
if(afterBattle)
{
iw.text.addTxt(MetaString::ADVOB_TXT,text);//%s has lost treasure.
iw.text.replacements.push_back(h->name);
}
else
{
iw.text << message;
afterBattle = true;
}
}
void CGEvent::getText( InfoWindow &iw, bool &afterBattle, int val, int positive, int negative, const CGHeroInstance * h ) const
{
iw.components.clear();
iw.text.clear();
if(afterBattle)
{
iw.text.addTxt(MetaString::ADVOB_TXT,val < 0 ? negative : positive); //%s's luck takes a turn for the worse / %s's luck increases
iw.text.replacements.push_back(h->name);
}
else
{
iw.text << message;
afterBattle = true;
}
}
void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
{
InfoWindow iw;

View File

@ -41,6 +41,7 @@ class CArtifact;
class CGDefInfo;
class CSpecObjInfo;
struct TerrainTile;
struct InfoWindow;
class DLL_EXPORT CCastleEvent
{
@ -375,10 +376,9 @@ public:
}
};
class DLL_EXPORT CGEvent : public CGObjectInstance //event objects
class DLL_EXPORT CGEvent : public CArmedInstance //event objects
{
public:
CCreatureSet guarders;
std::string message;
ui32 gainedExp;
si32 manaDiff; //amount of gained / lost mana
@ -394,18 +394,23 @@ public:
ui8 availableFor; //players whom this event is available for
ui8 computerActivate; //true if computre player can activate this event
ui8 humanActivate; //true if human player can activate this event
ui8 removeAfterVisit; //true if event is removed after occurring
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
h & guarders & message & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills
h & static_cast<CArmedInstance&>(*this);
h & message & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills
& abilities & abilityLevels & artifacts & spells & creatures & availableFor
& computerActivate & humanActivate;
}
void activated(const CGHeroInstance * h) const;
void onHeroVisit(const CGHeroInstance * h) const;
void endBattle(BattleResult *result) const;
void endBattle(const CGHeroInstance *h, BattleResult *result) const;
void giveContents(const CGHeroInstance *h, bool afterBattle) const;
void getText( InfoWindow &iw, bool &afterBattle, int val, int positive, int negative, const CGHeroInstance * h ) const;
void getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const;
};
class DLL_EXPORT CGCreature : public CArmedInstance //creatures on map

View File

@ -101,6 +101,7 @@ struct MetaString : public CPack //2001 helper for object scrips
strings.clear();
texts.clear();
message.clear();
replacements.clear();
}
MetaString(){type = 2001;};

View File

@ -10,6 +10,8 @@
#include "../hch/CSpellHandler.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
@ -166,7 +168,22 @@ DLL_EXPORT void GiveBonus::applyGs( CGameState *gs )
{
CGHeroInstance *h = gs->getHero(hid);
h->bonuses.push_back(bonus);
h->bonuses.back().description = toString(bdescr);
std::string &descr = h->bonuses.back().description;
if(!bdescr.texts.size()
&& bonus.source == HeroBonus::OBJECT
&& (bonus.type == HeroBonus::LUCK || bonus.type == HeroBonus::MORALE || bonus.type == HeroBonus::MORALE_AND_LUCK)
&& gs->map->objects[bonus.id]->ID == 26) //it's morale/luck bonus from an event without description
{
descr = VLC->generaltexth->arraytxt[bonus.val > 0 ? 110 : 109]; //+/-%d Temporary until next battle"
boost::replace_first(descr,"%d",boost::lexical_cast<std::string>(std::abs(bonus.val)));
}
else
{
descr = toString(bdescr);
}
}
DLL_EXPORT void ChangeObjPos::applyGs( CGameState *gs )

10
map.cpp
View File

@ -1325,6 +1325,10 @@ void Mapa::readDefInfo( unsigned char * bufor, int &i)
}
else
vinya->visitDir = 0xff;
if(vinya->id == 26)
std::memset(vinya->blockMap,255,6);
defy.push_back(vinya); // add this def to the vector
}
}
@ -1366,7 +1370,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
}
if(bufor[i++])
{
evnt->guarders = readCreatureSet(bufor,i,7,(version>RoE));
evnt->army = readCreatureSet(bufor,i,7,(version>RoE));
}
i+=4;
}
@ -1415,7 +1419,9 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
i+=8;
evnt->availableFor = readNormalNr(bufor,i, 1); ++i;
evnt->computerActivate = readNormalNr(bufor,i, 1); ++i;
evnt->humanActivate = readNormalNr(bufor,i, 1); ++i;
evnt->removeAfterVisit = readNormalNr(bufor,i, 1); ++i;
evnt->humanActivate = true;
i+=4;
break;
}

View File

@ -409,8 +409,6 @@ askInterfaceForMove:
//end battle, remove all info, free memory
giveExp(*battleResult.data);
sendAndApply(battleResult.data);
if(cb)
cb(battleResult.data);
//if one hero has lost we will erase him
if(battleResult.data->winner!=0 && hero1)
@ -430,6 +428,9 @@ askInterfaceForMove:
if(battleResult.data->exp[1] && hero2)
changePrimSkill(hero2->id,4,battleResult.data->exp[1]);
if(cb)
cb(battleResult.data);
delete battleResult.data;
}