Advertisement
Guest User

Untitled

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