Advertisement
Guest User

Untitled

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