1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-01 00:45:26 +02:00

* fixed reading .defs

* new system for handling objects and their behaviors, most functionalities don't work now but will be restored soon
* more serialization code, savegame/loadgame bit closer :)
CHANGES IN PROJECT FILES:
* removed CLua.h and CLua.cpp (server)
* removed CScriptCallback.h and CScriptCallback.cpp (server)
* added IGameCallback.h header (lib)
This commit is contained in:
Michał W. Urbańczyk
2008-12-22 17:48:41 +00:00
parent 633b0007ba
commit ae48e73fe7
29 changed files with 1840 additions and 2691 deletions

View File

@ -7,15 +7,40 @@
#include "CDefObjInfoHandler.h"
#include "CHeroHandler.h"
#include "CSpellHandler.h"
#include <boost/bind.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/random/linear_congruential.hpp>
#include "CTownHandler.h"
#include "CArtHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/IGameCallback.h"
#include "../CGameState.h"
#include "../lib/NetPacks.h"
IGameCallback * IObjectInterface::cb = NULL;
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
extern CLodHandler * bitmaph;
extern boost::rand48 ran;
void IObjectInterface::onHeroVisit(const CGHeroInstance * h)
{};
void IObjectInterface::onHeroLeave(const CGHeroInstance * h)
{};
void IObjectInterface::newTurn ()
{};
IObjectInterface::~IObjectInterface()
{}
IObjectInterface::IObjectInterface()
{}
void IObjectInterface::initObj()
{}
void CObjectHandler::loadObjects()
{
VLC->objh = this;
@ -110,11 +135,6 @@ void CObjectHandler::loadObjects()
}
tlog5 << "\t\tDone loading objects!\n";
}
bool CGObjectInstance::isHero() const
{
return false;
}
int CGObjectInstance::getOwner() const
{
//if (state)
@ -123,6 +143,58 @@ int CGObjectInstance::getOwner() const
return tempOwner; //won't have owner
}
CGObjectInstance::CGObjectInstance(): animPhaseShift(rand()%0xff)
{
pos = int3(-1,-1,-1);
//std::cout << "Tworze obiekt "<<this<<std::endl;
//state = new CLuaObjectScript();
ID = subID = id = -1;
defInfo = NULL;
state = NULL;
info = NULL;
tempOwner = 254;
blockVisit = false;
}
CGObjectInstance::~CGObjectInstance()
{
//std::cout << "Usuwam obiekt "<<this<<std::endl;
//if (state)
// delete state;
//state=NULL;
}
CGObjectInstance::CGObjectInstance(const CGObjectInstance & right)
{
pos = right.pos;
ID = right.ID;
subID = right.subID;
id = right.id;
defInfo = right.defInfo;
info = right.info;
blockVisit = right.blockVisit;
//state = new CLuaObjectScript(right.state->);
//*state = *right.state;
//state = right.state;
tempOwner = right.tempOwner;
}
CGObjectInstance& CGObjectInstance::operator=(const CGObjectInstance & right)
{
pos = right.pos;
ID = right.ID;
subID = right.subID;
id = right.id;
defInfo = right.defInfo;
info = right.info;
blockVisit = right.blockVisit;
//state = new CLuaObjectScript();
//*state = *right.state;
tempOwner = right.tempOwner;
return *this;
}
const std::string & CGObjectInstance::getHoverText() const
{
return hoverName;
}
void CGObjectInstance::setOwner(int ow)
{
//if (state)
@ -177,11 +249,26 @@ bool CGObjectInstance::operator<(const CGObjectInstance & cmp) const //screen p
return false;
}
bool CGHeroInstance::isHero() const
void CGObjectInstance::initObj()
{
return true;
}
int lowestSpeed(const CGHeroInstance * chi)
{
if(!chi->army.slots.size())
{
tlog1 << "Error! Hero " << chi->id << " ("<<chi->name<<") has no army!\n";
return 20;
}
std::map<si32,std::pair<ui32,si32> >::const_iterator i = chi->army.slots.begin();
ui32 ret = VLC->creh->creatures[(*i++).second.first].speed;
for (;i!=chi->army.slots.end();i++)
{
ret = std::min(ret,VLC->creh->creatures[(*i).second.first].speed);
}
return ret;
}
unsigned int CGHeroInstance::getTileCost(const EterrainType & ttype, const Eroad & rdtype, const Eriver & rvtype) const
{
unsigned int ret = type->heroClass->terrCosts[ttype];
@ -202,9 +289,9 @@ unsigned int CGHeroInstance::getTileCost(const EterrainType & ttype, const Eroad
if(ret>150)
ret = 150;
break;
default:
//TODO do something nasty here throw maybe? or some def value asing
break;
default:
//TODO do something nasty here throw maybe? or some def value asing
break;
}
break;
case 2: //advanced
@ -219,17 +306,17 @@ unsigned int CGHeroInstance::getTileCost(const EterrainType & ttype, const Eroad
if(ret>125)
ret = 125;
break;
default:
//TODO look up
break;
default:
//TODO look up
break;
}
break;
case 3: //expert
ret = 100;
break;
default:
//TODO look up
break;
default:
//TODO look up
break;
}
//calculating road influence
@ -244,19 +331,19 @@ unsigned int CGHeroInstance::getTileCost(const EterrainType & ttype, const Eroad
case cobblestoneRoad:
ret*=0.5;
break;
default:
//TODO killllll me
break;
default:
//TODO killllll me
break;
}
return ret;
}
unsigned int CGHeroInstance::getLowestCreatureSpeed()
unsigned int CGHeroInstance::getLowestCreatureSpeed() const
{
unsigned int sl = 100;
for(size_t h=0; h < army.slots.size(); ++h)
{
if(VLC->creh->creatures[army.slots[h].first].speed<sl)
sl = VLC->creh->creatures[army.slots[h].first].speed;
if(VLC->creh->creatures[army.slots.find(h)->first].speed<sl)
sl = VLC->creh->creatures[army.slots.find(h)->first].speed;
}
return sl;
}
@ -332,22 +419,6 @@ int CGHeroInstance::getSecSkillLevel(const int & ID) const
return secSkills[i].second;
return 0;
}
int lowestSpeed(const CGHeroInstance * chi)
{
if(!chi->army.slots.size())
{
tlog1 << "Error! Hero " << chi->id << " ("<<chi->name<<") has no army!\n";
return 20;
}
std::map<si32,std::pair<ui32,si32> >::const_iterator i = chi->army.slots.begin();
int ret = VLC->creh->creatures[(*i++).second.first].speed;
for (;i!=chi->army.slots.end();i++)
{
ret = std::min(ret,VLC->creh->creatures[(*i).second.first].speed);
}
return ret;
}
int CGHeroInstance::maxMovePoints(bool onLand) const
{
int ret = 1270+70*lowestSpeed(this);
@ -456,6 +527,149 @@ int CGHeroInstance::getSpellSecLevel(int spell) const
return bestslvl;
}
CGHeroInstance::CGHeroInstance()
{
ID = 34;
tacticFormationEnabled = inTownGarrison = false;
mana = movement = portrait = level = -1;
isStanding = true;
moveDir = 4;
exp = 0xffffffff;
visitedTown = NULL;
type = NULL;
secSkills.push_back(std::make_pair(-1, -1));
}
void CGHeroInstance::initHero(int SUBID)
{
subID = SUBID;
initHero();
}
void CGHeroInstance::initHero()
{
if(!defInfo)
{
defInfo = new CGDefInfo();
defInfo->id = 34;
defInfo->subid = subID;
defInfo->printPriority = 0;
defInfo->visitDir = 0xff;
}
if(!type)
type = VLC->heroh->heroes[subID];
for(int i=0;i<6;i++)
{
defInfo->blockMap[i]=255;
defInfo->visitMap[i]=0;
}
defInfo->handler=NULL;
defInfo->blockMap[5] = 253;
defInfo->visitMap[5] = 2;
artifWorn[16] = 3;
if(type->heroType % 2 == 1) //it's a magical hero
{
artifWorn[17] = 0; //give him spellbook
}
if(portrait < 0 || portrait == 255)
portrait = subID;
if((!primSkills.size()) || (getPrimSkillLevel(0)<0))
{
primSkills.resize(4);
primSkills[0] = type->heroClass->initialAttack;
primSkills[1] = type->heroClass->initialDefence;
primSkills[2] = type->heroClass->initialPower;
primSkills[3] = type->heroClass->initialKnowledge;
}
if(secSkills.size() == 1 && secSkills[0] == std::pair<ui8,ui8>(-1, -1)) //set secondary skills to default
secSkills = type->secSkillsInit;
if(mana < 0)
mana = manaLimit();
if (!name.length())
name = type->name;
if (exp == 0xffffffff)
{
exp=40+ (ran()) % 50;
level = 1;
}
else
{
level = VLC->heroh->level(exp);
}
if (!army.slots.size()) //standard army//initial army
{
int pom, pom2=0;
for(int x=0;x<3;x++)
{
pom = (VLC->creh->nameToID[type->refTypeStack[x]]);
if(pom>=145 && pom<=149) //war machine
{
pom2++;
switch (pom)
{
case 145: //catapult
artifWorn[16] = 3;
break;
default:
artifWorn[9+CArtHandler::convertMachineID(pom,true)] = CArtHandler::convertMachineID(pom,true);
break;
}
continue;
}
army.slots[x-pom2].first = pom;
if((pom = (type->highStack[x]-type->lowStack[x])) > 0)
army.slots[x-pom2].second = (ran()%pom)+type->lowStack[x];
else
army.slots[x-pom2].second = +type->lowStack[x];
army.formation = false;
}
}
hoverName = VLC->generaltexth->allTexts[15];
boost::algorithm::replace_first(hoverName,"%s",name);
boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
}
CGHeroInstance::~CGHeroInstance()
{
}
bool CGHeroInstance::needsLastStack() const
{
return true;
}
void CGHeroInstance::onHeroVisit(const CGHeroInstance * h)
{
//TODO: check for allies
if(tempOwner == h->tempOwner) //our hero
{
//exchange
}
else
{
cb->startBattleI(
&h->army,
&army,
h->pos,
h,
this,
0);
}
}
const std::string & CGHeroInstance::getBiography() const
{
if (biography.length())
return biography;
else
return VLC->generaltexth->hTxts[subID].biography;
}
void CGHeroInstance::initObj()
{
cb->setBlockVis(id,true);
}
int CGTownInstance::getSightDistance() const //returns sight distance
{
return 10;
@ -556,143 +770,6 @@ CGTownInstance::CGTownInstance()
visitingHero = NULL;
}
CGObjectInstance::CGObjectInstance(): animPhaseShift(rand()%0xff)
{
pos = int3(-1,-1,-1);
//std::cout << "Tworze obiekt "<<this<<std::endl;
//state = new CLuaObjectScript();
ID = subID = id = -1;
defInfo = NULL;
state = NULL;
info = NULL;
tempOwner = 254;
blockVisit = false;
}
CGObjectInstance::~CGObjectInstance()
{
//std::cout << "Usuwam obiekt "<<this<<std::endl;
//if (state)
// delete state;
//state=NULL;
}
CGHeroInstance::CGHeroInstance()
{
ID = 34;
tacticFormationEnabled = inTownGarrison = false;
mana = movement = portrait = level = -1;
isStanding = true;
moveDir = 4;
exp = 0xffffffff;
visitedTown = NULL;
type = NULL;
secSkills.push_back(std::make_pair(-1, -1));
}
void CGHeroInstance::initHero(int SUBID)
{
subID = SUBID;
initHero();
}
void CGHeroInstance::initHero()
{
if(!defInfo)
{
defInfo = new CGDefInfo();
defInfo->id = 34;
defInfo->subid = subID;
defInfo->printPriority = 0;
defInfo->visitDir = 0xff;
}
if(!type)
type = VLC->heroh->heroes[subID];
for(int i=0;i<6;i++)
{
defInfo->blockMap[i]=255;
defInfo->visitMap[i]=0;
}
defInfo->handler=NULL;
defInfo->blockMap[5] = 253;
defInfo->visitMap[5] = 2;
artifWorn[16] = 3;
if(type->heroType % 2 == 1) //it's a magical hero
{
artifWorn[17] = 0; //give him spellbook
}
if(portrait < 0 || portrait == 255)
portrait = subID;
if((!primSkills.size()) || (getPrimSkillLevel(0)<0))
{
primSkills.resize(4);
primSkills[0] = type->heroClass->initialAttack;
primSkills[1] = type->heroClass->initialDefence;
primSkills[2] = type->heroClass->initialPower;
primSkills[3] = type->heroClass->initialKnowledge;
}
if(secSkills.size() == 1 && secSkills[0] == std::pair<ui8,ui8>(-1, -1)) //set secondary skills to default
secSkills = type->secSkillsInit;
if(mana < 0)
mana = manaLimit();
if (!name.length())
name = type->name;
if (exp == 0xffffffff)
{
exp=40+ (ran()) % 50;
level = 1;
}
else
{
level = VLC->heroh->level(exp);
}
if (!army.slots.size()) //standard army//initial army
{
int pom, pom2=0;
for(int x=0;x<3;x++)
{
pom = (VLC->creh->nameToID[type->refTypeStack[x]]);
if(pom>=145 && pom<=149) //war machine
{
pom2++;
switch (pom)
{
case 145: //catapult
artifWorn[16] = 3;
break;
default:
artifWorn[9+CArtHandler::convertMachineID(pom,true)] = CArtHandler::convertMachineID(pom,true);
break;
}
continue;
}
army.slots[x-pom2].first = pom;
if((pom = (type->highStack[x]-type->lowStack[x])) > 0)
army.slots[x-pom2].second = (ran()%pom)+type->lowStack[x];
else
army.slots[x-pom2].second = +type->lowStack[x];
army.formation = false;
}
}
}
CGHeroInstance::~CGHeroInstance()
{
}
bool CGHeroInstance::needsLastStack() const
{
return true;
}
const std::string & CGHeroInstance::getBiography()
{
if (biography.length())
return biography;
else
return VLC->generaltexth->hTxts[subID].biography;
}
CGTownInstance::~CGTownInstance()
{}
@ -712,31 +789,263 @@ bool CGTownInstance::needsLastStack() const
return true;
else return false;
}
CGObjectInstance::CGObjectInstance(const CGObjectInstance & right)
void CGTownInstance::onHeroVisit(const CGHeroInstance * h)
{
pos = right.pos;
ID = right.ID;
subID = right.subID;
id = right.id;
defInfo = right.defInfo;
info = right.info;
blockVisit = right.blockVisit;
//state = new CLuaObjectScript(right.state->);
//*state = *right.state;
//state = right.state;
tempOwner = right.tempOwner;
if(getOwner() != h->getOwner())
{
return;
}
cb->heroVisitCastle(id,h->id);
}
CGObjectInstance& CGObjectInstance::operator=(const CGObjectInstance & right)
void CGTownInstance::onHeroLeave(const CGHeroInstance * h)
{
pos = right.pos;
ID = right.ID;
subID = right.subID;
id = right.id;
defInfo = right.defInfo;
info = right.info;
blockVisit = right.blockVisit;
//state = new CLuaObjectScript();
//*state = *right.state;
tempOwner = right.tempOwner;
return *this;
cb->stopHeroVisitCastle(id,h->id);
}
void CGTownInstance::initObj()
{
MetaString ms;
ms << name << ", " << town->Name();
cb->setHoverName(id,&ms);
}
//std::vector<int> CVisitableOPH::yourObjects()
//{
// std::vector<int> ret;
// ret.push_back(51);//camp
// ret.push_back(23);//tower
// ret.push_back(61);//axis
// ret.push_back(32);//garden
// ret.push_back(100);//stone
// ret.push_back(102);//tree
// return ret;
//}
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h )
{
if(visitors.find(h->id)==visitors.end())
{
onNAHeroVisit(h->id, false);
if(ID != 102) //not tree
visitors.insert(h->id);
}
else
{
onNAHeroVisit(h->id, true);
}
}
void CGVisitableOPH::initObj()
{
if(ID==102)
ttype = ran()%3;
else
ttype = -1;
}
void CGVisitableOPH::treeSelected( int heroID, int resType, int resVal, int expVal, ui32 result )
{
if(result==0) //player agreed to give res for exp
{
cb->giveResource(cb->getOwner(heroID),resType,-resVal); //take resource
cb->changePrimSkill(heroID,4,expVal); //give exp
visitors.insert(heroID); //set state to visited
}
}
void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited)
{
int id=0, subid=0, ot=0, val=1;
switch(ID)
{
case 51:
subid=0;
ot=80;
break;
case 23:
subid=1;
ot=39;
break;
case 61:
subid=2;
ot=100;
break;
case 32:
subid=3;
ot=59;
break;
case 100:
id=5;
ot=143;
val=1000;
break;
case 102:
id = 5;
subid = 1;
ot = 146;
val = 1;
break;
}
if (!alreadyVisited)
{
switch (ID)
{
case 51:
case 23:
case 61:
case 32:
{
cb->changePrimSkill(heroID,subid,val);
InfoWindow iw;
iw.components.push_back(Component(0,subid,val,0));
iw.text << std::pair<ui8,ui32>(11,ot);
iw.player = cb->getOwner(heroID);
cb->showInfoDialog(&iw);
break;
}
case 100: //give exp
{
InfoWindow iw;
iw.components.push_back(Component(id,subid,val,0));
iw.player = cb->getOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,ot);
cb->showInfoDialog(&iw);
cb->changePrimSkill(heroID,4,val);
break;
}
case 102:
{
const CGHeroInstance *h = cb->getHero(heroID);
val = VLC->heroh->reqExp(h->level+val) - VLC->heroh->reqExp(h->level);
if(!ttype)
{
visitors.insert(heroID);
InfoWindow iw;
iw.components.push_back(Component(id,subid,1,0));
iw.player = cb->getOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,148);
cb->showInfoDialog(&iw);
cb->changePrimSkill(heroID,4,val);
break;
}
else
{
int res, resval;
if(ttype==1)
{
res = 6;
resval = 2000;
ot = 149;
}
else
{
res = 5;
resval = 10;
ot = 151;
}
if(cb->getResource(h->tempOwner,res) < resval) //not enough resources
{
ot++;
InfoWindow iw;
iw.player = h->tempOwner;
iw.text << std::pair<ui8,ui32>(11,ot);
cb->showInfoDialog(&iw);
return;
}
YesNoDialog sd;
sd.player = cb->getOwner(heroID);
sd.text << std::pair<ui8,ui32>(11,ot);
sd.components.push_back(Component(id,subid,val,0));
cb->showYesNoDialog(&sd,boost::bind(&CGVisitableOPH::treeSelected,this,heroID,res,resval,val,_1));
}
break;
}
}
}
else
{
ot++;
InfoWindow iw;
iw.player = cb->getOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,ot);
cb->showInfoDialog(&iw);
}
}
const std::string & CGVisitableOPH::getHoverText() const
{
int pom;
switch(ID)
{
case 51:
pom = 8;
break;
case 23:
pom = 7;
break;
case 61:
pom = 11;
break;
case 32:
pom = 4;
break;
case 100:
pom = 5;
break;
case 102:
pom = 18;
break;
default:
throw "Wrong CGVisitableOPH object ID!\n";
}
hoverName = VLC->objh->names[ID] + " " + VLC->objh->xtrainfo[pom];
const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
if(h)
{
hoverName += (vstd::contains(visitors,h->id))
? (VLC->generaltexth->allTexts[353]) //not visited
: ( VLC->generaltexth->allTexts[352]); //visited
}
return hoverName;
}
bool CArmedInstance::needsLastStack() const
{
return false;
}
void CGCreature::onHeroVisit( const CGHeroInstance * h )
{
army.slots[0].first = subID;
cb->startBattleI(h->id,army,pos,boost::bind(&CGCreature::endBattle,this,_1));
}
void CGCreature::endBattle( BattleResult *result )
{
if(result->winner==0)
{
cb->removeObject(id);
}
else
{
int killedAmount=0;
for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
if(i->first == subID)
killedAmount += i->second;
cb->setAmount(id, army.slots[0].second - killedAmount);
}
}
void CGCreature::initObj()
{
si32 &amount = army.slots[0].second;
CCreature &c = VLC->creh->creatures[subID];
if(!amount)
if(c.ammMax == c.ammMin)
amount = c.ammMax;
else
amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
}