#include "stdafx.h" #include "CLua.h" #include "CLuaHandler.h" #include "hch/CHeroHandler.h" #include "lua.h" #include "lualib.h" #include "lauxlib.h" #include "lobject.h" #include "lgc.h" #include "lapi.h" #include "CGameInfo.h" #include "CGameState.h" #include #include "hch/CObjectHandler.h" #include "hch/CTownHandler.h" #include "CCallback.h" #include "hch/CGeneralTextHandler.h" #include #include "CPlayerInterface.h" #include #include #include "hch/CDefObjInfoHandler.h" #pragma warning (disable : 4311) bool getGlobalFunc(lua_State * L, std::string fname) { unsigned int hash = lua_calchash(fname.c_str(), fname.size()); lua_pushhstring(L, hash, fname.c_str(), fname.size()); lua_gettable(L, LUA_GLOBALSINDEX); return lua_isfunction(L, -1); } CObjectScript::CObjectScript() { language = UNDEF; //std::cout << "Tworze obiekt objectscript "<ID)); lua_pushinteger(is, (int)os); if (lua_pcall (is, 1, 0, 0)) { lua_settop(is, 0); #ifndef __GNUC__ throw new std::exception(("Failed to call "+genFN("newObject",os->ID)+" function in lua script.").c_str()); #else throw std::exception(); #endif } lua_settop(is, 0); return; } void CLuaObjectScript::onHeroVisit(CGObjectInstance *os, int heroID) { findF(genFN("heroVisit",os->ID)); lua_pushinteger(is, (int)os); lua_pushinteger(is, heroID); if (lua_pcall (is, 2, 0, 0)) { lua_settop(is, 0); #ifndef __GNUC__ throw new std::exception(("Failed to call "+genFN("heroVisit",os->ID)+" function in lua script.").c_str()); #else throw std::exception(); #endif } lua_settop(is, 0); } std::string CLuaObjectScript::hoverText(CGObjectInstance *os) { findF(genFN("hoverText",os->ID)); lua_pushinteger(is, (int)os); if (lua_pcall (is, 1, 1, 0)) { lua_settop(is, 0); #ifndef __GNUC__ throw new std::exception(("Failed to call "+genFN("hoverText",os->ID)+" function in lua script.").c_str()); #else throw std::exception(); #endif } std::string ret = lua_tostring(is,1); lua_settop(is, 0); return ret; } std::string CCPPObjectScript::hoverText(CGObjectInstance *os) { return CGI->objh->objects[os->defInfo->id].name; } void CVisitableOPH::newObject(CGObjectInstance *os) { visitors.insert (std::pair >(os,std::set())); }; void CVisitableOPH::onHeroVisit(CGObjectInstance *os, int heroID) { if (visitors.find(os)!=visitors.end()) { if(visitors[os].find(heroID)==visitors[os].end()) { onNAHeroVisit(os,heroID, false); visitors[os].insert(heroID); } else { onNAHeroVisit(os,heroID, true); } } else { #ifndef __GNUC__ throw new std::exception("Skrypt nie zainicjalizowal instancji tego obiektu. :("); #else throw std::exception(); #endif } }; void CVisitableOPH::onNAHeroVisit(CGObjectInstance *os, int heroID, bool alreadyVisited) { int w=0, ot=0, vvv=1; switch(os->ID) { case 51: w=0; ot=80; break; case 23: w=1; ot=39; break; case 61: w=2; ot=100; break; case 32: w=3; ot=59; break; case 100: w=4; ot=143; vvv=1000; break; } if (!alreadyVisited) { switch (os->ID) { case 51: case 23: case 61: case 32: { cb->changePrimSkill(heroID,w,vvv); std::vector weko; weko.push_back(new SComponent(SComponent::primskill,w,vvv)); cb->showInfoDialog(cb->getHeroOwner(heroID),CGI->objh->advobtxt[ot],&weko); //for (int ii=0; iichangePrimSkill(heroID,w,vvv); std::vector weko; weko.push_back(new SComponent(SComponent::experience,0,vvv)); cb->showInfoDialog(cb->getHeroOwner(heroID),CGI->objh->advobtxt[ot],&weko); //for (int ii=0; iishowInfoDialog(cb->getHeroOwner(heroID),CGI->objh->advobtxt[ot],&std::vector()); } } std::vector CVisitableOPH::yourObjects() { std::vector ret(5); ret.push_back(51); ret.push_back(23); ret.push_back(61); ret.push_back(32); ret.push_back(100); return ret; } std::string CVisitableOPH::hoverText(CGObjectInstance *os) { std::string add; int pom; switch(os->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; default: #ifndef __GNUC__ throw new std::exception("Unsupported ID in CVisitableOPH::hoverText"); #else throw std::exception(); #endif } add = " " + CGI->objh->xtrainfo[pom] + " "; int heroID = cb->getSelectedHero(); if (heroID>=0) { add += ( (visitors[os].find(heroID) == visitors[os].end()) ? (CGI->generaltexth->allTexts[353]) //not visited : ( CGI->generaltexth->allTexts[352]) ); //visited } return CGI->objh->objects[os->defInfo->id].name + add; } void CVisitableOPW::onNAHeroVisit(CGObjectInstance *os, int heroID, bool alreadyVisited) { int mid; switch (os->ID) { case 55: mid = 92; break; case 112: mid = 170; break; case 109: mid = 164; break; } if (alreadyVisited) { if (os->ID!=112) mid++; else mid--; cb->showInfoDialog(cb->getHeroOwner(heroID),CGI->objh->advobtxt[mid],&std::vector()); //TODO: maybe we have memory leak with these windows } else { int type, sub, val; type = SComponent::resource; switch (os->ID) { case 55: if (rand()%2) { sub = 5; val = 5; } else { sub = 6; val = 500; } break; case 112: mid = 170; sub = (rand() % 5) + 1; val = (rand() % 4) + 3; break; case 109: mid = 164; sub = 6; if(cb->getDate(2)<2) val = 500; else val = 1000; } SComponent * com = new SComponent((SComponent::Etype)type,sub,val); std::vector weko; weko.push_back(com); cb->giveResource(cb->getHeroOwner(heroID),sub,val); cb->showInfoDialog(cb->getHeroOwner(heroID),CGI->objh->advobtxt[mid],&weko); visited[os] = true; } } void CVisitableOPW::newTurn () { if (cb->getDate(1)==1) { for (std::map::iterator i = visited.begin(); i != visited.end(); i++) { (*i).second = false; } } } void CVisitableOPW::newObject(CGObjectInstance *os) { visited.insert(std::pair(os,false)); } void CVisitableOPW::onHeroVisit(CGObjectInstance *os, int heroID) { if(visited[os]) onNAHeroVisit(os,heroID,true); else onNAHeroVisit(os,heroID,false); } std::vector CVisitableOPW::yourObjects() //returns IDs of objects which are handled by script { std::vector ret(3); ret.push_back(55); //mystical garden ret.push_back(112); //windmill ret.push_back(109); //water wheel return ret; } std::string CVisitableOPW::hoverText(CGObjectInstance *os) { return CGI->objh->objects[os->defInfo->id].name + " " + ( (visited[os]) ? (CGI->generaltexth->allTexts[352]) : (CGI->generaltexth->allTexts[353])) ; } void CMines::newObject(CGObjectInstance *os) { ourObjs.push_back(os); os->tempOwner = NEUTRAL_PLAYER; } void CMines::onHeroVisit(CGObjectInstance *os, int heroID) { int vv = 1; if (os->subID==0 || os->subID==2) vv++; else if (os->subID==6) vv = 1000; if (os->tempOwner == cb->getHeroOwner(heroID)) { //TODO: garrison } else { if (os->subID==7) return; //TODO: support for abandoned mine os->tempOwner = cb->getHeroOwner(heroID); SComponent * com = new SComponent(SComponent::resource,os->subID,vv); com->subtitle+=CGI->generaltexth->allTexts[3].substr(2,CGI->generaltexth->allTexts[3].length()-2); std::vector weko; weko.push_back(com); cb->showInfoDialog(cb->getHeroOwner(heroID),CGI->objh->mines[os->subID].second,&weko); } } std::vector CMines::yourObjects() { std::vector ret(1); ret.push_back(53); return ret; } std::string CMines::hoverText(CGObjectInstance *os) { if (os->tempOwner == NEUTRAL_PLAYER) return CGI->objh->mines[os->subID].first; else return CGI->objh->mines[os->subID].first + " " + CGI->generaltexth->arraytxt[23+os->tempOwner]; } void CMines::newTurn () { for (int i=0;itempOwner == NEUTRAL_PLAYER) continue; int vv = 1; if (ourObjs[i]->subID==0 || ourObjs[i]->subID==2) vv++; else if (ourObjs[i]->subID==6) vv = 1000; cb->giveResource(ourObjs[i]->tempOwner,ourObjs[i]->subID,vv); } } void CPickable::newObject(CGObjectInstance *os) { os->blockVisit = true; } void CPickable::onHeroVisit(CGObjectInstance *os, int heroID) { switch(os->ID) { case 5: { cb->giveHeroArtifact(os->subID,heroID,-1); //TODO: na pozycje break; } case 79: { //TODO: handle guards (when battles are finished) CResourceObjInfo * t2 = static_cast(os->info); int val; if(t2->amount) val = t2->amount; else { switch(os->subID) { case 6: val = 500 + (rand()%6)*100; break; case 0: case 2: val = 6 + (rand()%5); break; default: val = 3 + (rand()%3); break; } } if(t2->message.length()) cb->showInfoDialog(cb->getHeroOwner(heroID),t2->message,&std::vector()); SComponent ccc(SComponent::resource,os->subID,val); ccc.description = CGI->objh->advobtxt[113]; boost::algorithm::replace_first(ccc.description,"%s",CGI->objh->restypes[os->subID]); cb->giveResource(cb->getHeroOwner(heroID),os->subID,val); cb->showCompInfo(cb->getHeroOwner(heroID),&ccc); break; } case 101: { if (os->subID) break; //not OH3 treasure chest int wyn = rand()%100; if (wyn<32) { tempStore.push_back(new CSelectableComponent(SComponent::resource,6,1000)); tempStore.push_back(new CSelectableComponent(SComponent::experience,0,500)); }//1k/0.5k else if(wyn<64) { tempStore.push_back(new CSelectableComponent(SComponent::resource,6,1500)); tempStore.push_back(new CSelectableComponent(SComponent::experience,0,1000)); }//1.5k/1k else if(wyn<95) { tempStore.push_back(new CSelectableComponent(SComponent::resource,6,2000)); tempStore.push_back(new CSelectableComponent(SComponent::experience,0,1500)); }//2k/1.5k else { if (1/*TODO: backpack is full*/) { tempStore.push_back(new CSelectableComponent(SComponent::resource,6,1000)); tempStore.push_back(new CSelectableComponent(SComponent::experience,0,500)); } else { //TODO: give treasure artifact break; } }//random treasure artifact, or (if backapack is full) 1k/0.5k tempStore[1]->ID = heroID; player = cb->getHeroOwner(heroID); cb->showSelDialog(player,CGI->objh->advobtxt[146],&tempStore,this); break; } } CGI->mh->removeObject(os); } void CPickable::chosen(int which) { switch(tempStore[which]->type) { case SComponent::resource: cb->giveResource(player,tempStore[which]->subtype,tempStore[which]->val); break; case SComponent::experience: cb->changePrimSkill(tempStore[which]->ID,4,tempStore[which]->val); break; default: #ifndef __GNUC__ throw new std::exception("Unhandled choice"); #else throw std::exception(); #endif } for (int i=0;iID) { case 79: return CGI->objh->restypes[os->subID]; break; case 5: return CGI->arth->artifacts[os->subID].name; break; default: return CGI->objh->objects[os->defInfo->id].name; break; } } std::vector CPickable::yourObjects() //returns IDs of objects which are handled by script { std::vector ret(3); ret.push_back(79); //resource ret.push_back(5); //artifact ret.push_back(101); //treasure chest / commander stone return ret; } void CTownScript::onHeroVisit(CGObjectInstance *os, int heroID) { cb->heroVisitCastle(os,heroID); } void CTownScript::onHeroLeave(CGObjectInstance *os, int heroID) { cb->stopHeroVisitCastle(os,heroID); } std::string CTownScript::hoverText(CGObjectInstance *os) { CGTownInstance * n; if(n = dynamic_cast(os)) return n->name + ", " + n->town->name; else return ""; } std::vector CTownScript::yourObjects() //returns IDs of objects which are handled by script { std::vector ret(1); ret.push_back(98); //town return ret; } void CHeroScript::newObject(CGObjectInstance *os) { os->blockVisit = true; heroes.insert(std::pair(os->subID,os)); } void CHeroScript::onHeroVisit(CGObjectInstance *os, int heroID) { //TODO: check for allies if(static_cast(heroes[heroID])->tempOwner == static_cast(os)->tempOwner) //one of allied cases { //exchange } else { cb->startBattle( &(static_cast(heroes[heroID]))->army, &(static_cast(os))->army, os->pos, static_cast(heroes[heroID]), static_cast(os)); } } std::vector CHeroScript::yourObjects() //returns IDs of objects which are handled by script { std::vector ret(1); ret.push_back(34); //hero return ret; } std::string CHeroScript::hoverText(CGObjectInstance *os) { CGHeroInstance* h = static_cast(os); std::string ret = CGI->generaltexth->allTexts[15]; boost::algorithm::replace_first(ret,"%s",h->name); boost::algorithm::replace_first(ret,"%s",h->type->heroClass->name); return ret; } void CMonsterS::newObject(CGObjectInstance *os) { //os->blockVisit = true; switch(CGI->creh->creatures[os->subID].level) { case 1: ((CCreatureObjInfo*)os->info)->number = rand()%31+20; break; case 2: ((CCreatureObjInfo*)os->info)->number = rand()%16+15; break; case 3: ((CCreatureObjInfo*)os->info)->number = rand()%16+10; break; case 4: ((CCreatureObjInfo*)os->info)->number = rand()%11+10; break; case 5: ((CCreatureObjInfo*)os->info)->number = rand()%9+8; break; case 6: ((CCreatureObjInfo*)os->info)->number = rand()%8+5; break; case 7: ((CCreatureObjInfo*)os->info)->number = rand()%7+3; break; case 8: ((CCreatureObjInfo*)os->info)->number = rand()%4+2; break; case 9: ((CCreatureObjInfo*)os->info)->number = rand()%3+2; break; case 10: ((CCreatureObjInfo*)os->info)->number = rand()%3+1; break; } } std::string CMonsterS::hoverText(CGObjectInstance *os) { int pom = CCreature::getQuantityID(((CCreatureObjInfo*)os->info)->number); pom = 174 + 3*pom + 1; return CGI->generaltexth->arraytxt[pom] + " " + CGI->creh->creatures[os->subID].namePl; } void CMonsterS::onHeroVisit(CGObjectInstance *os, int heroID) { CCreatureSet set; //TODO: zrobic secik w sposob wyrafinowany set.slots[0] = std::pair(&CGI->creh->creatures[os->subID],((CCreatureObjInfo*)os->info)->number); cb->startBattle(heroID,&set,os->pos); } std::vector CMonsterS::yourObjects() //returns IDs of objects which are handled by script { std::vector ret(1); ret.push_back(54); //monster return ret; } void CCreatureGen::newObject(CGObjectInstance *os) { amount[os] = CGI->creh->creatures[CGI->objh->cregens[os->subID]].growth; } std::string CCreatureGen::hoverText(CGObjectInstance *os) { return CGI->objh->creGens[os->subID]; } void CCreatureGen::onHeroVisit(CGObjectInstance *os, int heroID) { } std::vector CCreatureGen::yourObjects() //returns IDs of objects which are handled by script { std::vector ret(1); ret.push_back(17); //cregen1 return ret; }