1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-29 00:41:38 +02:00

Large rewrite of adventure map objects:

- replaced CDefObjInfo with ObjectTemplate class
- ObjectTempate is a direct member of objects instead of pointer with
shared ownership across CMap, handler and game objects
- simplified handling of objects that can change appearance (e.g. towns)
- all object queries regarding object appearance/blockmaps use h3m pos
instead of relative positions
- removed need of modhandler::reload
- cleanup of some old code
This commit is contained in:
Ivan Savenko
2014-01-02 23:48:38 +00:00
parent 2b9e074d54
commit 2c4c964a45
27 changed files with 729 additions and 672 deletions

View File

@ -343,36 +343,23 @@ static CGObjectInstance * createObject(Obj id, int subid, int3 pos, PlayerColor
switch(id)
{
case Obj::HERO:
{
auto nobj = new CGHeroInstance();
nobj->pos = pos;
nobj->tempOwner = owner;
nobj->subID = subid;
//nobj->initHero(ran);
return nobj;
}
nobj = new CGHeroInstance();
nobj->appearance = VLC->dobjinfo->pickCandidates(id, VLC->heroh->heroes[subid]->heroClass->id).front();
break;
case Obj::TOWN:
nobj = new CGTownInstance;
break;
default: //rest of objects
nobj = new CGObjectInstance;
nobj->defInfo = id.toDefObjInfo()[subid];
break;
}
nobj->ID = id;
nobj->subID = subid;
if(!nobj->defInfo)
logGlobal->warnStream() <<"No def declaration for " <<id <<" "<<subid;
nobj->pos = pos;
//nobj->state = nullptr;//new CLuaObjectScript();
nobj->tempOwner = owner;
nobj->defInfo->id = id;
nobj->defInfo->subid = subid;
if (id != Obj::HERO)
nobj->appearance = VLC->dobjinfo->pickCandidates(id, subid).front();
//assigning defhandler
if(nobj->ID==Obj::HERO || nobj->ID==Obj::TOWN)
return nobj;
nobj->defInfo = id.toDefObjInfo()[subid];
return nobj;
}
@ -641,14 +628,11 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
{
if(cur->ID==Obj::TOWN) //town - set def
{
const TerrainTile &tile = map->getTile(cur->pos);
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
t->town = VLC->townh->factions[t->subID]->town;
if(t->hasCapitol())
t->defInfo = VLC->dobjinfo->capitols[t->subID];
else if(t->hasFort())
t->defInfo = VLC->dobjinfo->gobjs[Obj::TOWN][t->subID];
else
t->defInfo = VLC->dobjinfo->villages[t->subID];
t->appearance = VLC->dobjinfo->pickCandidates(Obj::TOWN, t->subID, tile.terType).front();
t->updateAppearance();
}
return;
}
@ -666,33 +650,33 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
}
else if(ran.first==Obj::TOWN)//special code for town
{
const TerrainTile &tile = map->getTile(cur->pos);
CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
if(!t) {logGlobal->warnStream()<<"Wrong random town at "<<cur->pos; return;}
cur->ID = ran.first;
cur->subID = ran.second;
//FIXME: copy-pasted from above
t->town = VLC->townh->factions[t->subID]->town;
if(t->hasCapitol())
t->defInfo = VLC->dobjinfo->capitols[t->subID];
else if(t->hasFort())
t->defInfo = VLC->dobjinfo->gobjs[Obj::TOWN][t->subID];
else
t->defInfo = VLC->dobjinfo->villages[t->subID];
t->appearance = VLC->dobjinfo->pickCandidates(Obj::TOWN,t->subID, tile.terType).front();
t->updateAppearance();
t->randomizeArmy(t->subID);
map->towns.push_back(t);
return;
}
else
{
if (ran.first != cur->appearance.id ||
ran.second != cur->appearance.subid)
{
const TerrainTile &tile = map->getTile(cur->pos);
cur->appearance = VLC->dobjinfo->pickCandidates(Obj(ran.first),ran.second, tile.terType).front();
}
}
//we have to replace normal random object
cur->ID = ran.first;
cur->subID = ran.second;
map->removeBlockVisTiles(cur); //recalculate blockvis tiles - picked object might have different than random placeholder
map->customDefs.push_back(cur->defInfo = ran.first.toDefObjInfo()[ran.second]);
if(!cur->defInfo)
{
logGlobal->errorStream()<<"*BIG* WARNING: Missing def declaration for "<<cur->ID<<" "<<cur->subID;
return;
}
map->removeBlockVisTiles(cur, true); //recalculate blockvis tiles - picked object might have different than random placeholder
map->addBlockVisTiles(cur);
}
@ -1189,7 +1173,6 @@ void CGameState::placeStartingHero(PlayerColor playerColor, HeroTypeID heroTypeI
townPos.x += 1;
CGHeroInstance * hero = static_cast<CGHeroInstance*>(createObject(Obj::HERO, heroTypeId.getNum(), townPos, playerColor));
hero->initHeroDefInfo();
map->getEditManager()->insertObject(hero, townPos);
}
@ -2205,14 +2188,15 @@ bool CGameState::isVisible( const CGObjectInstance *obj, boost::optional<PlayerC
if(*player == PlayerColor::NEUTRAL) //-> TODO ??? needed?
return false;
//object is visible when at least one blocked tile is visible
for(int fx=0; fx<8; ++fx)
for(int fy=0; fy < obj->getHeight(); ++fy)
{
for(int fy=0; fy<6; ++fy)
for(int fx=0; fx < obj->getWidth(); ++fx)
{
int3 pos = obj->pos + int3(fx-7,fy-5,0);
if(map->isInTheMap(pos)
&& !((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)
&& isVisible(pos, *player) )
int3 pos = obj->pos + int3(-fx, -fy, 0);
if ( map->isInTheMap(pos) &&
obj->coveringAt(pos.x, pos.y) &&
isVisible(pos, *player))
return true;
}
}
@ -2232,39 +2216,10 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
if(!vstd::contains(pom->blockingObjects, pom->visitableObjects[b])) //this visitable object is not blocking, ignore
continue;
CGDefInfo * di = pom->visitableObjects[b]->defInfo;
if( (dst.x == src.x-1 && dst.y == src.y-1) && !(di->visitDir & (1<<4)) )
{
const CGObjectInstance * obj = pom->visitableObjects[b];
if (!obj->appearance.isVisitableFrom(src.x - dst.x, src.y - dst.y))
return false;
}
if( (dst.x == src.x && dst.y == src.y-1) && !(di->visitDir & (1<<5)) )
{
return false;
}
if( (dst.x == src.x+1 && dst.y == src.y-1) && !(di->visitDir & (1<<6)) )
{
return false;
}
if( (dst.x == src.x+1 && dst.y == src.y) && !(di->visitDir & (1<<7)) )
{
return false;
}
if( (dst.x == src.x+1 && dst.y == src.y+1) && !(di->visitDir & (1<<0)) )
{
return false;
}
if( (dst.x == src.x && dst.y == src.y+1) && !(di->visitDir & (1<<1)) )
{
return false;
}
if( (dst.x == src.x-1 && dst.y == src.y+1) && !(di->visitDir & (1<<2)) )
{
return false;
}
if( (dst.x == src.x-1 && dst.y == src.y) && !(di->visitDir & (1<<3)) )
{
return false;
}
}
return true;
}