Advertisement
Guest User

Untitled

a guest
Aug 12th, 2017
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 38.20 KB | None | 0 0
  1.  
  2. /* $Id: world.cpp 189 2010-04-27 06:18:38Z sausage $
  3.  * EOSERV is released under the zlib license.
  4.  * See LICENSE.txt for more info.
  5.  */
  6.  
  7. #include "world.hpp"
  8.  
  9. #include "character.hpp"
  10. #include "config.hpp"
  11. #include "console.hpp"
  12. #include "database.hpp"
  13. #include "eoclient.hpp"
  14. #include "eodata.hpp"
  15. #include "eoserver.hpp"
  16. #include "guild.hpp"
  17. #include "hash.hpp"
  18. #include "hook.hpp"
  19. #include "map.hpp"
  20. #include "npc.hpp"
  21. #include "packet.hpp"
  22. #include "party.hpp"
  23. #include "player.hpp"
  24. #include "quest.hpp"
  25. #include "scriptreg.hpp"
  26. #include "util.hpp"
  27.  
  28. void world_spawn_npcs(void *world_void)
  29. {
  30.     World *world(static_cast<World *>(world_void));
  31.  
  32.     double spawnrate = world->config["SpawnRate"];
  33.     double current_time = Timer::GetTime();
  34.     UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  35.     {
  36.         UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  37.         {
  38.             if ((!npc->alive && npc->dead_since + (double(npc->spawn_time) * spawnrate) < current_time)
  39.              && (!npc->Data()->child || (npc->parent && npc->parent->alive && world->config["RespawnBossChildren"])))
  40.             {
  41. #ifdef DEBUG
  42.                 Console::Dbg("Spawning NPC %i on map %i", npc->id, map->id);
  43. #endif // DEBUG
  44.                 npc->Spawn();
  45.             }
  46.         }
  47.     }
  48. }
  49.  
  50. void world_execute_weddings(void *world_void)
  51. {
  52.     World *world = static_cast<World *>(world_void);
  53.     double now = Timer::GetTime();
  54.  
  55.     UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  56.     {
  57.         UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  58.         {
  59.             if (npc->marriage && npc->marriage->request_accepted)
  60.             {
  61.                 if (!npc->marriage->partner[0] || !npc->marriage->partner[1])
  62.                 {
  63.                     npc->ShowDialog("Something went wrong. Stopping wedding");
  64.                     npc->marriage = 0;
  65.                     continue;
  66.                 }
  67.                 else if (!npc->marriage->partner[0]->online || !npc->marriage->partner[1]->online)
  68.                 {
  69.                     npc->ShowDialog("One of the wedding partners has exited the game. Stopping wedding");
  70.                     npc->marriage = 0;
  71.                     continue;
  72.                 }
  73.                 else if (npc->marriage->partner[0]->map != npc->map || npc->marriage->partner[1]->map != npc->map)
  74.                 {
  75.                     npc->ShowDialog("One of the wedding partners has left the map. Stopping wedding");
  76.                     npc->marriage = 0;
  77.                     continue;
  78.                 }
  79.                 else if ((npc->marriage->state == 5 && npc->marriage->partner_accepted[0]) || (npc->marriage->state == 8 && npc->marriage->partner_accepted[1]))
  80.                 {
  81.                     ++npc->marriage->state;
  82.                 }
  83.                 else if (npc->marriage->last_execution + (util::to_int(world->config["PriestDialogInterval"])) <= now)
  84.                 {
  85.                     switch (npc->marriage->state)
  86.                     {
  87.                         case 1: // Starting state
  88.                         {
  89.                             npc->ShowDialog("We are here at the invitation of " + util::ucfirst(npc->marriage->partner[0]->name) + " and " + util::ucfirst(npc->marriage->partner[1]->name) + ", who have come before us to join together in marriage.");
  90.                             ++npc->marriage->state;
  91.                         }
  92.                         break;
  93.  
  94.                         case 2: // second dialog
  95.                         {
  96.                             npc->ShowDialog("Their relationship is based on love, respect, and a determination to face the future together in health or sickness, in joy and sorrow.");
  97.                             ++npc->marriage->state;
  98.                         }
  99.                         break;
  100.  
  101.                         case 3: // Partner 1 question
  102.                         {
  103.                             npc->ShowDialog(util::ucfirst(npc->marriage->partner[0]->name) + ", do you take " + util::ucfirst(npc->marriage->partner[1]->name) + " to be your partner, and promise to love, comfort and stay together as long as you both shall live?");
  104.                             ++npc->marriage->state;
  105.                         }
  106.                         break;
  107.  
  108.                         case 4: // Partner 1 question box
  109.                         {
  110.                             PacketBuilder builder(PACKET_PRIEST, PACKET_REPLY);
  111.                             builder.AddChar(PRIEST_REQUEST);
  112.                             npc->marriage->partner[0]->player->client->SendBuilder(builder);
  113.                             ++npc->marriage->state;
  114.                         }
  115.                         break;
  116.  
  117.                         case 5: break; // Waiting for Partner 1 acceptance
  118.  
  119.                         case 6: // Recived agreement from partner 1
  120.                         {
  121.                             npc->ShowDialog(util::ucfirst(npc->marriage->partner[1]->name) + ", do you take " + util::ucfirst(npc->marriage->partner[0]->name) + " to be your partner, and promise to love, comfort and stay together as long as you both shall live?");
  122.                             ++npc->marriage->state;
  123.                         }
  124.                         break;
  125.  
  126.                         case 7: // Partner 2 question box
  127.                         {
  128.                             PacketBuilder builder(PACKET_PRIEST, PACKET_REPLY);
  129.                             builder.AddChar(PRIEST_REQUEST);
  130.                             npc->marriage->partner[1]->player->client->SendBuilder(builder);
  131.                             ++npc->marriage->state;
  132.                         }
  133.                         break;
  134.  
  135.                         case 8: break; // Waiting for Partner 2 acceptance
  136.  
  137.                         case 9: // Rings message
  138.                         {
  139.                             npc->ShowDialog("Let these rings be given and received as a token of your affection, sincerity and trust in one another.");
  140.                             ++npc->marriage->state;
  141.                         }
  142.                         break;
  143.  
  144.                         case 10:
  145.                         {
  146.                             PacketBuilder builder(PACKET_ITEM, static_cast<PacketAction>(26));
  147.                             builder.AddShort(util::to_int(world->config["WeddingRing"]));
  148.                             builder.AddThree(1);
  149.                             for (int i = 0; i < 2; ++i)
  150.                             {
  151.                                 npc->marriage->partner[i]->AddItem(util::to_int(world->config["WeddingRing"]), 1);
  152.                                 npc->marriage->partner[i]->player->client->SendBuilder(builder);
  153.                             }
  154.                             ++npc->marriage->state;
  155.                         }
  156.  
  157.                         case 11:
  158.                         {
  159.                             npc->ShowDialog("Please place these rings on eachothers finger");
  160.                             ++npc->marriage->state;
  161.                         }
  162.                         break;
  163.  
  164.                         case 12:
  165.                         {
  166.                             if (npc->marriage->partner[0]->paperdoll[Character::Ring1] == util::to_int(world->config["WeddingRing"]) ||
  167.                                 npc->marriage->partner[0]->paperdoll[Character::Ring2] == util::to_int(world->config["WeddingRing"]) ||
  168.                                 npc->marriage->partner[1]->paperdoll[Character::Ring1] == util::to_int(world->config["WeddingRing"]) ||
  169.                                 npc->marriage->partner[1]->paperdoll[Character::Ring2] == util::to_int(world->config["WeddingRing"]))
  170.                                 {
  171.                                     ++npc->marriage->state;
  172.                                 }
  173.                         }
  174.                         break;
  175.  
  176.                         case 13: // Waiting for ring equiping
  177.                         {
  178.                             int effect = util::to_int(util::explode(',', world->config["WeddingEffects"])[0]);
  179.                             for (int i = 0; i < 2; ++i)
  180.                                 npc->marriage->partner[i]->Effect(effect);
  181.  
  182.                             npc->ShowDialog(util::ucfirst(npc->marriage->partner[0]->name) + " and " + util::ucfirst(npc->marriage->partner[1]->name) + " have consented together in marriage. And are now partners for as long you both shall live.");
  183.                             ++npc->marriage->state;
  184.                         }
  185.                         break;
  186.  
  187.                         case 14: // Next effect
  188.                         {
  189.                             int effect = util::to_int(util::explode(',', world->config["WeddingEffects"])[1]);
  190.                             for (int i = 0; i < 2; ++i)
  191.                                 npc->marriage->partner[i]->Effect(effect);
  192.                             ++npc->marriage->state;
  193.                         }
  194.                         break;
  195.  
  196.                         case 15: // Next effect
  197.                         {
  198.                             npc->ShowDialog("Congratulations to the couple!");
  199.                             int effect = util::to_int(util::explode(',', world->config["WeddingEffects"])[2]);
  200.                             for (int i = 0; i < 2; ++i)
  201.                                 npc->marriage->partner[i]->Effect(effect);
  202.  
  203.                             npc->marriage->partner[0]->partner = npc->marriage->partner[1]->name;
  204.                             npc->marriage->partner[0]->fiance = "";
  205.  
  206.                             npc->marriage->partner[1]->partner = npc->marriage->partner[0]->name;
  207.                             npc->marriage->partner[1]->fiance = "";
  208.                             npc->marriage = 0;
  209.                         }
  210.                         break;
  211.  
  212.                         default: Console::Err("Invalid state for marriage ceremony."); npc->marriage = 0;
  213.                     }
  214.                     if (npc->marriage)
  215.                         npc->marriage->last_execution = Timer::GetTime();
  216.                 }
  217.             }
  218.         }
  219.     }
  220. }
  221.  
  222. void world_act_npcs(void *world_void)
  223. {
  224.     World *world(static_cast<World *>(world_void));
  225.  
  226.     double current_time = Timer::GetTime();
  227.     UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  228.     {
  229.         UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  230.         {
  231.             if (npc->alive && npc->last_act + npc->act_speed < current_time)
  232.             {
  233.                 npc->Act();
  234.             }
  235.         }
  236.     }
  237. }
  238.  
  239. void world_recover(void *world_void)
  240. {
  241.     World *world(static_cast<World *>(world_void));
  242.  
  243.     PacketBuilder builder(PACKET_RECOVER, PACKET_PLAYER);
  244.  
  245.     UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
  246.     {
  247.         bool updated = false;
  248.  
  249.         if (character->hp < character->maxhp)
  250.         {
  251.             character->hp += character->maxhp / 10;
  252.             character->hp = std::min(character->hp, character->maxhp);
  253.             updated = true;
  254.  
  255.             if (character->party)
  256.             {
  257.                 character->party->UpdateHP(*character);
  258.             }
  259.         }
  260.  
  261.         if (character->tp < character->maxtp)
  262.         {
  263.             character->tp += character->maxtp / 10;
  264.             character->tp = std::min(character->tp, character->maxtp);
  265.             updated = true;
  266.         }
  267.  
  268.         if (updated)
  269.         {
  270.             builder.Reset();
  271.             builder.AddShort(character->hp);
  272.             builder.AddShort(character->tp);
  273.             builder.AddShort(0); // ?
  274.             character->player->client->SendBuilder(builder);
  275.         }
  276.     }
  277. }
  278.  
  279. void world_despawn_items(void *world_void)
  280. {
  281.     World *world = static_cast<World *>(world_void);
  282.  
  283.     UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  284.     {
  285.         restart_loop:
  286.         UTIL_PTR_LIST_FOREACH(map->items, Map_Item, item)
  287.         {
  288.             if (item->unprotecttime < (Timer::GetTime() - static_cast<double>(world->config["ItemDespawnRate"])))
  289.             {
  290.                 map->DelItem(item->uid, 0);
  291.                 goto restart_loop;
  292.             }
  293.         }
  294.     }
  295. }
  296.  
  297. void world_timed_save(void *world_void)
  298. {
  299.     World *world = static_cast<World *>(world_void);
  300.  
  301.     UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
  302.     {
  303.         //character->Refresh();
  304.         character->Save();
  305.     }
  306.  
  307.     world->guildmanager->SaveAll();
  308. }
  309.  
  310. void world_speak_npcs(void *world_void)
  311. {
  312.     World *world = static_cast<World *>(world_void);
  313.  
  314.     UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  315.     {
  316.         UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  317.         {
  318.            int rand = util::rand(1, 100);
  319.            if(rand > 1 && rand < 3) //1% chance say first message
  320.            {
  321.                npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".1"]));
  322.            }
  323.            else if(rand > 30 && rand < 32) //1% chance change message
  324.            {
  325.                npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".2"]));
  326.            }
  327.            else if(rand > 70 && rand < 72) // 1% chance say 3rd
  328.            {
  329.                npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".3"]));
  330.            }
  331.         }
  332.     }
  333. }
  334.  
  335. void world_warp(void *world_void)
  336. {
  337.   World *world = static_cast<World *>(world_void);
  338.  
  339.  UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  340.    {
  341. map->Warp();
  342.    }
  343. }
  344. void world_hide(void *world_void)
  345. {
  346. World *world = static_cast<World *>(world_void);
  347.  
  348. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  349.     {
  350. map->Unhide();
  351.    }
  352. }
  353. void world_shine_god(void *world_void)
  354. {
  355.     World *world = static_cast<World *>(world_void);
  356.  
  357.     UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  358.     {
  359.         map->Shine_God();
  360.     }
  361. }
  362. void world_restart(void *world_void)
  363. {
  364.      World *world = static_cast<World *>(world_void);
  365.  
  366.      UTIL_PTR_VECTOR_FOREACH(world->characters, Character, from)
  367.         {
  368.          from->Restart();
  369.     }
  370. }
  371.  
  372. void world_spawn(void *world_void)
  373. {
  374.      World *world = static_cast<World *>(world_void);
  375.  
  376.        UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  377.         {
  378.        map->SLoad();
  379.        /*UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  380.         {
  381.        UTIL_PTR_VECTOR_FOREACH(world->characters, Character, from)
  382.         {
  383.         int mapd, x, y, id, spawntype, spawntime, amount;
  384.         int index = 0;
  385.         for(int i = 0 ; i < static_cast<int>(world->spawn_config["Amount"]) ; i++){
  386.         mapd = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".map"]);
  387.         x = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".x"]);
  388.         y = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".y"]);
  389.         id = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".id"]);
  390.         spawntype = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".spawntype"]);
  391.         spawntime = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".spawntime"]);
  392.         amount = static_cast<int>(world->spawn_config[util::to_string(i+1) + ".amount"]);
  393.  
  394.             for (int ii = 0; ii < amount; ++ii)
  395.                {
  396.                 //unsigned char index = from->map->GenerateNPCIndex();
  397.  
  398.             if (index > 250)
  399.               {
  400.                 break;
  401.               }
  402.  
  403.               NPC *npc = new NPC(map, id, x, y, spawntype, spawntime, index++);
  404.               map->npcs.push_back(npc);
  405.               npc->Spawn();
  406.               npc->Release();
  407.              }
  408.           }
  409.        }
  410.     }*/
  411.   }
  412. }
  413.  
  414. World::World(util::array<std::string, 6> dbinfo, const Config &eoserv_config, const Config &admin_config)
  415. {
  416.     if (int(this->timer.resolution * 1000.0) > 1)
  417.     {
  418.         Console::Out("Timers set at approx. %i ms resolution", int(this->timer.resolution * 1000.0));
  419.     }
  420.     else
  421.     {
  422.         Console::Out("Timers set at < 1 ms resolution");
  423.     }
  424.  
  425.     this->config = eoserv_config;
  426.     this->admin_config = admin_config;
  427.  
  428.     Database::Engine engine;
  429.     if (dbinfo[0].compare("sqlite") == 0)
  430.     {
  431.         engine = Database::SQLite;
  432.     }
  433.     else
  434.     {
  435.         engine = Database::MySQL;
  436.     }
  437.     this->db.Connect(engine, dbinfo[1], util::to_int(dbinfo[5]), dbinfo[2], dbinfo[3], dbinfo[4]);
  438.  
  439.     try
  440.     {
  441.         this->drops_config.Read(this->config["DropsFile"]);
  442.         this->shops_config.Read(this->config["ShopsFile"]);
  443.         this->arenas_config.Read(this->config["ArenasFile"]);
  444.         this->formulas_config.Read(this->config["FormulasFile"]);
  445.         this->home_config.Read(this->config["HomeFile"]);
  446.         this->spells_config.Read(this->config["SpellsFile"]);
  447.         this->npcsay_config.Read(this->config["NpcSpeachFile"]);
  448.         this->spawn_config.Read(this->config["SpawnFile"]);
  449.     }
  450.     catch (std::runtime_error &e)
  451.     {
  452.         Console::Wrn(e.what());
  453.     }
  454.  
  455.     this->eif = new EIF(this->config["EIF"]);
  456.     this->enf = new ENF(this->config["ENF"]);
  457.     this->esf = new ESF(this->config["ESF"]);
  458.     this->ecf = new ECF(this->config["ECF"]);
  459.  
  460.     this->maps.resize(static_cast<int>(this->config["Maps"])+1);
  461.     this->maps[0] = new Map(1, this); // Just in case
  462.     int loaded = 0;
  463.     int npcs = 0;
  464.     for (int i = 1; i <= static_cast<int>(this->config["Maps"]); ++i)
  465.     {
  466.         this->maps[i] = new Map(i, this);
  467.         if (this->maps[i]->exists)
  468.         {
  469.             npcs += this->maps[i]->npcs.size();
  470.             ++loaded;
  471.         }
  472.     }
  473.     Console::Out("%i/%i maps loaded.", loaded, this->maps.size()-1);
  474.     Console::Out("%i NPCs loaded.", npcs);
  475.  
  476.      this->quests.resize(static_cast<int>(this->config["Quests"]));
  477.     loaded = 0;
  478.     for (int i = 1; i <= static_cast<int>(this->config["Quests"]); ++i)
  479.     {
  480.          this->quests[i-1] = new Quest(i, this);
  481.          if (this->quests[i-1]->exists)
  482.         ++loaded;
  483.     }
  484.     Console::Out("%i/%i quests loaded.", loaded, this->quests.size());
  485.  
  486.     this->last_character_id = 0;
  487.  
  488.     TimeEvent *event = new TimeEvent(world_spawn_npcs, this, 1.0, Timer::FOREVER);
  489.     this->timer.Register(event);
  490.     event->Release();
  491.  
  492.     event = new TimeEvent(world_act_npcs, this, 0.05, Timer::FOREVER);
  493.     this->timer.Register(event);
  494.     event->Release();
  495.  
  496.     event = new TimeEvent(world_warp, this, 5.00, Timer::FOREVER);
  497.     this->timer.Register(event);
  498.     event->Release();
  499.  
  500.     event = new TimeEvent(world_execute_weddings, this, 1.0, Timer::FOREVER);
  501.     this->timer.Register(event);
  502.     event->Release();
  503.  
  504.     event = new TimeEvent(world_recover, this, 90.0, Timer::FOREVER);
  505.     this->timer.Register(event);
  506.     event->Release();
  507.  
  508.     event = new TimeEvent(world_speak_npcs, this, 25.0, Timer::FOREVER);
  509.     this->timer.Register(event);
  510.     event->Release();
  511.  
  512.     event = new TimeEvent(world_shine_god, this, 1.00, Timer::FOREVER);
  513.     this->timer.Register(event);
  514.     event->Release();
  515.  
  516.     if (this->config["ItemDespawn"])
  517.     {
  518.         event = new TimeEvent(world_despawn_items, this, static_cast<double>(this->config["ItemDespawnCheck"]), Timer::FOREVER);
  519.         this->timer.Register(event);
  520.         event->Release();
  521.     }
  522.  
  523.     if (this->config["TimedSave"])
  524.     {
  525.         event = new TimeEvent(world_timed_save, this, static_cast<double>(this->config["TimedSave"]), Timer::FOREVER);
  526.         this->timer.Register(event);
  527.         event->Release();
  528.     }
  529.  
  530.     exp_table[0] = 0;
  531.     for (std::size_t i = 1; i < sizeof(this->exp_table)/sizeof(int); ++i)
  532.     {
  533.         exp_table[i] = int(util::round(std::pow(double(i), 3.0) * 133.1));
  534.     }
  535.  
  536.     for (std::size_t i = 0; i < this->boards.size(); ++i)
  537.     {
  538.         this->boards[i] = new Board(i);
  539.     }
  540.  
  541.     this->hookmanager = new HookManager(this->config["ScriptDir"]);
  542.  
  543.     this->guildmanager = new GuildManager(this);
  544.  
  545.     this->LoadHome();
  546.  
  547.     script_register(*this); // See scriptreg.cpp
  548.  
  549.     FILE *fh = fopen(static_cast<std::string>(this->config["ScriptsFile"]).c_str(), "rt");
  550.  
  551.     if (!fh)
  552.     {
  553.         Console::Wrn("Failed to open %s, no scripts will be loaded", static_cast<std::string>(this->config["ScriptsFile"]).c_str());
  554.     }
  555.  
  556.     char buf[4096];
  557.  
  558.     while (fgets(buf, 4096, fh))
  559.     {
  560.         std::string sbuf(buf);
  561.         sbuf = util::trim(sbuf);
  562.  
  563.         if (sbuf.length() == 0 || sbuf[0] == '#')
  564.         {
  565.             continue;
  566.         }
  567.  
  568.         this->hookmanager->InitCall(sbuf.c_str());
  569.     }
  570.  
  571.     fclose(fh);
  572. }
  573.  
  574. void World::Restart()
  575. {
  576.  
  577. TimeEvent *event = new TimeEvent(world_restart, this, 1.00, 6);
  578. this->timer.Register(event);
  579. event->Release();
  580. }
  581.  
  582. void World::Spawn()
  583. {
  584.  
  585. TimeEvent *event = new TimeEvent(world_spawn, this, 5.00, Timer::FOREVER);
  586. this->timer.Register(event);
  587. event->Release();
  588. }
  589.  
  590. void World::Hide()
  591. {
  592. TimeEvent *event = new TimeEvent(world_hide, this, static_cast<double>(this->config["Time"]), 1);
  593. this->timer.Register(event);
  594. event->Release();
  595. }
  596.  
  597. void World::LoadHome()
  598. {
  599.     this->homes.clear();
  600.  
  601.     std::tr1::unordered_map<std::string, Home *> temp_homes;
  602.  
  603.     UTIL_UNORDERED_MAP_FOREACH_ALL(this->home_config, std::string, util::variant, hc)
  604.     {
  605.         std::vector<std::string> parts = util::explode('.', hc.first);
  606.  
  607.         if (parts.size() < 2)
  608.         {
  609.             continue;
  610.         }
  611.  
  612.         if (parts[0] == "level")
  613.         {
  614.             int level = util::to_int(parts[1]);
  615.  
  616.             std::tr1::unordered_map<std::string, Home *>::iterator home_iter = temp_homes.find(hc.second);
  617.  
  618.             if (home_iter == temp_homes.end())
  619.             {
  620.                 Home *home = new Home;
  621.                 home->id = static_cast<std::string>(hc.second);
  622.                 temp_homes[hc.second] = home;
  623.                 home->level = level;
  624.             }
  625.             else
  626.             {
  627.                 home_iter->second->level = level;
  628.             }
  629.  
  630.             continue;
  631.         }
  632.  
  633.         Home *&home = temp_homes[parts[0]];
  634.  
  635.         if (!home)
  636.         {
  637.             temp_homes[parts[0]] = home = new Home;
  638.             home->id = parts[0];
  639.         }
  640.  
  641.         if (parts[1] == "name")
  642.         {
  643.             home->name = home->name = static_cast<std::string>(hc.second);
  644.         }
  645.         else if (parts[1] == "location")
  646.         {
  647.             std::vector<std::string> locparts = util::explode(',', hc.second);
  648.             home->map = locparts.size() >= 1 ? util::to_int(locparts[0]) : 1;
  649.             home->x = locparts.size() >= 2 ? util::to_int(locparts[1]) : 0;
  650.             home->y = locparts.size() >= 3 ? util::to_int(locparts[2]) : 0;
  651.         }
  652.     }
  653.  
  654.     UTIL_UNORDERED_MAP_FOREACH_ALL(temp_homes, std::string, Home *, home)
  655.     {
  656.         this->homes.push_back(home.second);
  657.         home.second->Release();
  658.     }
  659. }
  660.  
  661. int World::GenerateCharacterID()
  662. {
  663.     return ++this->last_character_id;
  664. }
  665.  
  666. int World::GeneratePlayerID()
  667. {
  668.     unsigned int lowest_free_id = 10000;
  669.     restart_loop:
  670.     UTIL_PTR_LIST_FOREACH(this->server->clients, EOClient, client)
  671.     {
  672.         if (client->id == lowest_free_id)
  673.         {
  674.             lowest_free_id = client->id + 1;
  675.             goto restart_loop;
  676.         }
  677.     }
  678.     return lowest_free_id;
  679. }
  680.  
  681. void World::Login(Character *character)
  682. {
  683.     this->characters.push_back(character);
  684.  
  685.     if (this->GetMap(character->mapid)->relog_x || this->GetMap(character->mapid)->relog_y)
  686.     {
  687.         character->x = this->GetMap(character->mapid)->relog_x;
  688.         character->y = this->GetMap(character->mapid)->relog_y;
  689.     }
  690.  
  691.     this->GetMap(character->mapid)->Enter(character);
  692. }
  693.  
  694. void World::Logout(Character *character)
  695. {
  696.     if (this->GetMap(character->mapid)->exists)
  697.     {
  698.         this->GetMap(character->mapid)->Leave(character);
  699.     }
  700.  
  701.     erase_first(this->characters, character);
  702. }
  703.  
  704. void World::Msg(Character *from, std::string message, bool echo)
  705. {
  706.     message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + "  "));
  707.  
  708.     PacketBuilder builder(PACKET_TALK, PACKET_MSG);
  709.     builder.AddBreakString(from ? from->name : "Server");
  710.     builder.AddBreakString(message);
  711.  
  712.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  713.     {
  714.         if (!echo && *character == from)
  715.         {
  716.             continue;
  717.         }
  718.  
  719.         character->player->client->SendBuilder(builder);
  720.     }
  721. }
  722.  
  723. void World::AdminMsg(Character *from, std::string message, int minlevel, bool echo)
  724. {
  725.     message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + "  "));
  726.  
  727.     PacketBuilder builder(PACKET_TALK, PACKET_ADMIN);
  728.     builder.AddBreakString(from ? from->name : "Server");
  729.     builder.AddBreakString(message);
  730.  
  731.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  732.     {
  733.         if ((!echo && *character == from) || character->admin < minlevel)
  734.         {
  735.             continue;
  736.         }
  737.  
  738.         character->player->client->SendBuilder(builder);
  739.     }
  740. }
  741.  
  742. void World::AnnounceMsg(Character *from, std::string message, bool echo)
  743. {
  744.     message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + "  "));
  745.  
  746.     PacketBuilder builder(PACKET_TALK, PACKET_ANNOUNCE);
  747.     builder.AddBreakString(from ? from->name : "Server");
  748.     builder.AddBreakString(message);
  749.  
  750.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  751.     {
  752.         if (!echo && *character == from)
  753.         {
  754.             continue;
  755.         }
  756.  
  757.         character->player->client->SendBuilder(builder);
  758.     }
  759. }
  760.  
  761. void World::ServerMsg(std::string message)
  762. {
  763.     message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width("Server  "));
  764.  
  765.     PacketBuilder builder(PACKET_TALK, PACKET_SERVER);
  766.     builder.AddString(message);
  767.  
  768.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  769.     {
  770.         character->player->client->SendBuilder(builder);
  771.     }
  772. }
  773.  
  774. void World::AdminReport(Character *from, std::string reportee, std::string message)
  775. {
  776.     message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + "  reports: " + reportee + ", "));
  777.  
  778.     PacketBuilder builder(PACKET_ADMININTERACT, PACKET_REPLY);
  779.     builder.AddChar(2); // message type
  780.     builder.AddByte(255);
  781.     builder.AddBreakString(from->name);
  782.     builder.AddBreakString(message);
  783.     builder.AddBreakString(reportee);
  784.  
  785.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  786.     {
  787.         if (character->admin >= static_cast<int>(this->admin_config["reports"]))
  788.         {
  789.             character->player->client->SendBuilder(builder);
  790.         }
  791.     }
  792.  
  793.     short boardid = static_cast<int>(this->server->world->config["AdminBoard"]) - 1;
  794.  
  795.     if (static_cast<std::size_t>(boardid) < this->server->world->boards.size())
  796.     {
  797.         Board *admin_board = this->server->world->boards[boardid];
  798.  
  799.         Board_Post *newpost = new Board_Post;
  800.         newpost->id = ++admin_board->last_id;
  801.         newpost->author = from->name;
  802.         newpost->author_admin = from->admin;
  803.         newpost->subject = std::string(" [Report] ") + util::ucfirst(from->name) + " reports: " + reportee;
  804.         newpost->body = message;
  805.         newpost->time = Timer::GetTime();
  806.  
  807.         admin_board->posts.push_front(newpost);
  808.  
  809.         if (admin_board->posts.size() > static_cast<std::size_t>(static_cast<int>(this->server->world->config["AdminBoardLimit"])))
  810.         {
  811.             admin_board->posts.pop_back();
  812.         }
  813.     }
  814. }
  815.  
  816. void World::AdminRequest(Character *from, std::string message)
  817. {
  818.     message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + "  needs help: "));
  819.  
  820.     PacketBuilder builder(PACKET_ADMININTERACT, PACKET_REPLY);
  821.     builder.AddChar(1); // message type
  822.     builder.AddByte(255);
  823.     builder.AddBreakString(from->name);
  824.     builder.AddBreakString(message);
  825.  
  826.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  827.     {
  828.         if (character->admin >= static_cast<int>(this->admin_config["reports"]))
  829.         {
  830.             character->player->client->SendBuilder(builder);
  831.         }
  832.     }
  833.  
  834.     short boardid = static_cast<int>(this->server->world->config["AdminBoard"]) - 1;
  835.  
  836.     if (static_cast<std::size_t>(boardid) < this->server->world->boards.size())
  837.     {
  838.         Board *admin_board = this->server->world->boards[boardid];
  839.  
  840.         Board_Post *newpost = new Board_Post;
  841.         newpost->id = ++admin_board->last_id;
  842.         newpost->author = from->name;
  843.         newpost->author_admin = from->admin;
  844.         newpost->subject = std::string(" [Request] ") + util::ucfirst(from->name) + " needs help";
  845.         newpost->body = message;
  846.         newpost->time = Timer::GetTime();
  847.  
  848.         admin_board->posts.push_front(newpost);
  849.  
  850.         if (admin_board->posts.size() > static_cast<std::size_t>(static_cast<int>(this->server->world->config["AdminBoardLimit"])))
  851.         {
  852.             admin_board->posts.pop_back();
  853.         }
  854.     }
  855. }
  856.  
  857. void World::Rehash()
  858. {
  859.     try
  860.     {
  861.         this->config.Read("config.ini");
  862.         this->admin_config.Read("admin.ini");
  863.         this->drops_config.Read(this->config["DropsFile"]);
  864.         this->shops_config.Read(this->config["ShopsFile"]);
  865.         this->arenas_config.Read(this->config["ArenasFile"]);
  866.         this->formulas_config.Read(this->config["FormulasFile"]);
  867.         this->home_config.Read(this->config["HomeFile"]);
  868.         this->spells_config.Read(this->config["SpellsFile"]);
  869.         this->npcsay_config.Read(this->config["NpcSpeachFile"]);
  870.     this->spawn_config.Read(static_cast<std::string>(this->config["SpawnFile"]));
  871.     }
  872.     catch (std::runtime_error &e)
  873.     {
  874.         Console::Err(e.what());
  875.     }
  876.  
  877.     this->LoadHome();
  878.  
  879.     UTIL_PTR_VECTOR_FOREACH(this->maps, Map, map)
  880.     {
  881.         map->LoadArena();
  882.  
  883.         UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  884.         {
  885.             npc->LoadShopDrop();
  886.         }
  887.     }
  888.  
  889.     UTIL_PTR_VECTOR_FOREACH(this->quests, Quest, quest)
  890.     {
  891.         quest->Reload(this);
  892.     }
  893. }
  894.  
  895. void World::ReloadPub()
  896. {
  897.     this->eif->Read(this->config["EIF"]);
  898.     this->enf->Read(this->config["ENF"]);
  899.     this->esf->Read(this->config["ESF"]);
  900.     this->ecf->Read(this->config["ECF"]);
  901.  
  902.     std::string filename;
  903.     std::FILE *fh;
  904.     InitReply replycode;
  905.  
  906.     for (int i = 0; i < 4; ++i)
  907.     {
  908.         std::string content;
  909.  
  910.         switch (i)
  911.         {
  912.             case 0: filename = static_cast<std::string>(this->config["EIF"]); replycode = INIT_FILE_EIF; break;
  913.             case 1: filename = static_cast<std::string>(this->config["ENF"]); replycode = INIT_FILE_ENF; break;
  914.             case 2: filename = static_cast<std::string>(this->config["ESF"]); replycode = INIT_FILE_ESF; break;
  915.             case 3: filename = static_cast<std::string>(this->config["ECF"]); replycode = INIT_FILE_ECF; break;
  916.         }
  917.  
  918.         fh = std::fopen(filename.c_str(), "rb");
  919.  
  920.         if (!fh)
  921.         {
  922.             Console::Err("Could not load file: %s", filename.c_str());
  923.             std::exit(1);
  924.         }
  925.  
  926.         do {
  927.             char buf[4096];
  928.             int len = std::fread(buf, sizeof(char), 4096, fh);
  929.             content.append(buf, len);
  930.         } while (!std::feof(fh));
  931.  
  932.         std::fclose(fh);
  933.  
  934.         PacketBuilder builder(0);
  935.         builder.AddChar(replycode);
  936.         builder.AddChar(1); // fileid
  937.         builder.AddString(content);
  938.  
  939.         UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  940.         {
  941.             character->player->client->SendBuilderRaw(builder);
  942.         }
  943.     }
  944.  
  945.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  946.     {
  947.         character->Warp(character->mapid, character->x, character->y);
  948.     }
  949. }
  950.  
  951. Character *World::GetCharacter(std::string name)
  952. {
  953.     name = util::lowercase(name);
  954.  
  955.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  956.     {
  957.         if (character->name.compare(name) == 0)
  958.         {
  959.             return *character;
  960.         }
  961.     }
  962.  
  963.     return 0;
  964. }
  965.  
  966. Character *World::GetCharacterPID(unsigned int id)
  967. {
  968.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  969.     {
  970.         if (character->player->id == id)
  971.         {
  972.             return *character;
  973.         }
  974.     }
  975.  
  976.     return 0;
  977. }
  978.  
  979. Character *World::GetCharacterCID(unsigned int id)
  980. {
  981.     UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  982.     {
  983.         if (character->id == id)
  984.         {
  985.             return *character;
  986.         }
  987.     }
  988.  
  989.     return 0;
  990. }
  991.  
  992. Map *World::GetMap(short id)
  993. {
  994.     try
  995.     {
  996.         return this->maps.at(id);
  997.     }
  998.     catch (...)
  999.     {
  1000.         return this->maps.at(0);
  1001.     }
  1002. }
  1003.  
  1004. Home *World::GetHome(Character *character)
  1005. {
  1006.     Home *home = 0;
  1007.     static Home *null_home = new Home;
  1008.  
  1009.     UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
  1010.     {
  1011.         if (h->id == character->home)
  1012.         {
  1013.             return *h;
  1014.         }
  1015.     }
  1016.  
  1017.     int current_home_level = -2;
  1018.     UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
  1019.     {
  1020.         if (h->level <= character->level && h->level > current_home_level)
  1021.         {
  1022.             home = *h;
  1023.             current_home_level = h->level;
  1024.         }
  1025.     }
  1026.  
  1027.     if (!home)
  1028.     {
  1029.         home = null_home;
  1030.     }
  1031.  
  1032.     return home;
  1033. }
  1034.  
  1035. Home *World::GetHome(std::string id)
  1036. {
  1037.     UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
  1038.     {
  1039.         if (h->id == id)
  1040.         {
  1041.             return *h;
  1042.         }
  1043.     }
  1044.  
  1045.     return 0;
  1046. }
  1047.  
  1048. Quest *World::GetQuest(short id)
  1049. {
  1050.     try
  1051.     {
  1052.         return this->quests.at(id-1);
  1053.     }
  1054.     catch (...)
  1055.     {
  1056.         return this->quests.at(0);
  1057.     }
  1058. }
  1059.  
  1060. bool World::CharacterExists(std::string name)
  1061. {
  1062.     Database_Result res = this->db.Query("SELECT 1 FROM `characters` WHERE `name` = '$'", name.c_str());
  1063.     return !res.empty();
  1064. }
  1065.  
  1066. Character *World::CreateCharacter(Player *player, std::string name, Gender gender, int hairstyle, int haircolor, Skin race)
  1067. {
  1068.     char buffer[1024];
  1069.     std::string startmapinfo;
  1070.     std::string startmapval;
  1071.  
  1072.     if (static_cast<int>(this->config["StartMap"]))
  1073.     {
  1074.         startmapinfo = ", `map`, `x`, `y`";
  1075.         snprintf(buffer, 1024, ",%i,%i,%i", static_cast<int>(this->config["StartMap"]), static_cast<int>(this->config["StartX"]), static_cast<int>(this->config["StartY"]));
  1076.         startmapval = buffer;
  1077.     }
  1078.  
  1079.     this->db.Query("INSERT INTO `characters` (`name`, `account`, `gender`, `hairstyle`, `haircolor`, `race`, `inventory`, `bank`, `paperdoll`, `spells`, `quest`, `vars`@) VALUES ('$','$',#,#,#,#,'$','','$','$','',''@)",
  1080.         startmapinfo.c_str(), name.c_str(), player->username.c_str(), gender, hairstyle, haircolor, race,
  1081.         static_cast<std::string>(this->config["StartItems"]).c_str(), static_cast<std::string>(gender?this->config["StartEquipMale"]:this->config["StartEquipFemale"]).c_str(),
  1082.         static_cast<std::string>(this->config["StartSpells"]).c_str(), startmapval.c_str());
  1083.  
  1084.     return new Character(name, this);
  1085. }
  1086.  
  1087. void World::DeleteCharacter(std::string name)
  1088. {
  1089.     this->db.Query("DELETE FROM `characters` WHERE name = '$'", name.c_str());
  1090. }
  1091.  
  1092. Player *World::Login(std::string username, std::string password)
  1093. {
  1094.     password = sha256(static_cast<std::string>(this->config["PasswordSalt"]) + username + password);
  1095.     Database_Result res = this->db.Query("SELECT 1 FROM `accounts` WHERE `username` = '$' AND `password` = '$'", username.c_str(), password.c_str());
  1096.     if (res.empty())
  1097.     {
  1098.         return 0;
  1099.     }
  1100.     std::tr1::unordered_map<std::string, util::variant> row = res.front();
  1101.  
  1102.     return new Player(username, this);
  1103. }
  1104.  
  1105. bool World::CreatePlayer(std::string username, std::string password, std::string fullname, std::string location, std::string email, std::string computer, std::string hdid, std::string ip)
  1106. {
  1107.     password = sha256(static_cast<std::string>(this->config["PasswordSalt"]) + username + password);
  1108.     Database_Result result = this->db.Query("INSERT INTO `accounts` (`username`, `password`, `fullname`, `location`, `email`, `computer`, `hdid`, `regip`, `created`) VALUES ('$','$','$','$','$','$','$','$',#)", username.c_str(), password.c_str(), fullname.c_str(), location.c_str(), email.c_str(), computer.c_str(), hdid.c_str(), ip.c_str(), std::time(0));
  1109.     return !result.Error();
  1110. }
  1111.  
  1112. bool World::PlayerExists(std::string username)
  1113. {
  1114.     Database_Result res = this->db.Query("SELECT 1 FROM `accounts` WHERE `username` = '$'", username.c_str());
  1115.     return !res.empty();
  1116. }
  1117.  
  1118. bool World::PlayerOnline(std::string username)
  1119. {
  1120.     if (!Player::ValidName(username))
  1121.     {
  1122.         return false;
  1123.     }
  1124.  
  1125.     UTIL_PTR_LIST_FOREACH(this->server->clients, EOClient, connection)
  1126.     {
  1127.         if (connection->player)
  1128.         {
  1129.             if (connection->player->username.compare(username) == 0)
  1130.             {
  1131.                 return true;
  1132.             }
  1133.         }
  1134.     }
  1135.  
  1136.     return false;
  1137. }
  1138.  
  1139. void World::Kick(Character *from, Character *victim, bool announce)
  1140. {
  1141.     if (announce)
  1142.     {
  1143.         std::string msg("Attention!! ");
  1144.         msg += victim->name + " has been kicked ";
  1145.         if (from) msg += "-" + from->name + " ";
  1146.         msg += "[kicked]";
  1147.         this->ServerMsg(msg);
  1148.     }
  1149.  
  1150.     victim->player->client->Close();
  1151. }
  1152.  
  1153. void World::Jail(Character *from, Character *victim, bool announce)
  1154. {
  1155.     if (announce)
  1156.     {
  1157.         std::string msg("Attention!! ");
  1158.         msg += victim->name + " has been removed from the game. ";
  1159.         if (from) msg += "-" + from->name + " ";
  1160.         msg += "[jailed]";
  1161.         this->ServerMsg(msg);
  1162.     }
  1163.  
  1164.     victim->Warp(static_cast<int>(this->server->world->config["JailMap"]), static_cast<int>(this->server->world->config["JailX"]), static_cast<int>(this->server->world->config["JailY"]), WARP_ANIMATION_ADMIN);
  1165. }
  1166.  
  1167. void World::Wall(Character *from, Character *victim, bool announce)
  1168. {
  1169.     if (announce)
  1170.     {
  1171.         std::string msg("Attention!!! ");//Says Attention
  1172.         msg += victim->name + " has been "; //Bob has been
  1173.         msg += "[Walled]";// Walled
  1174.         if (from) msg += "-" + from->name + " ";//-Billy
  1175.         this->ServerMsg(msg);
  1176.               //Attention!!! Bob has been [Walled] -Billy
  1177.         }
  1178.  
  1179.     victim->Warp(static_cast<int>(this->server->world->config["WallMap"]), static_cast<int>(this->server->world->config["WallX"]), static_cast<int>(this->server->world->config["WallY"]), WARP_ANIMATION_ADMIN);
  1180. }
  1181.  
  1182. void World::Ban(Character *from, Character *victim, int duration, bool announce)
  1183. {
  1184.     if (announce)
  1185.     {
  1186.         std::string msg("Attention!! ");
  1187.         msg += victim->name + " has been booted from the game for bein a biAtCh ";
  1188.         if (from) msg += "-" + from->name + " ";
  1189.         msg += "[banned]";
  1190.         this->ServerMsg(msg);
  1191.     }
  1192.  
  1193.     std::string query("INSERT INTO bans (username, ip, hdid, expires, setter) VALUES ");
  1194.  
  1195.     query += "('" + db.Escape(victim->player->username) + "', ";
  1196.     query += util::to_string(static_cast<int>(victim->player->client->GetRemoteAddr())) + ", ";
  1197.     query += util::to_string(victim->player->client->hdid) + ", ";
  1198.     if (duration == -1)
  1199.     {
  1200.         query += "0";
  1201.     }
  1202.     else
  1203.     {
  1204.         query += util::to_string(int(std::time(0) + duration));
  1205.     }
  1206.     if (from)
  1207.     {
  1208.         query += ", '" + db.Escape(from->name) + "')";
  1209.     }
  1210.     else
  1211.     {
  1212.         query += ")";
  1213.     }
  1214.  
  1215.     db.Query(query.c_str(), std::time(0));
  1216.  
  1217.     victim->player->client->Close();
  1218. }
  1219.  
  1220. int World::CheckBan(const std::string *username, const IPAddress *address, const int *hdid)
  1221. {
  1222.     std::string query("SELECT COALESCE(MAX(expires),-1) AS expires FROM bans WHERE (");
  1223.  
  1224.     if (!username && !address && !hdid)
  1225.     {
  1226.         return -1;
  1227.     }
  1228.  
  1229.     if (username)
  1230.     {
  1231.         query += "username = '";
  1232.         query += db.Escape(*username);
  1233.         query += "' OR ";
  1234.     }
  1235.  
  1236.     if (address)
  1237.     {
  1238.         query += "ip = ";
  1239.         query += util::to_string(static_cast<int>(*const_cast<IPAddress *>(address)));
  1240.         query += " OR ";
  1241.     }
  1242.  
  1243.     if (hdid)
  1244.     {
  1245.         query += "hdid = ";
  1246.         query += util::to_string(*hdid);
  1247.         query += " OR ";
  1248.     }
  1249.  
  1250.     Database_Result res = db.Query((query.substr(0, query.length()-4) + ") AND (expires > # OR expires = 0)").c_str(), std::time(0));
  1251.  
  1252.     return static_cast<int>(res[0]["expires"]);
  1253. }
  1254.  
  1255. static std::list<int> PKExceptUnserialize(std::string serialized)
  1256. {
  1257.     std::list<int> list;
  1258.     std::size_t p = 0;
  1259.     std::size_t lastp = std::numeric_limits<std::size_t>::max();
  1260.  
  1261.     if (!serialized.empty() && *(serialized.end()-1) != ',')
  1262.     {
  1263.         serialized.push_back(',');
  1264.     }
  1265.  
  1266.     while ((p = serialized.find_first_of(',', p+1)) != std::string::npos)
  1267.     {
  1268.         list.push_back(util::to_int(serialized.substr(lastp+1, p-lastp-1)));
  1269.         lastp = p;
  1270.     }
  1271.  
  1272.     return list;
  1273. }
  1274.  
  1275. bool World::PKExcept(const Map *map)
  1276. {
  1277.     return this->PKExcept(map->id);
  1278. }
  1279.  
  1280. bool World::PKExcept(int mapid)
  1281. {
  1282.     if (mapid == static_cast<int>(this->config["JailMap"]))
  1283.     {
  1284.         return true;
  1285.     }
  1286.  
  1287.     if (this->GetMap(mapid)->arena)
  1288.     {
  1289.         return true;
  1290.     }
  1291.  
  1292.     std::list<int> except_list = PKExceptUnserialize(this->config["PKExcept"]);
  1293.  
  1294.     return std::find(except_list.begin(), except_list.end(), mapid) != except_list.end();
  1295. }
  1296.  
  1297. World::~World()
  1298. {
  1299.     while (!this->characters.empty())
  1300.     {
  1301.         this->characters.back()->player->client->Close(true);
  1302.         this->characters.back()->Destroy();
  1303.     }
  1304.  
  1305.     this->hookmanager->Release();
  1306.     this->guildmanager->Release();
  1307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement