Code:
bool Vocations::reload()
{
clear();
return loadFromXml();
}
static struct v {
const char* name;
int type;
}
vocation[] = {
{"id", LUA_TNUMBER},
{"name", LUA_TSTRING },
{"description", LUA_TSTRING },
{"needpremium", LUA_TNUMBER},
{"gaincap", LUA_TNUMBER},
{"gainhp", LUA_TNUMBER},
{"gainmana", LUA_TNUMBER},
{"gainhpticks", LUA_TNUMBER},
{"gainhpamount", LUA_TNUMBER},
{"gainmanaticks", LUA_TNUMBER},
{"gainmanaamount", LUA_TNUMBER},
{"manamultiplier", LUA_TNUMBER},
{"attackspeed", LUA_TNUMBER},
{"soulmax", LUA_TNUMBER},
{"gainsoulamount", LUA_TNUMBER},
{"gainsoulticks", LUA_TNUMBER},
{"fromvoc", LUA_TNUMBER},
{"attackable", LUA_TNUMBER},
{"formula", LUA_TTABLE},
{"skill", LUA_TTABLE},
{"absorb", LUA_TTABLE},
{"reflect", LUA_TTABLE},
{ NULL, 0 }
},
formula[] = {
{"melee", LUA_TNUMBER},
{"distance", LUA_TNUMBER},
{"wand", LUA_TNUMBER},
{"magic", LUA_TNUMBER},
{"healing", LUA_TNUMBER},
{"defense", LUA_TNUMBER},
{"magicDefense", LUA_TNUMBER},
{"armor", LUA_TNUMBER},
{ NULL, 0 }
},
skill[] = {
{"fist", LUA_TNUMBER},
{"fistBase", LUA_TNUMBER},
{"club", LUA_TNUMBER},
{"clubBase", LUA_TNUMBER},
{"sword", LUA_TNUMBER},
{"swordBase", LUA_TNUMBER},
{"axe", LUA_TNUMBER},
{"axeBase", LUA_TNUMBER},
{"dist", LUA_TNUMBER},
{"distBase", LUA_TNUMBER},
{"shield", LUA_TNUMBER},
{"shieldBase", LUA_TNUMBER},
{"fish", LUA_TNUMBER},
{"fishBase", LUA_TNUMBER},
{"experience", LUA_TNUMBER},
{ NULL, 0 }
},
absorb[] = {
{"percentAll", LUA_TNUMBER},
{"percentElements", LUA_TNUMBER},
{"percentMagic", LUA_TNUMBER},
{"percentEnergy", LUA_TNUMBER},
{"percentFire", LUA_TNUMBER},
{"percentPoison", LUA_TNUMBER},
{"percentIce", LUA_TNUMBER},
{"percentHoly", LUA_TNUMBER},
{"percentDeath", LUA_TNUMBER},
{"percentLifeDrain", LUA_TNUMBER},
{"percentManaDrain", LUA_TNUMBER},
{"percentDrown", LUA_TNUMBER},
{"percentPhysical", LUA_TNUMBER},
{"percentHealing", LUA_TNUMBER},
{"percentUndefined", LUA_TNUMBER},
{ NULL, 0 }
},
reflect[] = {
{"percentAll", LUA_TNUMBER},
{"percentElements", LUA_TNUMBER},
{"percentMagic", LUA_TNUMBER},
{"percentEnergy", LUA_TNUMBER},
{"percentFire", LUA_TNUMBER},
{"percentPoison", LUA_TNUMBER},
{"percentIce", LUA_TNUMBER},
{"percentHoly", LUA_TNUMBER},
{"percentDeath", LUA_TNUMBER},
{"percentLifeDrain", LUA_TNUMBER},
{"percentManaDrain", LUA_TNUMBER},
{"percentDrown", LUA_TNUMBER},
{"percentPhysical", LUA_TNUMBER},
{"percentHealing", LUA_TNUMBER},
{"percentUndefined", LUA_TNUMBER},
{"chanceAll", LUA_TNUMBER},
{"chanceElements", LUA_TNUMBER},
{"chanceMagic", LUA_TNUMBER},
{"chanceEnergy", LUA_TNUMBER},
{"chanceFire", LUA_TNUMBER},
{"chancePoison", LUA_TNUMBER},
{"chanceIce", LUA_TNUMBER},
{"chanceHoly", LUA_TNUMBER},
{"chanceDeath", LUA_TNUMBER},
{"chanceLifeDrain", LUA_TNUMBER},
{"chanceManaDrain", LUA_TNUMBER},
{"chanceDrown", LUA_TNUMBER},
{"chancePhysical", LUA_TNUMBER},
{"chanceHealing", LUA_TNUMBER},
{"chanceUndefined", LUA_TNUMBER},
{ NULL, 0 }
};
bool Vocations::loadFromXml()
{
lua_State *L = luaL_newstate();
std::string str;
int32_t id = 0;
if (!L) {
throw std::runtime_error("Failed to allocate memory in vocations");
}
luaL_openlibs(L);
if (luaL_dofile(L, "data/lua/vocations.lua")) {
std::cout << "[Error - Vocations] " << lua_tostring(L, -1) << std::endl;
lua_close(L);
return false;
}
lua_getglobal(L, "vocations");
for (int i = 1; ; i++) {
lua_rawgeti(L, -1, i);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
break;
}
//std::cout << i << std::endl;
luaL_checktype(L, -1, LUA_TTABLE);
//id = (int32_t)i;
Vocation* voc = new Vocation(id);
id++;
for (int fields = 0; vocation[fields].name != NULL; fields++) {
lua_getfield(L, -1, vocation[fields].name);
luaL_checktype(L, -1, vocation[fields].type);
str = vocation[fields].name;
//std::cout << str << std::endl;
if (lua_isnumber(L, -1)) {
if (str == "id") {
}
else if (str == "needpremium") {
voc->setNeedPremium((lua_tonumber(L, -1) != 0));
}
else if (str == "gaincap") {
voc->setGainCap((int32_t)lua_tonumber(L, -1));
}
else if (str == "gainhp") {
voc->setGain(GAIN_HEALTH, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainmana") {
voc->setGain(GAIN_MANA, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainhpticks") {
voc->setGainTicks(GAIN_HEALTH, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainhpamount") {
voc->setGainAmount(GAIN_HEALTH, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainmanaticks") {
voc->setGainTicks(GAIN_MANA, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainmanaamount") {
voc->setGainAmount(GAIN_MANA, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "manamultiplier") {
voc->setMultiplier(MULTIPLIER_MANA, (float)lua_tonumber(L, -1));
}
else if (str == "attackspeed") {
voc->setAttackSpeed((uint32_t)lua_tonumber(L, -1));
}
else if (str == "basespeed") {
voc->setBaseSpeed((uint32_t)lua_tonumber(L, -1));
}
else if (str == "soulmax") {
voc->setGain(GAIN_SOUL, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainsoulamount") {
voc->setGainAmount(GAIN_SOUL, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "gainsoulticks") {
voc->setGainTicks(GAIN_SOUL, (uint32_t)lua_tonumber(L, -1));
}
else if (str == "attackable") {
voc->setAttackable((lua_tonumber(L, -1) != 0));
}
else if (str == "fromvoc") {
voc->setFromVocation((int32_t)lua_tonumber(L, -1));
}
else if (str == "lessloss") {
voc->setLessLoss((int32_t)lua_tonumber(L, -1));
}
}
if (lua_isstring(L, -1)) {
if (str == "name") {
voc->setName(lua_tostring(L, -1));
}
else if (str == "description") {
voc->setDescription(lua_tostring(L, -1));
}
}
if (lua_istable(L, -1)) {
if (str == "formula") {
std::string formstr;
for (int n = 0; formula[n].name != NULL; n++) {
lua_getfield(L, -1, formula[n].name);
luaL_checktype(L, -1, formula[n].type);
formstr = formula[n].name;
switch (lua_type(L, -1)) {
case LUA_TNUMBER:
if (formstr == "melee") {
voc->setMultiplier(MULTIPLIER_MELEE, (float)lua_tonumber(L, -1));
}
else if (formstr == "distance") {
voc->setMultiplier(MULTIPLIER_DISTANCE, (float)lua_tonumber(L, -1));
}
else if (formstr == "wand") {
voc->setMultiplier(MULTIPLIER_WAND, (float)lua_tonumber(L, -1));
}
else if (formstr == "magic") {
voc->setMultiplier(MULTIPLIER_MAGIC, (float)lua_tonumber(L, -1));
}
else if (formstr == "healing") {
voc->setMultiplier(MULTIPLIER_HEALING, (float)lua_tonumber(L, -1));
}
else if (formstr == "defense") {
voc->setMultiplier(MULTIPLIER_DEFENSE, (float)lua_tonumber(L, -1));
}
else if (formstr == "magicDefense") {
voc->setMultiplier(MULTIPLIER_MAGICDEFENSE, (float)lua_tonumber(L, -1));
}
else if (formstr == "armor") {
voc->setMultiplier(MULTIPLIER_ARMOR, (float)lua_tonumber(L, -1));
}else{
std::cout << "[Error - Parsing Formula] (" << formstr << ") is not a valid skill." << std::endl;
}
break;
}
lua_pop(L, 1);
}
}
else if (str == "skill") {
std::string skillstr;
for (int x = 0; skill[x].name != NULL; x++) {
lua_getfield(L, -1, skill[x].name);
luaL_checktype(L, -1, skill[x].type);
skillstr = skill[x].name;
switch (lua_type(L, -1)) {
case LUA_TNUMBER:
if (skillstr == "fist") {
voc->setSkillMultiplier(SKILL_FIST, (float)lua_tonumber(L, -1));
}
else if(skillstr == "fistBase"){
voc->setSkillBase(SKILL_FIST, (uint32_t)lua_tonumber(L, -1));
}
else if (skillstr == "club") {
voc->setSkillMultiplier(SKILL_CLUB, (float)lua_tonumber(L, -1));
}
else if(skillstr == "clubBase"){
voc->setSkillBase(SKILL_CLUB, (uint32_t)lua_tonumber(L, -1));
}
else if (skillstr == "sword") {
voc->setSkillMultiplier(SKILL_SWORD, (float)lua_tonumber(L, -1));
}
else if(skillstr == "swordBase"){
voc->setSkillBase(SKILL_SWORD, (uint32_t)lua_tonumber(L, -1));
}
else if (skillstr == "axe") {
voc->setSkillMultiplier(SKILL_AXE, (float)lua_tonumber(L, -1));
}
else if(skillstr == "axeBase"){
voc->setSkillBase(SKILL_AXE, (uint32_t)lua_tonumber(L, -1));
}
else if (skillstr == "dist") {
voc->setSkillMultiplier(SKILL_DIST, (float)lua_tonumber(L, -1));
}
else if(skillstr == "distBase"){
voc->setSkillBase(SKILL_DIST, (uint32_t)lua_tonumber(L, -1));
}
else if (skillstr == "shield") {
voc->setSkillMultiplier(SKILL_SHIELD, (float)lua_tonumber(L, -1));
}
else if(skillstr == "shieldBase"){
voc->setSkillBase(SKILL_SHIELD, (uint32_t)lua_tonumber(L, -1));
}
else if (skillstr == "fish") {
voc->setSkillMultiplier(SKILL_FISH, (float)lua_tonumber(L, -1));
}
else if(skillstr == "fishBase"){
voc->setSkillBase(SKILL_FISH, (uint32_t)lua_tonumber(L, -1));
}
else if(skillstr == "experience"){
voc->setSkillMultiplier(SKILL__LEVEL, (float)lua_tonumber(L, -1));
}else{
std::cout << "[Error - Parsing Skills] (" << skillstr << ") is not a valid skill." << std::endl;
}
break;
}
lua_pop(L, 1);
}
}
else if (str == "absorb") {
std::string absorbstr;
int16_t intValue = 0;
for (int a = 0; absorb[a].name != NULL; a++) {
lua_getfield(L, -1, absorb[a].name);
luaL_checktype(L, -1, absorb[a].type);
absorbstr = absorb[a].name;
switch (lua_type(L, -1)) {
case LUA_TNUMBER:
if (absorbstr == "percentAll") {
intValue = (int16_t)lua_tonumber(L, -1);
for(int32_t i = COMBAT_FIRST; i <= COMBAT_LAST; i++){
voc->increaseAbsorb((CombatType_t)i, intValue);
}
}
else if(absorbstr == "percentElements"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_ENERGYDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_FIREDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_EARTHDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_ICEDAMAGE, intValue);
}
else if (absorbstr == "percentMagic") {
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_ENERGYDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_FIREDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_EARTHDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_ICEDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_HOLYDAMAGE, intValue);
voc->increaseAbsorb(COMBAT_DEATHDAMAGE, intValue);
}
else if(absorbstr == "percentEnergy"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_ENERGYDAMAGE, intValue);
}
else if (absorbstr == "percentFire") {
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_FIREDAMAGE, intValue);
}
else if(absorbstr == "percentPoison"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_EARTHDAMAGE, intValue);
}
else if (absorbstr == "percentIce") {
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_ICEDAMAGE, intValue);
}
else if(absorbstr == "percentHoly"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_HOLYDAMAGE, intValue);
}
else if (absorbstr == "percentDeath") {
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_DEATHDAMAGE, intValue);
}
else if(absorbstr == "percentLifeDrain"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_LIFEDRAIN, intValue);
}
else if (absorbstr == "percentManaDrain") {
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_MANADRAIN, intValue);
}
else if(absorbstr == "percentDrown"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_DROWNDAMAGE, intValue);
}
else if (absorbstr == "percentPhysical") {
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_PHYSICALDAMAGE, intValue);
}
else if(absorbstr == "percentHealing"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_HEALING, intValue);
}
else if(absorbstr == "percentUndefined"){
intValue = (int16_t)lua_tonumber(L, -1);
voc->increaseAbsorb(COMBAT_UNDEFINEDDAMAGE, intValue);
}else{
std::cout << "[Error - Parsing Absorb] (" << absorbstr << ") is not a valid skill." << std::endl;