Subversion Repositories eoserv

Compare Revisions

Ignore whitespace Rev 394 → Rev 395

/trunk/data/shops.ini
10,13 → 10,21
# 3.trade = 2,100,50, 3,200,100
# 3.craft = 4,2,5,3,1,0,0,0,0
#
# NPC #3's shop will be called "Potion Shop".
# Shop #3 shop will be called "Potion Shop".
# It will sell "item #2"s for 100g (and buy them for 50g),
# and sell "item #3"s for 200g (and buy them for 100g).
# You can craft "item #4" with 5x "item #2" and 1x "item #3".
#
# An NPC must be given the vendor id 3 in the pub files to access this shop.
#
# The server will warn you if a sell price is higher than a buy price.
#
# It is recommended to create a new file and change the config to point at it
# rather than editing this file.
#
 
## Version (number)
# Specifies the version of the configuration file (Default: 1)
# Version 1 specifies shops for individual NPC ids
# Version 2 specifies shops for NPC vendor ids
Version = 2
/trunk/data/skills.ini
9,10 → 9,18
# 2.name = Anundo Skill Master
# 2.learn = 3,2000,5,2,7,0,0,0,0,12,4,0,0,0
#
# NPC #2's spell shop will be called "Anundo Skill Master"
# Skill Master #2's spell shop will be called "Anundo Skill Master"
# Spell ID #3 will be sold for 2000 gold, require level 5, class #2
# and spell #7 to be learned, as well as 12 int and 4 wis.
#
# An NPC must be given the vendor id 2 in the pub files to access this skill set.
#
# It is recommended to create a new file and change the config to point at it
# rather than editing this file.
#
 
## Version (number)
# Specifies the version of the configuration file (Default: 1)
# Version 1 specifies skills for individual NPC ids
# Version 2 specifies skills for NPC vendor ids
Version = 2
/trunk/data/home.ini
3,7 → 3,7
# Spawn Point Format:
# name.name = name
# name.location = map, x,y
# name.innkeeper = npcid (optional)
# name.innkeeper = vendor_id (optional)
# name.question[1-3] = question (optional)
# name.answer[1-3] = snswer (optional)
#
18,6 → 18,14
# Creates a spawn point at 3,4 on map 1 called Wanderer for vagabonds.
# Questions and answers are only needed if the innkeeper id is set.
#
# An innkeeper NPC must be given the vendor id specified to offer citizenship.
#
# It is recommended to create a new file and change the config to point at it
# rather than editing this file.
#
 
## Version (number)
# Specifies the version of the configuration file (Default: 1)
# Version 1 specifies innkeepers as individual NPC ids
# Version 2 specifies innkeepers as NPC vendor ids
Version = 2
/trunk/src/npc.cpp
114,165 → 114,208
}
}
 
this->shop_name = static_cast<std::string>(map->world->shops_config[util::to_string(this->id) + ".name"]);
Config::iterator shops = map->world->shops_config.find(util::to_string(this->id) + ".trade");
if (shops != map->world->shops_config.end())
short shop_vend_id;
 
if (int(map->world->shops_config["Version"]) < 2)
{
std::vector<std::string> parts = util::explode(',', static_cast<std::string>((*shops).second));
shop_vend_id = this->id;
}
else
{
shop_vend_id = this->Data().vendor_id;
}
 
if (parts.size() > 1)
if (this->Data().type == ENF::Type::Shop && shop_vend_id > 0)
{
this->shop_name = static_cast<std::string>(map->world->shops_config[util::to_string(shop_vend_id) + ".name"]);
Config::iterator shops = map->world->shops_config.find(util::to_string(shop_vend_id) + ".trade");
if (shops != map->world->shops_config.end())
{
if (parts.size() % 3 != 0)
std::vector<std::string> parts = util::explode(',', static_cast<std::string>((*shops).second));
 
if (parts.size() > 1)
{
Console::Wrn("skipping invalid trade shop data for NPC #%i", id);
return;
}
if (parts.size() % 3 != 0)
{
Console::Wrn("skipping invalid trade shop data for vendor #%i", shop_vend_id);
return;
}
 
this->shop_trade.resize(parts.size() / 3);
this->shop_trade.resize(parts.size() / 3);
 
for (std::size_t i = 0; i < parts.size(); i += 3)
{
NPC_Shop_Trade_Item *item(new NPC_Shop_Trade_Item);
item->id = util::to_int(parts[i]);
item->buy = util::to_int(parts[i+1]);
item->sell = util::to_int(parts[i+2]);
for (std::size_t i = 0; i < parts.size(); i += 3)
{
NPC_Shop_Trade_Item *item(new NPC_Shop_Trade_Item);
item->id = util::to_int(parts[i]);
item->buy = util::to_int(parts[i+1]);
item->sell = util::to_int(parts[i+2]);
 
if (item->buy != 0 && item->sell != 0 && item->sell > item->buy)
{
Console::Wrn("item #%i (NPC #%i) has a higher sell price than buy price.", item->id, id);
if (item->buy != 0 && item->sell != 0 && item->sell > item->buy)
{
Console::Wrn("item #%i (vendor #%i) has a higher sell price than buy price.", item->id, shop_vend_id);
}
 
this->shop_trade[i/3] = item;
}
 
this->shop_trade[i/3] = item;
}
}
}
 
shops = this->map->world->shops_config.find(util::to_string(this->id) + ".craft");
if (shops != this->map->world->shops_config.end())
{
std::vector<std::string> parts = util::explode(',', static_cast<std::string>((*shops).second));
 
if (parts.size() > 1)
shops = this->map->world->shops_config.find(util::to_string(shop_vend_id) + ".craft");
if (shops != this->map->world->shops_config.end())
{
if (parts.size() % 9 != 0)
{
Console::Wrn("skipping invalid craft shop data for NPC #%i", id);
return;
}
std::vector<std::string> parts = util::explode(',', static_cast<std::string>((*shops).second));
 
this->shop_craft.resize(parts.size() / 9);
 
for (std::size_t i = 0; i < parts.size(); i += 9)
if (parts.size() > 1)
{
NPC_Shop_Craft_Item *item = new NPC_Shop_Craft_Item;
std::vector<NPC_Shop_Craft_Ingredient *> ingredients;
ingredients.resize(4);
if (parts.size() % 9 != 0)
{
Console::Wrn("skipping invalid craft shop data for vendor #%i", shop_vend_id);
return;
}
 
item->id = util::to_int(parts[i]);
this->shop_craft.resize(parts.size() / 9);
 
for (int ii = 0; ii < 4; ++ii)
for (std::size_t i = 0; i < parts.size(); i += 9)
{
NPC_Shop_Craft_Ingredient *ingredient = new NPC_Shop_Craft_Ingredient;
ingredient->id = util::to_int(parts[i+1+ii*2]);
ingredient->amount = util::to_int(parts[i+2+ii*2]);
ingredients[ii] = ingredient;
}
NPC_Shop_Craft_Item *item = new NPC_Shop_Craft_Item;
std::vector<NPC_Shop_Craft_Ingredient *> ingredients;
ingredients.resize(4);
 
item->ingredients = ingredients;
item->id = util::to_int(parts[i]);
 
this->shop_craft[i/9] = item;
for (int ii = 0; ii < 4; ++ii)
{
NPC_Shop_Craft_Ingredient *ingredient = new NPC_Shop_Craft_Ingredient;
ingredient->id = util::to_int(parts[i+1+ii*2]);
ingredient->amount = util::to_int(parts[i+2+ii*2]);
ingredients[ii] = ingredient;
}
 
item->ingredients = ingredients;
 
this->shop_craft[i/9] = item;
}
}
}
}
 
this->skill_name = static_cast<std::string>(map->world->skills_config[util::to_string(this->id) + ".name"]);
Config::iterator skills = this->map->world->skills_config.find(util::to_string(this->id) + ".learn");
if (skills != this->map->world->skills_config.end())
short skills_vend_id;
 
if (int(map->world->skills_config["Version"]) < 2)
{
std::vector<std::string> parts = util::explode(',', static_cast<std::string>((*skills).second));
skills_vend_id = this->id;
}
else
{
skills_vend_id = this->Data().vendor_id;
}
 
if (parts.size() > 1)
if (this->Data().type == ENF::Type::Skills && skills_vend_id > 0)
{
this->skill_name = static_cast<std::string>(map->world->skills_config[util::to_string(skills_vend_id) + ".name"]);
Config::iterator skills = this->map->world->skills_config.find(util::to_string(skills_vend_id) + ".learn");
if (skills != this->map->world->skills_config.end())
{
if (parts.size() % 14 != 0)
std::vector<std::string> parts = util::explode(',', static_cast<std::string>((*skills).second));
 
if (parts.size() > 1)
{
Console::Err("WARNING: skipping invalid skill learn data for NPC #%i", id);
return;
}
if (parts.size() % 14 != 0)
{
Console::Err("WARNING: skipping invalid skill learn data for vendor #%i", skills_vend_id);
return;
}
 
this->skill_learn.resize(parts.size() / 14);
this->skill_learn.resize(parts.size() / 14);
 
for (std::size_t i = 0; i < parts.size(); i += 14)
{
NPC_Learn_Skill *skill = new NPC_Learn_Skill;
for (std::size_t i = 0; i < parts.size(); i += 14)
{
NPC_Learn_Skill *skill = new NPC_Learn_Skill;
 
skill->id = util::to_int(parts[i]);
skill->cost = util::to_int(parts[i+1]);
skill->levelreq = util::to_int(parts[i+2]);
skill->classreq = util::to_int(parts[i+3]);
skill->id = util::to_int(parts[i]);
skill->cost = util::to_int(parts[i+1]);
skill->levelreq = util::to_int(parts[i+2]);
skill->classreq = util::to_int(parts[i+3]);
 
skill->skillreq[0] = util::to_int(parts[i+4]);
skill->skillreq[1] = util::to_int(parts[i+5]);
skill->skillreq[2] = util::to_int(parts[i+6]);
skill->skillreq[3] = util::to_int(parts[i+7]);
skill->skillreq[0] = util::to_int(parts[i+4]);
skill->skillreq[1] = util::to_int(parts[i+5]);
skill->skillreq[2] = util::to_int(parts[i+6]);
skill->skillreq[3] = util::to_int(parts[i+7]);
 
skill->strreq = util::to_int(parts[i+8]);
skill->intreq = util::to_int(parts[i+9]);
skill->wisreq = util::to_int(parts[i+10]);
skill->agireq = util::to_int(parts[i+11]);
skill->conreq = util::to_int(parts[i+12]);
skill->chareq = util::to_int(parts[i+13]);
skill->strreq = util::to_int(parts[i+8]);
skill->intreq = util::to_int(parts[i+9]);
skill->wisreq = util::to_int(parts[i+10]);
skill->agireq = util::to_int(parts[i+11]);
skill->conreq = util::to_int(parts[i+12]);
skill->chareq = util::to_int(parts[i+13]);
 
this->skill_learn[i/14] = skill;
this->skill_learn[i/14] = skill;
}
}
}
}
 
this->citizenship = 0;
short home_vend_id;
 
restart_loop:
UTIL_FOREACH(this->map->world->home_config, hc)
if (int(map->world->home_config["Version"]) < 2)
{
std::vector<std::string> parts = util::explode('.', hc.first);
home_vend_id = this->id;
}
else
{
home_vend_id = this->Data().vendor_id;
}
 
if (parts.size() < 2)
{
continue;
}
this->citizenship = 0;
 
if (!this->citizenship && parts[1] == "innkeeper" && util::to_int(hc.second) == this->id)
if (this->Data().type == ENF::Type::Inn && home_vend_id > 0)
{
restart_loop:
UTIL_FOREACH(this->map->world->home_config, hc)
{
this->citizenship = new NPC_Citizenship;
this->citizenship->home = parts[0];
Home* home = this->map->world->GetHome(this->citizenship->home);
std::vector<std::string> parts = util::explode('.', hc.first);
 
if (home)
home->innkeeper_vend = this->Data().vendor_id;
else
Console::Wrn("NPC #%i's innkeeper set on non-existent home: %s", id, this->citizenship->home.c_str());
if (parts.size() < 2)
{
continue;
}
 
goto restart_loop;
}
else if (this->citizenship && this->citizenship->home == parts[0] && parts[1].substr(0, parts[1].length() - 1) == "question")
{
int index = parts[1][parts[1].length() - 1] - '1';
if (!this->citizenship && parts[1] == "innkeeper" && util::to_int(hc.second) == home_vend_id)
{
this->citizenship = new NPC_Citizenship;
this->citizenship->home = parts[0];
Home* home = this->map->world->GetHome(this->citizenship->home);
 
if (index < 0 || index >= 3)
if (home)
home->innkeeper_vend = this->Data().vendor_id;
else
Console::Wrn("Vendor #%i's innkeeper set on non-existent home: %s", home_vend_id, this->citizenship->home.c_str());
 
// Restart the loop so questions/answers specified before the innkeeper option will load
goto restart_loop;
}
else if (this->citizenship && this->citizenship->home == parts[0] && parts[1].substr(0, parts[1].length() - 1) == "question")
{
Console::Wrn("Exactly 3 questions must be specified for %s innkeeper NPC #%i", std::string(hc.second).c_str(), id);
int index = parts[1][parts[1].length() - 1] - '1';
 
if (index < 0 || index >= 3)
{
Console::Wrn("Exactly 3 questions must be specified for %s innkeeper vendor #%i", std::string(hc.second).c_str(), home_vend_id);
}
 
this->citizenship->questions[index] = static_cast<std::string>(hc.second);
}
else if (this->citizenship && this->citizenship->home == parts[0] && parts[1].substr(0, parts[1].length() - 1) == "answer")
{
int index = parts[1][parts[1].length() - 1] - '1';
 
this->citizenship->questions[index] = static_cast<std::string>(hc.second);
}
else if (this->citizenship && this->citizenship->home == parts[0] && parts[1].substr(0, parts[1].length() - 1) == "answer")
{
int index = parts[1][parts[1].length() - 1] - '1';
if (index < 0 || index >= 3)
{
Console::Wrn("Exactly 3 answers must be specified for %s innkeeper vendor #%i", std::string(hc.second).c_str(), home_vend_id);
}
 
if (index < 0 || index >= 3)
{
Console::Wrn("Exactly 3 answers must be specified for %s innkeeper NPC #%i", std::string(hc.second).c_str(), id);
this->citizenship->answers[index] = static_cast<std::string>(hc.second);
}
 
this->citizenship->answers[index] = static_cast<std::string>(hc.second);
}
}
}