- renamed a missed file (including buildsystem update)
authorAkiko <akiko@linux-addicted.net>
Tue, 19 May 2015 10:06:06 +0000 (12:06 +0200)
committerAkiko <akiko@linux-addicted.net>
Tue, 19 May 2015 10:06:06 +0000 (12:06 +0200)
- changed windows/dos linefeeds to unix ones

193 files changed:
TinNS/Source/Common/Config.cxx
TinNS/Source/Common/Config.hxx
TinNS/Source/Common/Console.cxx
TinNS/Source/Common/Console.hxx
TinNS/Source/Common/FileSystem.cxx
TinNS/Source/Common/FileSystem.hxx
TinNS/Source/Common/Misc.cxx
TinNS/Source/Common/Misc.hxx
TinNS/Source/Common/Mutex.hxx
TinNS/Source/Common/Semaphore.hxx
TinNS/Source/Common/Thread.hxx
TinNS/Source/Common/Version.hxx
TinNS/Source/DevelopmentTools/CMakeLists.txt
TinNS/Source/DevelopmentTools/getsvnrev.cxx [moved from TinNS/Source/DevelopmentTools/getsvnrev.cpp with 95% similarity]
TinNS/Source/GameServer/Accounts.cxx
TinNS/Source/GameServer/Accounts.hxx
TinNS/Source/GameServer/Appartements.cxx
TinNS/Source/GameServer/Appartements.hxx
TinNS/Source/GameServer/BuddyList.cxx
TinNS/Source/GameServer/BuddyList.hxx
TinNS/Source/GameServer/Chars.cxx
TinNS/Source/GameServer/Chars.hxx
TinNS/Source/GameServer/Chat.cxx
TinNS/Source/GameServer/Chat.hxx
TinNS/Source/GameServer/Client.cxx
TinNS/Source/GameServer/Client.hxx
TinNS/Source/GameServer/ClientManager.cxx
TinNS/Source/GameServer/ClientManager.hxx
TinNS/Source/GameServer/ConfigTemplate.hxx
TinNS/Source/GameServer/Container.cxx
TinNS/Source/GameServer/Container.hxx
TinNS/Source/GameServer/Decoder/MessageDecoder.cxx
TinNS/Source/GameServer/Decoder/MessageDecoder.hxx
TinNS/Source/GameServer/Decoder/Udp0x08.cxx
TinNS/Source/GameServer/Decoder/Udp0x08.hxx
TinNS/Source/GameServer/Decoder/Udp0x13.hxx
TinNS/Source/GameServer/Decoder/Udp0x1f.cxx
TinNS/Source/GameServer/Decoder/Udp0x1f.hxx
TinNS/Source/GameServer/Decoder/Udp0x22.cxx
TinNS/Source/GameServer/Decoder/Udp0x22.hxx
TinNS/Source/GameServer/Decoder/Udp0x2b.cxx
TinNS/Source/GameServer/Decoder/Udp0x2b.hxx
TinNS/Source/GameServer/Decoder/UdpAnalyser.cxx
TinNS/Source/GameServer/Decoder/UdpAnalyser.hxx
TinNS/Source/GameServer/Decoder/UdpAppartment.hxx
TinNS/Source/GameServer/Decoder/UdpCharMove.cxx
TinNS/Source/GameServer/Decoder/UdpCharMove.hxx
TinNS/Source/GameServer/Decoder/UdpChat.hxx
TinNS/Source/GameServer/Decoder/UdpEntityPositionRequest.cxx
TinNS/Source/GameServer/Decoder/UdpEntityPositionRequest.hxx
TinNS/Source/GameServer/Decoder/UdpHack.hxx
TinNS/Source/GameServer/Decoder/UdpItemMove.cxx
TinNS/Source/GameServer/Decoder/UdpItemMove.hxx
TinNS/Source/GameServer/Decoder/UdpOOO.cxx
TinNS/Source/GameServer/Decoder/UdpOOO.hxx
TinNS/Source/GameServer/Decoder/UdpPacket0.hxx
TinNS/Source/GameServer/Decoder/UdpPing.hxx
TinNS/Source/GameServer/Decoder/UdpQuickAccessBelt.hxx
TinNS/Source/GameServer/Decoder/UdpRequestInfo.hxx
TinNS/Source/GameServer/Decoder/UdpSubSkill.hxx
TinNS/Source/GameServer/Decoder/UdpSync.hxx
TinNS/Source/GameServer/Decoder/UdpTerminal.cxx
TinNS/Source/GameServer/Decoder/UdpTerminal.hxx
TinNS/Source/GameServer/Decoder/UdpUseObject.cxx
TinNS/Source/GameServer/Decoder/UdpUseObject.hxx
TinNS/Source/GameServer/Decoder/UdpVehicle.cxx
TinNS/Source/GameServer/Decoder/UdpVehicle.hxx
TinNS/Source/GameServer/Decoder/UdpZoning.hxx
TinNS/Source/GameServer/Definitions/AppartementPlaces.cxx
TinNS/Source/GameServer/Definitions/AppartementPlaces.hxx
TinNS/Source/GameServer/Definitions/Appartements.cxx
TinNS/Source/GameServer/Definitions/Appartements.hxx
TinNS/Source/GameServer/Definitions/CharacterKinds.cxx
TinNS/Source/GameServer/Definitions/CharacterKinds.hxx
TinNS/Source/GameServer/Definitions/Characters.cxx
TinNS/Source/GameServer/Definitions/Characters.hxx
TinNS/Source/GameServer/Definitions/Factions.cxx
TinNS/Source/GameServer/Definitions/Factions.hxx
TinNS/Source/GameServer/Definitions/GameDefinitions.cxx
TinNS/Source/GameServer/Definitions/GameDefinitions.hxx
TinNS/Source/GameServer/Definitions/Hack.cxx
TinNS/Source/GameServer/Definitions/Hack.hxx
TinNS/Source/GameServer/Definitions/Items.cxx
TinNS/Source/GameServer/Definitions/Items.hxx
TinNS/Source/GameServer/Definitions/Parser.cxx
TinNS/Source/GameServer/Definitions/Parser.hxx
TinNS/Source/GameServer/Definitions/Respawn.cxx
TinNS/Source/GameServer/Definitions/Respawn.hxx
TinNS/Source/GameServer/Definitions/Skills.cxx
TinNS/Source/GameServer/Definitions/Skills.hxx
TinNS/Source/GameServer/Definitions/SubSkills.cxx
TinNS/Source/GameServer/Definitions/SubSkills.hxx
TinNS/Source/GameServer/Definitions/WorldDatParser.cxx
TinNS/Source/GameServer/Definitions/WorldDatParser.hxx
TinNS/Source/GameServer/Definitions/WorldDatStruct.hxx
TinNS/Source/GameServer/Definitions/WorldFile.cxx
TinNS/Source/GameServer/Definitions/WorldFile.hxx
TinNS/Source/GameServer/Definitions/WorldModels.cxx
TinNS/Source/GameServer/Definitions/WorldModels.hxx
TinNS/Source/GameServer/Definitions/Worlds.cxx
TinNS/Source/GameServer/Definitions/Worlds.hxx
TinNS/Source/GameServer/DoorTemplate.cxx
TinNS/Source/GameServer/DoorTemplate.hxx
TinNS/Source/GameServer/FurnitureTemplate.cxx
TinNS/Source/GameServer/FurnitureTemplate.hxx
TinNS/Source/GameServer/GameCommands/Ban.cxx
TinNS/Source/GameServer/GameCommands/Brightness.cxx
TinNS/Source/GameServer/GameCommands/Broadcast.cxx
TinNS/Source/GameServer/GameCommands/Color.cxx
TinNS/Source/GameServer/GameCommands/Debug.cxx
TinNS/Source/GameServer/GameCommands/Effect.cxx
TinNS/Source/GameServer/GameCommands/H.cxx
TinNS/Source/GameServer/GameCommands/Info.cxx
TinNS/Source/GameServer/GameCommands/Kick.cxx
TinNS/Source/GameServer/GameCommands/ListBans.cxx
TinNS/Source/GameServer/GameCommands/Online.cxx
TinNS/Source/GameServer/GameCommands/RawF.cxx
TinNS/Source/GameServer/GameCommands/Remove.cxx
TinNS/Source/GameServer/GameCommands/SetLevel.cxx
TinNS/Source/GameServer/GameCommands/SetTime.cxx
TinNS/Source/GameServer/GameCommands/Shun.cxx
TinNS/Source/GameServer/GameCommands/Skin.cxx
TinNS/Source/GameServer/GameCommands/SpawnActor.cxx
TinNS/Source/GameServer/GameCommands/Speed.cxx
TinNS/Source/GameServer/GameCommands/T.cxx
TinNS/Source/GameServer/GameCommands/Test.cxx
TinNS/Source/GameServer/GameCommands/UnBan.cxx
TinNS/Source/GameServer/GameCommands/UnShun.cxx
TinNS/Source/GameServer/GameCommands/Uptime.cxx
TinNS/Source/GameServer/GameCommands/V.cxx
TinNS/Source/GameServer/GameCommands/Version.cxx
TinNS/Source/GameServer/GameScript.cxx
TinNS/Source/GameServer/GameScript.hxx
TinNS/Source/GameServer/GameServer.cxx
TinNS/Source/GameServer/GameServer.hxx
TinNS/Source/GameServer/GenrepList.cxx
TinNS/Source/GameServer/GenrepList.hxx
TinNS/Source/GameServer/Includes.cxx
TinNS/Source/GameServer/Includes.hxx
TinNS/Source/GameServer/Inventory.cxx
TinNS/Source/GameServer/Inventory.hxx
TinNS/Source/GameServer/Isc.cxx
TinNS/Source/GameServer/Isc.hxx
TinNS/Source/GameServer/Item.cxx
TinNS/Source/GameServer/Item.hxx
TinNS/Source/GameServer/Main.hxx
TinNS/Source/GameServer/MessageBuilder.cxx
TinNS/Source/GameServer/MessageBuilder.hxx
TinNS/Source/GameServer/Npc.cxx
TinNS/Source/GameServer/Npc.hxx
TinNS/Source/GameServer/RemoteConsole.cxx
TinNS/Source/GameServer/RemoteConsole.hxx
TinNS/Source/GameServer/Server.cxx
TinNS/Source/GameServer/Server.hxx
TinNS/Source/GameServer/Sql.cxx
TinNS/Source/GameServer/Sql.hxx
TinNS/Source/GameServer/Subway.cxx
TinNS/Source/GameServer/Subway.hxx
TinNS/Source/GameServer/Terminal.hxx
TinNS/Source/GameServer/TerminalReceiveDatabase.cxx
TinNS/Source/GameServer/TerminalUpdateDatabase.cxx
TinNS/Source/GameServer/Vehicle.cxx
TinNS/Source/GameServer/Vehicle.hxx
TinNS/Source/GameServer/WorldActors.hxx
TinNS/Source/GameServer/WorldDataTemplate.cxx
TinNS/Source/GameServer/WorldDataTemplate.hxx
TinNS/Source/GameServer/Worlds.cxx
TinNS/Source/GameServer/Zoning.cxx
TinNS/Source/GameServer/Zoning.hxx
TinNS/Source/InfoServer/Accounts.cxx
TinNS/Source/InfoServer/Accounts.hxx
TinNS/Source/InfoServer/Client.cxx
TinNS/Source/InfoServer/Client.hxx
TinNS/Source/InfoServer/ConfigTemplate.hxx
TinNS/Source/InfoServer/Includes.cxx
TinNS/Source/InfoServer/Includes.hxx
TinNS/Source/InfoServer/InfoServer.cxx
TinNS/Source/InfoServer/InfoServer.hxx
TinNS/Source/InfoServer/Main.cxx
TinNS/Source/InfoServer/Server.cxx
TinNS/Source/InfoServer/Server.hxx
TinNS/Source/InfoServer/Sql.cxx
TinNS/Source/InfoServer/Sql.hxx
TinNS/Source/PatchServer/Client.cxx
TinNS/Source/PatchServer/Client.hxx
TinNS/Source/PatchServer/ConfigTemplate.hxx
TinNS/Source/PatchServer/Includes.cxx
TinNS/Source/PatchServer/Includes.hxx
TinNS/Source/PatchServer/Main.cxx
TinNS/Source/PatchServer/PatchServer.cxx
TinNS/Source/PatchServer/PatchServer.hxx
TinNS/Source/PatchServer/Server.cxx
TinNS/Source/PatchServer/Server.hxx

index 1d30b06..3803b1c 100644 (file)
-#include <cstring>\r
-#include "Common/Includes.hxx"\r
-\r
-PConfig::PConfig()\r
-{\r
-  mOptValRegEx = new RegEx("^\\s*([[:graph:]]+)\\s*=\\s*(.+?)\\s*$", PCRE_CASELESS);\r
-  mIncludeRegEx = new RegEx("^\\s*include\\s+([[:graph:]]+)\\s*$", PCRE_CASELESS);\r
-}\r
-\r
-PConfig::~PConfig()\r
-{\r
-  delete mOptValRegEx;\r
-  delete mIncludeRegEx;\r
-}\r
-\r
-bool PConfig::LoadOptions(const char* nConfigTemplate[][2], const char* nConfigFile, int nDepth)\r
-{\r
-    FILE *ConfigFile;\r
-    char line[255];\r
-    std::string Opt, Val;\r
-    //int numOptions = 0;\r
-    int i;\r
-    bool Found;\r
-    bool NoError = true;\r
-\r
-    ConfigFile = fopen(nConfigFile,"r");\r
-\r
-    if(!ConfigFile)\r
-    {\r
-        Console->Print("%s Cant open file \"%s\"", Console->ColorText(RED, BLACK, "[Error]"), nConfigFile);\r
-        return false;\r
-    }\r
-\r
-  if(nDepth)\r
-    Console->Print("%s Including file %s (nesting level %d)", Console->ColorText(GREEN, BLACK, "[Info]"), nConfigFile, nDepth);\r
-  else\r
-      Console->Print("%s Loading configuration file %s", Console->ColorText(GREEN, BLACK, "[Info]"), nConfigFile);\r
-\r
-    while(!feof(ConfigFile) && fgets(line, 255, ConfigFile))\r
-    {\r
-        //Console->Print("LINE: '%s'", line);\r
-        if (line[0] == '/' && line[1] == '/')\r
-        continue;\r
-\r
-        if(mOptValRegEx->Search(line))\r
-      {\r
-        Opt = mOptValRegEx->Match(1);\r
-        Val = mOptValRegEx->Match(2);\r
-        //Console->Print("'%s'='%s'", Opt.c_str(), Val.c_str());\r
-\r
-        Trim(&Opt);\r
-        Trim(&Val);\r
-        //Console->Print("'%s'='%s'", Opt.c_str(), Val.c_str());\r
-      }\r
-      else if(mIncludeRegEx->Search(line))\r
-      {\r
-        if(nDepth < CONFIG_MAXDEPTH)\r
-        {\r
-          std::string TargetName = mIncludeRegEx->Match(1);\r
-          std::string StartName = nConfigFile;\r
-          int BasenamePos = StartName.rfind("/");\r
-          if(BasenamePos > 0)\r
-            TargetName = StartName.substr(0, BasenamePos) + "/" + TargetName;\r
-\r
-          NoError = LoadOptions(nConfigTemplate, TargetName.c_str(), nDepth+1) && NoError;\r
-          continue;\r
-        }\r
-        else\r
-        {\r
-          Console->Print("%s Max nesting level (%d) reached. Can't include configuration file %s", Console->ColorText(RED, BLACK, "[Error]"), CONFIG_MAXDEPTH,mIncludeRegEx->Match(1));\r
-          NoError = false;\r
-        }\r
-      }\r
-      else\r
-      {\r
-          continue;\r
-      }\r
-\r
-      i = 0;\r
-      Found = false;\r
-      while(!Found && (nConfigTemplate[i][0][0] != '\0'))\r
-      {\r
-        if(!strcmp(Opt.c_str(), nConfigTemplate[i++][0]))\r
-        {\r
-          Found = true;\r
-          break;\r
-        }\r
-      }\r
-\r
-        if(!Opt.empty() && !Val.empty())\r
-        {\r
-            //Console->Print("#%d [%s] [%s]", numOptions, Opt.c_str(), Val.c_str());\r
-            if (Found)\r
-            {\r
-              if (GetOption(Opt) != "")\r
-              {\r
-                Console->Print("%s trying to set option %s more than once (old value '%s' - new value '%s' ignored)", Console->ColorText(YELLOW, BLACK, "[Warning]"), Opt.c_str(), GetOption(Opt).c_str(), Val.c_str());\r
-              }\r
-              else\r
-              {\r
-                //Console->Print(GREEN, BLACK, "New option %s set to %s", Opt.c_str(), Val.c_str());\r
-              mOptions.insert(std::make_pair(Opt, Val));\r
-            }\r
-          }\r
-          else\r
-          {\r
-             Console->Print("%s option %s unknow and ignored (value %s)", Console->ColorText(YELLOW, BLACK, "[Warning]"), Opt.c_str(), Val.c_str());\r
-          }\r
-        }\r
-    }\r
-\r
-  // Now check for completeness and set default values when needed and available\r
-  if(!nDepth) // Check only if we're at top level (ie. not in an included file)\r
-  {\r
-    i = 0;\r
-    while(nConfigTemplate[i][0][0] != '\0')\r
-    {\r
-      if (GetOption(nConfigTemplate[i][0]) == "")\r
-      {\r
-        if(nConfigTemplate[i][1][0] == '\0')\r
-        {\r
-          Console->Print("%s required option %s missing from config file", Console->ColorText(RED, BLACK, "[Error]"), nConfigTemplate[i][0]);\r
-          NoError = false;\r
-        }\r
-        else\r
-        {\r
-          Console->Print("%s using default value %s for option %s", Console->ColorText(GREEN, BLACK, "[Info]"), nConfigTemplate[i][1], nConfigTemplate[i][0]);\r
-          mOptions.insert(std::make_pair(nConfigTemplate[i][0], nConfigTemplate[i][1]));\r
-        }\r
-      }\r
-      ++i;\r
-    }\r
-  }\r
-\r
-  if (NoError)\r
-  {\r
-      if(nDepth)\r
-        Console->Print("%s file included", Console->ColorText(GREEN, BLACK, "[Info]") );\r
-      else\r
-      Console->Print("%s Configuration file loaded", Console->ColorText(GREEN, BLACK, "[Success]") );\r
-  }\r
-  else\r
-    Console->Print(RED, BLACK, "[Error] Fatal errors found in configuration file");\r
-\r
-    return (NoError);\r
-}\r
-\r
-const std::string &PConfig::GetOption(const std::string Name) const\r
-{\r
-    static std::string NullString = "";\r
-    OptionsMap::const_iterator i = mOptions.find(Name);\r
-    if(i!=mOptions.end())\r
-        return i->second;\r
-\r
-    return NullString;\r
-}\r
-\r
-int PConfig::GetOptionInt(const std::string Name) const\r
-{\r
-    OptionsMap::const_iterator i = mOptions.find(Name);\r
-    if(i!=mOptions.end())\r
-        return atoi(i->second.c_str());\r
-\r
-    return 0;\r
-}\r
+#include <cstring>
+#include "Common/Includes.hxx"
+
+PConfig::PConfig()
+{
+  mOptValRegEx = new RegEx("^\\s*([[:graph:]]+)\\s*=\\s*(.+?)\\s*$", PCRE_CASELESS);
+  mIncludeRegEx = new RegEx("^\\s*include\\s+([[:graph:]]+)\\s*$", PCRE_CASELESS);
+}
+
+PConfig::~PConfig()
+{
+  delete mOptValRegEx;
+  delete mIncludeRegEx;
+}
+
+bool PConfig::LoadOptions(const char* nConfigTemplate[][2], const char* nConfigFile, int nDepth)
+{
+    FILE *ConfigFile;
+    char line[255];
+    std::string Opt, Val;
+    //int numOptions = 0;
+    int i;
+    bool Found;
+    bool NoError = true;
+
+    ConfigFile = fopen(nConfigFile,"r");
+
+    if(!ConfigFile)
+    {
+        Console->Print("%s Cant open file \"%s\"", Console->ColorText(RED, BLACK, "[Error]"), nConfigFile);
+        return false;
+    }
+
+  if(nDepth)
+    Console->Print("%s Including file %s (nesting level %d)", Console->ColorText(GREEN, BLACK, "[Info]"), nConfigFile, nDepth);
+  else
+      Console->Print("%s Loading configuration file %s", Console->ColorText(GREEN, BLACK, "[Info]"), nConfigFile);
+
+    while(!feof(ConfigFile) && fgets(line, 255, ConfigFile))
+    {
+        //Console->Print("LINE: '%s'", line);
+        if (line[0] == '/' && line[1] == '/')
+        continue;
+
+        if(mOptValRegEx->Search(line))
+      {
+        Opt = mOptValRegEx->Match(1);
+        Val = mOptValRegEx->Match(2);
+        //Console->Print("'%s'='%s'", Opt.c_str(), Val.c_str());
+
+        Trim(&Opt);
+        Trim(&Val);
+        //Console->Print("'%s'='%s'", Opt.c_str(), Val.c_str());
+      }
+      else if(mIncludeRegEx->Search(line))
+      {
+        if(nDepth < CONFIG_MAXDEPTH)
+        {
+          std::string TargetName = mIncludeRegEx->Match(1);
+          std::string StartName = nConfigFile;
+          int BasenamePos = StartName.rfind("/");
+          if(BasenamePos > 0)
+            TargetName = StartName.substr(0, BasenamePos) + "/" + TargetName;
+
+          NoError = LoadOptions(nConfigTemplate, TargetName.c_str(), nDepth+1) && NoError;
+          continue;
+        }
+        else
+        {
+          Console->Print("%s Max nesting level (%d) reached. Can't include configuration file %s", Console->ColorText(RED, BLACK, "[Error]"), CONFIG_MAXDEPTH,mIncludeRegEx->Match(1));
+          NoError = false;
+        }
+      }
+      else
+      {
+          continue;
+      }
+
+      i = 0;
+      Found = false;
+      while(!Found && (nConfigTemplate[i][0][0] != '\0'))
+      {
+        if(!strcmp(Opt.c_str(), nConfigTemplate[i++][0]))
+        {
+          Found = true;
+          break;
+        }
+      }
+
+        if(!Opt.empty() && !Val.empty())
+        {
+            //Console->Print("#%d [%s] [%s]", numOptions, Opt.c_str(), Val.c_str());
+            if (Found)
+            {
+              if (GetOption(Opt) != "")
+              {
+                Console->Print("%s trying to set option %s more than once (old value '%s' - new value '%s' ignored)", Console->ColorText(YELLOW, BLACK, "[Warning]"), Opt.c_str(), GetOption(Opt).c_str(), Val.c_str());
+              }
+              else
+              {
+                //Console->Print(GREEN, BLACK, "New option %s set to %s", Opt.c_str(), Val.c_str());
+              mOptions.insert(std::make_pair(Opt, Val));
+            }
+          }
+          else
+          {
+             Console->Print("%s option %s unknow and ignored (value %s)", Console->ColorText(YELLOW, BLACK, "[Warning]"), Opt.c_str(), Val.c_str());
+          }
+        }
+    }
+
+  // Now check for completeness and set default values when needed and available
+  if(!nDepth) // Check only if we're at top level (ie. not in an included file)
+  {
+    i = 0;
+    while(nConfigTemplate[i][0][0] != '\0')
+    {
+      if (GetOption(nConfigTemplate[i][0]) == "")
+      {
+        if(nConfigTemplate[i][1][0] == '\0')
+        {
+          Console->Print("%s required option %s missing from config file", Console->ColorText(RED, BLACK, "[Error]"), nConfigTemplate[i][0]);
+          NoError = false;
+        }
+        else
+        {
+          Console->Print("%s using default value %s for option %s", Console->ColorText(GREEN, BLACK, "[Info]"), nConfigTemplate[i][1], nConfigTemplate[i][0]);
+          mOptions.insert(std::make_pair(nConfigTemplate[i][0], nConfigTemplate[i][1]));
+        }
+      }
+      ++i;
+    }
+  }
+
+  if (NoError)
+  {
+      if(nDepth)
+        Console->Print("%s file included", Console->ColorText(GREEN, BLACK, "[Info]") );
+      else
+      Console->Print("%s Configuration file loaded", Console->ColorText(GREEN, BLACK, "[Success]") );
+  }
+  else
+    Console->Print(RED, BLACK, "[Error] Fatal errors found in configuration file");
+
+    return (NoError);
+}
+
+const std::string &PConfig::GetOption(const std::string Name) const
+{
+    static std::string NullString = "";
+    OptionsMap::const_iterator i = mOptions.find(Name);
+    if(i!=mOptions.end())
+        return i->second;
+
+    return NullString;
+}
+
+int PConfig::GetOptionInt(const std::string Name) const
+{
+    OptionsMap::const_iterator i = mOptions.find(Name);
+    if(i!=mOptions.end())
+        return atoi(i->second.c_str());
+
+    return 0;
+}
index 0741022..8f605dd 100644 (file)
@@ -1,57 +1,57 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <iostream>\r
-#include <map>\r
-#include <string>\r
-\r
-class RegEx;\r
-\r
-class PConfig {\r
-private:\r
-    typedef std::map<std::string, std::string> OptionsMap;\r
-    OptionsMap mOptions;\r
-    RegEx *mOptValRegEx;\r
-    RegEx *mIncludeRegEx;\r
-\r
-    bool LoadOptions(const char *nConfigTemplate[][2], const char *nConfigFile, int32_t nDepth);\r
-\r
-public:\r
-    PConfig();\r
-    ~PConfig();\r
-\r
-    inline bool LoadOptions(const char *nConfigTemplate[][2], const char *nConfigFile)\r
-      { return LoadOptions(nConfigTemplate, nConfigFile, 0); }\r
-    inline const std::string &GetOption(const char *Name) const { return GetOption((std::string) Name); }\r
-    const std::string &GetOption(const std::string Name) const;\r
-    int32_t GetOptionInt(const char *Name) const { return GetOptionInt((std::string) Name); }\r
-    int32_t GetOptionInt(const std::string Name) const;\r
-};\r
-\r
-// Max nested includes\r
-#define CONFIG_MAXDEPTH 4\r
-\r
-/*\r
-  The list of valid config options is now set in the array ConfigTemplate\r
-  A default value can be set for each option, whiches makes the option optionnal in config file\r
-  If no default value is set, the option is mandatory.\r
-  Duplicate option entries in config file are also checked, and only the first value is kept\r
-  Unkown options are rejected\r
-  Duplicates, unkown and default use generate a warning in logs but don't break options loading\r
-  Missing mandatory option generate an error in log and break option loading (imediate return false)\r
-\r
-  The ConfigTemplate parameter must have the structure shown in the following exemple:\r
-\r
-const char* ConfigTemplate[][2] = {\r
-  // {option_name, default_value} if default_value is empty string, it means option is mandatory\r
-  // List ends with empty string for option_name\r
-  {"info_sql_host", "127.0.0.1"},\r
-  {"info_sql_port", "3306"},\r
-  {"info_sql_username", ""},\r
-  {"info_sql_password", ""},\r
-  {"", ""} // do not change this line (end mark)\r
-};\r
-\r
-*/\r
-\r
-extern class PConfig* Config;\r
+#pragma once
+
+#include <cstdint>
+#include <iostream>
+#include <map>
+#include <string>
+
+class RegEx;
+
+class PConfig {
+private:
+    typedef std::map<std::string, std::string> OptionsMap;
+    OptionsMap mOptions;
+    RegEx *mOptValRegEx;
+    RegEx *mIncludeRegEx;
+
+    bool LoadOptions(const char *nConfigTemplate[][2], const char *nConfigFile, int32_t nDepth);
+
+public:
+    PConfig();
+    ~PConfig();
+
+    inline bool LoadOptions(const char *nConfigTemplate[][2], const char *nConfigFile)
+      { return LoadOptions(nConfigTemplate, nConfigFile, 0); }
+    inline const std::string &GetOption(const char *Name) const { return GetOption((std::string) Name); }
+    const std::string &GetOption(const std::string Name) const;
+    int32_t GetOptionInt(const char *Name) const { return GetOptionInt((std::string) Name); }
+    int32_t GetOptionInt(const std::string Name) const;
+};
+
+// Max nested includes
+#define CONFIG_MAXDEPTH 4
+
+/*
+  The list of valid config options is now set in the array ConfigTemplate
+  A default value can be set for each option, whiches makes the option optionnal in config file
+  If no default value is set, the option is mandatory.
+  Duplicate option entries in config file are also checked, and only the first value is kept
+  Unkown options are rejected
+  Duplicates, unkown and default use generate a warning in logs but don't break options loading
+  Missing mandatory option generate an error in log and break option loading (imediate return false)
+
+  The ConfigTemplate parameter must have the structure shown in the following exemple:
+
+const char* ConfigTemplate[][2] = {
+  // {option_name, default_value} if default_value is empty string, it means option is mandatory
+  // List ends with empty string for option_name
+  {"info_sql_host", "127.0.0.1"},
+  {"info_sql_port", "3306"},
+  {"info_sql_username", ""},
+  {"info_sql_password", ""},
+  {"", ""} // do not change this line (end mark)
+};
+
+*/
+
+extern class PConfig* Config;
index cc12a3b..a222c7c 100644 (file)
-#include <cstdarg>\r
-#include <sstream>\r
-#include <cstring>\r
-#include "Common/Includes.hxx"\r
-\r
-PConsole::PConsole(const char *nLogFile)\r
-{\r
-       std::time(&mLastLogTime);\r
-       mLogFile.open(nLogFile);\r
-}\r
-\r
-PConsole::~PConsole()\r
-{\r
-    Print("%s Shutdown complete", ColorText(GREEN, BLACK, "[Done]"));\r
-       mLogFile.close();\r
-}\r
-\r
-void PConsole::Print(const char *Fmt, ...)\r
-{\r
-       static char Str[2048];\r
-       va_list args;\r
-       va_start(args, Fmt);\r
-       vsnprintf(Str, 2047, Fmt, args);\r
-       va_end(args);\r
-\r
-       std::time(&mLastLogTime);\r
-       std::tm *now = std::localtime(&mLastLogTime);\r
-\r
-       static char datestr[64];\r
-       std::snprintf(datestr, 64, "%02i/%02i %02i:%02i:%02i ", now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);\r
-       std::stringstream str;\r
-       str << datestr << Str << std::endl;\r
-\r
-       std::printf("%s", str.str().c_str());\r
-       mLogFile << str.str();\r
-       mLogFile.flush();\r
-}\r
-\r
-void PConsole::Print(COLORS foreground, COLORS background, const char *Fmt, ...)\r
-{\r
-       static char Str[2048];\r
-       va_list args;\r
-       va_start(args, Fmt);\r
-       vsnprintf(Str, 2047, Fmt, args);\r
-       va_end(args);\r
-\r
-    char c_color[13];\r
-    char c_reset[13];\r
-    std::snprintf(c_color, 13, "%c[%d;%d;%dm", 0x1B, 0, foreground + 30, background + 40);\r
-    std::snprintf(c_reset, 13, "%c[%d;%d;%dm", 0x1B, 0, 37, 40);\r
-\r
-       std::time(&mLastLogTime);\r
-       std::tm *now = std::localtime(&mLastLogTime);\r
-\r
-       static char datestr[64];\r
-       std::snprintf(datestr, 64, "%02i/%02i %02i:%02i:%02i ", now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);\r
-       std::stringstream str;\r
-       str << datestr << c_color << Str << c_reset << std::endl;\r
-\r
-       std::printf("%s", str.str().c_str());\r
-       mLogFile << str.str();\r
-\r
-       mLogFile.flush();\r
-}\r
-\r
-char *PConsole::ColorText(COLORS foreground, COLORS background, const char *Fmt, ...)\r
-{\r
-       static char Str[2048];\r
-       va_list args;\r
-       va_start(args, Fmt);\r
-       vsnprintf(Str, 2047, Fmt, args);\r
-       va_end(args);\r
-\r
-  char c_color[13];\r
-  char c_reset[13];\r
-  std::snprintf(c_color, 13, "%c[%d;%d;%dm", 0x1B, 0, foreground + 30, background + 40);\r
-  std::snprintf(c_reset, 13, "%c[%d;%d;%dm", 0x1B, 0, 37, 40);\r
-\r
-  static char returnbuffer[2048];\r
-       strncpy (returnbuffer, c_color, 2048);\r
-       strncat (returnbuffer, Str, 2047 - strlen(returnbuffer));\r
-       strncat (returnbuffer, c_reset, 2047 - strlen(returnbuffer));\r
-\r
-       return returnbuffer;\r
-}\r
-\r
-void PConsole::LPrint(const char *Fmt, ...)\r
-{\r
-       static char Str[2048];\r
-       va_list args;\r
-       va_start(args, Fmt);\r
-       vsnprintf(Str, 2047, Fmt, args);\r
-       va_end(args);\r
-\r
-       std::time(&mLastLogTime);\r
-       std::tm *now = std::localtime(&mLastLogTime);\r
-\r
-       static char datestr[64];\r
-       std::snprintf(datestr, 64, "%02i/%02i %02i:%02i:%02i ", now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);\r
-       std::stringstream str;\r
-       str << datestr << Str;\r
-\r
-       std::printf("%s", str.str().c_str());\r
-       mLogFile << str.str();\r
-       mLogFile.flush();\r
-}\r
-\r
-void PConsole::LPrint(COLORS foreground, COLORS background, const char *Fmt, ...)\r
-{\r
-    static char Str[2048];\r
-       va_list args;\r
-       va_start(args, Fmt);\r
-       vsnprintf(Str, 2047, Fmt, args);\r
-       va_end(args);\r
-\r
-    char c_color[13];\r
-    char c_reset[13];\r
-    std::snprintf(c_color, 13, "%c[%d;%d;%dm", 0x1B, 0, foreground + 30, background + 40);\r
-    std::snprintf(c_reset, 13, "%c[%d;%d;%dm", 0x1B, 0, 37, 40);\r
-\r
-       std::stringstream str;\r
-       str << c_color << Str << c_reset;\r
-\r
-       std::printf("%s", str.str().c_str());\r
-       mLogFile << str.str();\r
-\r
-       mLogFile.flush();\r
-}\r
-\r
-void PConsole::LClose()\r
-{\r
-       std::stringstream str;\r
-       str << std::endl;\r
-\r
-       std::printf("%s", str.str().c_str());\r
-       mLogFile << str.str();\r
-\r
-       mLogFile.flush();\r
-}\r
-\r
-void PConsole::Update()\r
-{\r
-       // place a marker into the log each 15 minutes if no output has been generated\r
-       std::time_t t;\r
-       std::time(&t);\r
-       if(std::difftime(t, mLastLogTime) >= 900)\r
-               Print("--MARK--");\r
-}\r
+#include <cstdarg>
+#include <sstream>
+#include <cstring>
+#include "Common/Includes.hxx"
+
+PConsole::PConsole(const char *nLogFile)
+{
+       std::time(&mLastLogTime);
+       mLogFile.open(nLogFile);
+}
+
+PConsole::~PConsole()
+{
+    Print("%s Shutdown complete", ColorText(GREEN, BLACK, "[Done]"));
+       mLogFile.close();
+}
+
+void PConsole::Print(const char *Fmt, ...)
+{
+       static char Str[2048];
+       va_list args;
+       va_start(args, Fmt);
+       vsnprintf(Str, 2047, Fmt, args);
+       va_end(args);
+
+       std::time(&mLastLogTime);
+       std::tm *now = std::localtime(&mLastLogTime);
+
+       static char datestr[64];
+       std::snprintf(datestr, 64, "%02i/%02i %02i:%02i:%02i ", now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
+       std::stringstream str;
+       str << datestr << Str << std::endl;
+
+       std::printf("%s", str.str().c_str());
+       mLogFile << str.str();
+       mLogFile.flush();
+}
+
+void PConsole::Print(COLORS foreground, COLORS background, const char *Fmt, ...)
+{
+       static char Str[2048];
+       va_list args;
+       va_start(args, Fmt);
+       vsnprintf(Str, 2047, Fmt, args);
+       va_end(args);
+
+    char c_color[13];
+    char c_reset[13];
+    std::snprintf(c_color, 13, "%c[%d;%d;%dm", 0x1B, 0, foreground + 30, background + 40);
+    std::snprintf(c_reset, 13, "%c[%d;%d;%dm", 0x1B, 0, 37, 40);
+
+       std::time(&mLastLogTime);
+       std::tm *now = std::localtime(&mLastLogTime);
+
+       static char datestr[64];
+       std::snprintf(datestr, 64, "%02i/%02i %02i:%02i:%02i ", now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
+       std::stringstream str;
+       str << datestr << c_color << Str << c_reset << std::endl;
+
+       std::printf("%s", str.str().c_str());
+       mLogFile << str.str();
+
+       mLogFile.flush();
+}
+
+char *PConsole::ColorText(COLORS foreground, COLORS background, const char *Fmt, ...)
+{
+       static char Str[2048];
+       va_list args;
+       va_start(args, Fmt);
+       vsnprintf(Str, 2047, Fmt, args);
+       va_end(args);
+
+  char c_color[13];
+  char c_reset[13];
+  std::snprintf(c_color, 13, "%c[%d;%d;%dm", 0x1B, 0, foreground + 30, background + 40);
+  std::snprintf(c_reset, 13, "%c[%d;%d;%dm", 0x1B, 0, 37, 40);
+
+  static char returnbuffer[2048];
+       strncpy (returnbuffer, c_color, 2048);
+       strncat (returnbuffer, Str, 2047 - strlen(returnbuffer));
+       strncat (returnbuffer, c_reset, 2047 - strlen(returnbuffer));
+
+       return returnbuffer;
+}
+
+void PConsole::LPrint(const char *Fmt, ...)
+{
+       static char Str[2048];
+       va_list args;
+       va_start(args, Fmt);
+       vsnprintf(Str, 2047, Fmt, args);
+       va_end(args);
+
+       std::time(&mLastLogTime);
+       std::tm *now = std::localtime(&mLastLogTime);
+
+       static char datestr[64];
+       std::snprintf(datestr, 64, "%02i/%02i %02i:%02i:%02i ", now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
+       std::stringstream str;
+       str << datestr << Str;
+
+       std::printf("%s", str.str().c_str());
+       mLogFile << str.str();
+       mLogFile.flush();
+}
+
+void PConsole::LPrint(COLORS foreground, COLORS background, const char *Fmt, ...)
+{
+    static char Str[2048];
+       va_list args;
+       va_start(args, Fmt);
+       vsnprintf(Str, 2047, Fmt, args);
+       va_end(args);
+
+    char c_color[13];
+    char c_reset[13];
+    std::snprintf(c_color, 13, "%c[%d;%d;%dm", 0x1B, 0, foreground + 30, background + 40);
+    std::snprintf(c_reset, 13, "%c[%d;%d;%dm", 0x1B, 0, 37, 40);
+
+       std::stringstream str;
+       str << c_color << Str << c_reset;
+
+       std::printf("%s", str.str().c_str());
+       mLogFile << str.str();
+
+       mLogFile.flush();
+}
+
+void PConsole::LClose()
+{
+       std::stringstream str;
+       str << std::endl;
+
+       std::printf("%s", str.str().c_str());
+       mLogFile << str.str();
+
+       mLogFile.flush();
+}
+
+void PConsole::Update()
+{
+       // place a marker into the log each 15 minutes if no output has been generated
+       std::time_t t;
+       std::time(&t);
+       if(std::difftime(t, mLastLogTime) >= 900)
+               Print("--MARK--");
+}
index 8b610c4..fc477a7 100644 (file)
@@ -1,35 +1,35 @@
-#pragma once\r
-\r
-#include <chrono>\r
-#include <fstream>\r
-\r
-enum COLORS {\r
-    BLACK,\r
-    RED,\r
-    GREEN,\r
-    YELLOW,\r
-    BLUE,\r
-    MAGENTA,\r
-    CYAN,\r
-    WHITE\r
-};\r
-\r
-class PConsole {\r
-private:\r
-       std::ofstream mLogFile;\r
-       time_t mLastLogTime;\r
-\r
-public:\r
-       PConsole(const char *nLogFile);\r
-       ~PConsole();\r
-       void Print(const char *Fmt_, ...);\r
-       void Print(COLORS foreground, COLORS background, const char *Fmt_, ...);\r
-       char *ColorText(COLORS foreground, COLORS background, const char *Fmt, ...);\r
-\r
-       void LPrint(const char *Fmt_, ...);\r
-       void LPrint(COLORS foreground, COLORS background, const char *Fmt_, ...);\r
-       void LClose();\r
-       void Update();\r
-};\r
-\r
-extern class PConsole *Console;\r
+#pragma once
+
+#include <chrono>
+#include <fstream>
+
+enum COLORS {
+    BLACK,
+    RED,
+    GREEN,
+    YELLOW,
+    BLUE,
+    MAGENTA,
+    CYAN,
+    WHITE
+};
+
+class PConsole {
+private:
+       std::ofstream mLogFile;
+       time_t mLastLogTime;
+
+public:
+       PConsole(const char *nLogFile);
+       ~PConsole();
+       void Print(const char *Fmt_, ...);
+       void Print(COLORS foreground, COLORS background, const char *Fmt_, ...);
+       char *ColorText(COLORS foreground, COLORS background, const char *Fmt, ...);
+
+       void LPrint(const char *Fmt_, ...);
+       void LPrint(COLORS foreground, COLORS background, const char *Fmt_, ...);
+       void LClose();
+       void Update();
+};
+
+extern class PConsole *Console;
index 633b79d..0cbc179 100644 (file)
-#include <cstring>\r
-#include <sstream>\r
-#include <zlib.h>\r
-#include "Common/Includes.hxx"\r
-\r
-const int8_t DELIM = '/';\r
-\r
-PFile::PFile()\r
-{\r
-       mDataSize=0;\r
-       mDataOffs=0;\r
-}\r
-\r
-PFile::~PFile()\r
-{\r
-}\r
-\r
-bool PFile::ReadData(FILE *F, uint32_t Size)\r
-{\r
-       mBuffer.reserve(Size);\r
-       std::fread(&mBuffer[0], 1, Size, F);\r
-       mDataSize = Size;\r
-       return true;\r
-}\r
-\r
-bool PFile::ReadUnpakData(FILE *F, uint32_t Size, uint32_t UncSize)\r
-{\r
-       std::vector<int8_t> temp;\r
-       temp.reserve(Size);\r
-       mBuffer.reserve(UncSize);\r
-\r
-       std::fread(&temp[0], 1, Size, F);\r
-\r
-       unsigned long us=UncSize;\r
-       unsigned long s=Size;\r
-       uncompress(reinterpret_cast<Bytef *>(&mBuffer[0]), &us, reinterpret_cast<const Bytef *>(&temp[0]), s);\r
-       mDataSize=us;\r
-       return true;\r
-}\r
-\r
-int PFile::Read(void *Dest, uint32_t DestSize)\r
-{\r
-       int m = std::min(mDataSize-mDataOffs, DestSize);\r
-       if (m <= 0)\r
-         return 0;\r
-       memcpy(Dest, &mBuffer[mDataOffs], m);\r
-       mDataOffs+=m;\r
-       return m;\r
-}\r
-\r
-void PFile::Seek(uint32_t Offset)\r
-{\r
-       mDataOffs = std::min(mDataSize-1, Offset);\r
-}\r
-\r
-std::string PFile::ReadString()\r
-{\r
-       int l=0;\r
-       int s=mDataOffs;\r
-       char last=0;\r
-       while(mDataOffs < mDataSize && last!='\n')\r
-       {\r
-               last=mBuffer[mDataOffs++];\r
-               l++;\r
-       }\r
-\r
-       char *str = new char[l+1];\r
-       std::memcpy(str, &mBuffer[s], l);\r
-       str[l]=0;\r
-\r
-       std::string Result = str;\r
-       delete str;\r
-       return Result;\r
-}\r
-\r
-// ---------------\r
-\r
-PFileSystem::PFileSystem()\r
-{\r
-}\r
-\r
-PFileSystem::~PFileSystem()\r
-{\r
-       for(PPakFiles::iterator i=mPaks.begin(); i!=mPaks.end(); i++)\r
-       {\r
-               PPakFileList *list = i->second;\r
-               for(PPakFileList::iterator j=list->begin(); j!=list->end(); j++)\r
-                       delete j->second;\r
-               delete i->second;\r
-       }\r
-}\r
-\r
-PFileSystem::PPakFileList* PFileSystem::CachePak(const std::string &Pak, FILE *F)\r
-{\r
-       PPakFiles::iterator n = mPaks.find(Pak);\r
-       if(n != mPaks.end())\r
-               return n->second;\r
-\r
-       if(!F)\r
-               return 0;\r
-\r
-       PPakFileList *Result = 0;\r
-\r
-       int off = std::ftell(F);\r
-       std::fseek(F, 0, SEEK_SET);\r
-       PPakHeader header;\r
-       std::fread(&header, 1, sizeof(header), F);\r
-       if(header.mID==0x3d458cde && header.mNumFiles > 0)\r
-       {\r
-               Result = new PPakFileList();\r
-               for(int i=0; i<header.mNumFiles; i++)\r
-               {\r
-                       PPakFileHeader *h = new PPakFileHeader();\r
-                       std::fread(h, 1, 20, F);\r
-                       h->mFilename = new char[h->mNameLen+1];\r
-                       std::fread(h->mFilename, 1, h->mNameLen, F);\r
-                       Result->insert(std::make_pair(h->mFilename, h));\r
-               }\r
-               mPaks.insert(std::make_pair(Pak, Result));\r
-//Console->Print("%s: %i files registered", Pak.c_str(), header.mNumFiles);\r
-       } else\r
-       {\r
-               Console->Print("%s: invalid pakfile", Pak.c_str());\r
-       }\r
-       std::fseek(F, off, SEEK_SET);\r
-       return Result;\r
-}\r
-\r
-void PFileSystem::ClearCache()\r
-{\r
-  PFileSystem::PPakFiles::iterator nPak;\r
-  PFileSystem::PPakFileList::iterator nFList;\r
-  PPakFileHeader* FHeader;\r
-  PFileSystem::PPakFileList* FList;\r
-  \r
-  for( nPak = mPaks.begin(); nPak != mPaks.end(); nPak++)\r
-  {\r
-    FList = nPak->second;\r
-    for( nFList = FList->begin(); nFList != FList->end(); nFList++)\r
-    {\r
-      FHeader = nFList->second;\r
-      FList->erase(nFList);\r
-      delete[] FHeader->mFilename;\r
-      delete FHeader;\r
-    }\r
-    mPaks.erase(nPak);\r
-    delete FList;\r
-  }\r
-}\r
-\r
-void splitpath(const std::string& file, std::string& path, std::string& name, std::string& ext)\r
-{\r
-       unsigned long pos = file.rfind(DELIM);\r
-\r
-       if (pos == std::string::npos)\r
-       {\r
-               path = "";\r
-               name = file;\r
-       }\r
-       else\r
-       {\r
-               path = file.substr(0, pos);\r
-               name = file.substr(pos + 1);\r
-       }\r
-\r
-       pos = name.rfind('.');\r
-       if (pos == std::string::npos)\r
-       {\r
-               ext = "";\r
-       }\r
-       else\r
-       {\r
-               ext = name.substr(pos + 1);\r
-               name = name.substr(0, pos);\r
-       }\r
-}\r
-\r
-PFile *PFileSystem::Open(const std::string& Package, const char *File, std::string BasePath)\r
-{\r
-             std::string name = "";\r
-        std::string ext = "";\r
-        std::string path = "";\r
-        splitpath(File, path, name, ext);\r
-\r
-        std::string pak2;\r
-        std::string name2;\r
-\r
-        if ((BasePath == ".") || (BasePath == "./"))\r
-        {\r
-          BasePath = "";\r
-        }\r
-        else\r
-        {\r
-          if (BasePath.substr(0, 2) == "./")\r
-          {\r
-            BasePath = BasePath.substr(2, BasePath.length() -2);\r
-          }\r
-          if ( BasePath[BasePath.length()-1] != '/' )\r
-          {\r
-            BasePath += '/';\r
-          }\r
-        }\r
-//Console->Print("Basepath:%s", BasePath.c_str());\r
-     \r
-        std::string pak = Package;\r
-        if(pak=="")\r
-        {\r
-           pak=path;\r
-           if (path.substr(0, 2) == "./")\r
-           {\r
-              path = path.substr(2, path.length() -2);\r
-           }\r
-           unsigned long pos = path.find(DELIM);\r
-               if (pos == std::string::npos)\r
-               {\r
-                       pak2 = path;\r
-                       name2 = name;\r
-               }\r
-               else\r
-               {\r
-                       pak2 = path.substr(0, pos);\r
-                       name2 = path.substr(pos + 1) + '\\' + name;\r
-                       pos = name2.find(DELIM);\r
-                       while (pos != std::string::npos)\r
-                       {\r
-                         name2[pos] = '\\';\r
-                         pos = name2.find(DELIM);\r
-                       }\r
-               }\r
-        }          \r
-\r
-        std::stringstream package;\r
-        //package << pak << ".pak" << '\0';\r
-        package << BasePath << pak2 << ".pak" << '\0';\r
-        std::stringstream fname;\r
-        fname << BasePath << pak << '/' << name << "." << ext << '\0';\r
-        std::stringstream pakname;\r
-        pakname << BasePath << pak << "/pak_" << name << "." << ext << '\0';\r
-\r
-        std::FILE *f = std::fopen(fname.str().c_str(), "rb");\r
-        if(f)\r
-        {\r
-                PFile *Result = new PFile();\r
-                std::fseek(f, 0, SEEK_END);\r
-                int s = std::ftell(f);\r
-                std::fseek(f, 0, SEEK_SET);\r
-                Result->ReadData(f, s);\r
-                std::fclose(f);\r
-                return Result;\r
-        }\r
-//else\r
-//  Console->Print("File not found:%s", fname.str().c_str());\r
-        f = std::fopen(pakname.str().c_str(), "rb");\r
-        if(f)\r
-        {\r
-                PFile *Result = new PFile();\r
-                std::fseek(f, 0, SEEK_END);\r
-                int s = std::ftell(f)-16;\r
-                std::fseek(f, 12, SEEK_SET);\r
-                int os;\r
-                std::fread(&os, 1, 4, f);\r
-                Result->ReadUnpakData(f, s, os);\r
-                std::fclose(f);\r
-                return Result;\r
-        }\r
-//else\r
-//  Console->Print("Pak_ not found:%s", pakname.str().c_str());\r
-  \r
-//Console->Print("Serching package %s, file %s.%s", package.str().c_str(), name2.c_str(), ext.c_str());\r
-        f = std::fopen(package.str().c_str(), "rb");\r
-        if(f)\r
-        {\r
-                //std::string filename = name;\r
-                std::string filename = name2 + "." + ext;\r
-                           //filename.append(ext);\r
-\r
-                PPakFileHeader *file = 0;\r
-                PPakFileList *list = CachePak(std::string(package.str()), f);\r
-                for(PPakFileList::iterator i=list->begin(); i!=list->end(); i++)\r
-                {\r
-                        PPakFileHeader *h = i->second;\r
-                        if(!strcasecmp(i->first.c_str(), filename.c_str()))\r
-                        {\r
-                                file = h;\r
-                                break;\r
-                        }\r
-                }\r
-                PFile *Result = 0;\r
-                if(list && file)\r
-                {\r
-                        Result = new PFile();\r
-                        std::fseek(f, file->mOffset, SEEK_SET);\r
-                        Result->ReadUnpakData(f, file->mCompressedSize, file->mUncompressedSize);\r
-//Console->Print("%s, %s: file found", package.str().c_str(), filename.c_str());\r
-                }\r
-                else\r
-                {\r
-                        if(!list)\r
-                                //Console->Print("%s, %s: pak error", Package.c_str(), File);\r
-                                Console->Print("%s, %s: pak error", package.str().c_str(), File);\r
-//else\r
-//if(!file)\r
-//Console->Print("%s, %s: file not found", Package.c_str(), File);\r
-//  Console->Print("%s, %s: file not found", package.str().c_str(), filename.c_str());\r
-                }\r
-\r
-                std::fclose(f);\r
-                return Result;\r
-        }\r
-\r
-        return 0;\r
-}\r
-\r
-bool PFileSystem::Close(PFile *File)\r
-{\r
-       delete File;\r
-       return true;\r
-}\r
-\r
+#include <cstring>
+#include <sstream>
+#include <zlib.h>
+#include "Common/Includes.hxx"
+
+const int8_t DELIM = '/';
+
+PFile::PFile()
+{
+       mDataSize=0;
+       mDataOffs=0;
+}
+
+PFile::~PFile()
+{
+}
+
+bool PFile::ReadData(FILE *F, uint32_t Size)
+{
+       mBuffer.reserve(Size);
+       std::fread(&mBuffer[0], 1, Size, F);
+       mDataSize = Size;
+       return true;
+}
+
+bool PFile::ReadUnpakData(FILE *F, uint32_t Size, uint32_t UncSize)
+{
+       std::vector<int8_t> temp;
+       temp.reserve(Size);
+       mBuffer.reserve(UncSize);
+
+       std::fread(&temp[0], 1, Size, F);
+
+       unsigned long us=UncSize;
+       unsigned long s=Size;
+       uncompress(reinterpret_cast<Bytef *>(&mBuffer[0]), &us, reinterpret_cast<const Bytef *>(&temp[0]), s);
+       mDataSize=us;
+       return true;
+}
+
+int PFile::Read(void *Dest, uint32_t DestSize)
+{
+       int m = std::min(mDataSize-mDataOffs, DestSize);
+       if (m <= 0)
+         return 0;
+       memcpy(Dest, &mBuffer[mDataOffs], m);
+       mDataOffs+=m;
+       return m;
+}
+
+void PFile::Seek(uint32_t Offset)
+{
+       mDataOffs = std::min(mDataSize-1, Offset);
+}
+
+std::string PFile::ReadString()
+{
+       int l=0;
+       int s=mDataOffs;
+       char last=0;
+       while(mDataOffs < mDataSize && last!='\n')
+       {
+               last=mBuffer[mDataOffs++];
+               l++;
+       }
+
+       char *str = new char[l+1];
+       std::memcpy(str, &mBuffer[s], l);
+       str[l]=0;
+
+       std::string Result = str;
+       delete str;
+       return Result;
+}
+
+// ---------------
+
+PFileSystem::PFileSystem()
+{
+}
+
+PFileSystem::~PFileSystem()
+{
+       for(PPakFiles::iterator i=mPaks.begin(); i!=mPaks.end(); i++)
+       {
+               PPakFileList *list = i->second;
+               for(PPakFileList::iterator j=list->begin(); j!=list->end(); j++)
+                       delete j->second;
+               delete i->second;
+       }
+}
+
+PFileSystem::PPakFileList* PFileSystem::CachePak(const std::string &Pak, FILE *F)
+{
+       PPakFiles::iterator n = mPaks.find(Pak);
+       if(n != mPaks.end())
+               return n->second;
+
+       if(!F)
+               return 0;
+
+       PPakFileList *Result = 0;
+
+       int off = std::ftell(F);
+       std::fseek(F, 0, SEEK_SET);
+       PPakHeader header;
+       std::fread(&header, 1, sizeof(header), F);
+       if(header.mID==0x3d458cde && header.mNumFiles > 0)
+       {
+               Result = new PPakFileList();
+               for(int i=0; i<header.mNumFiles; i++)
+               {
+                       PPakFileHeader *h = new PPakFileHeader();
+                       std::fread(h, 1, 20, F);
+                       h->mFilename = new char[h->mNameLen+1];
+                       std::fread(h->mFilename, 1, h->mNameLen, F);
+                       Result->insert(std::make_pair(h->mFilename, h));
+               }
+               mPaks.insert(std::make_pair(Pak, Result));
+//Console->Print("%s: %i files registered", Pak.c_str(), header.mNumFiles);
+       } else
+       {
+               Console->Print("%s: invalid pakfile", Pak.c_str());
+       }
+       std::fseek(F, off, SEEK_SET);
+       return Result;
+}
+
+void PFileSystem::ClearCache()
+{
+  PFileSystem::PPakFiles::iterator nPak;
+  PFileSystem::PPakFileList::iterator nFList;
+  PPakFileHeader* FHeader;
+  PFileSystem::PPakFileList* FList;
+  
+  for( nPak = mPaks.begin(); nPak != mPaks.end(); nPak++)
+  {
+    FList = nPak->second;
+    for( nFList = FList->begin(); nFList != FList->end(); nFList++)
+    {
+      FHeader = nFList->second;
+      FList->erase(nFList);
+      delete[] FHeader->mFilename;
+      delete FHeader;
+    }
+    mPaks.erase(nPak);
+    delete FList;
+  }
+}
+
+void splitpath(const std::string& file, std::string& path, std::string& name, std::string& ext)
+{
+       unsigned long pos = file.rfind(DELIM);
+
+       if (pos == std::string::npos)
+       {
+               path = "";
+               name = file;
+       }
+       else
+       {
+               path = file.substr(0, pos);
+               name = file.substr(pos + 1);
+       }
+
+       pos = name.rfind('.');
+       if (pos == std::string::npos)
+       {
+               ext = "";
+       }
+       else
+       {
+               ext = name.substr(pos + 1);
+               name = name.substr(0, pos);
+       }
+}
+
+PFile *PFileSystem::Open(const std::string& Package, const char *File, std::string BasePath)
+{
+             std::string name = "";
+        std::string ext = "";
+        std::string path = "";
+        splitpath(File, path, name, ext);
+
+        std::string pak2;
+        std::string name2;
+
+        if ((BasePath == ".") || (BasePath == "./"))
+        {
+          BasePath = "";
+        }
+        else
+        {
+          if (BasePath.substr(0, 2) == "./")
+          {
+            BasePath = BasePath.substr(2, BasePath.length() -2);
+          }
+          if ( BasePath[BasePath.length()-1] != '/' )
+          {
+            BasePath += '/';
+          }
+        }
+//Console->Print("Basepath:%s", BasePath.c_str());
+     
+        std::string pak = Package;
+        if(pak=="")
+        {
+           pak=path;
+           if (path.substr(0, 2) == "./")
+           {
+              path = path.substr(2, path.length() -2);
+           }
+           unsigned long pos = path.find(DELIM);
+               if (pos == std::string::npos)
+               {
+                       pak2 = path;
+                       name2 = name;
+               }
+               else
+               {
+                       pak2 = path.substr(0, pos);
+                       name2 = path.substr(pos + 1) + '\\' + name;
+                       pos = name2.find(DELIM);
+                       while (pos != std::string::npos)
+                       {
+                         name2[pos] = '\\';
+                         pos = name2.find(DELIM);
+                       }
+               }
+        }          
+
+        std::stringstream package;
+        //package << pak << ".pak" << '\0';
+        package << BasePath << pak2 << ".pak" << '\0';
+        std::stringstream fname;
+        fname << BasePath << pak << '/' << name << "." << ext << '\0';
+        std::stringstream pakname;
+        pakname << BasePath << pak << "/pak_" << name << "." << ext << '\0';
+
+        std::FILE *f = std::fopen(fname.str().c_str(), "rb");
+        if(f)
+        {
+                PFile *Result = new PFile();
+                std::fseek(f, 0, SEEK_END);
+                int s = std::ftell(f);
+                std::fseek(f, 0, SEEK_SET);
+                Result->ReadData(f, s);
+                std::fclose(f);
+                return Result;
+        }
+//else
+//  Console->Print("File not found:%s", fname.str().c_str());
+        f = std::fopen(pakname.str().c_str(), "rb");
+        if(f)
+        {
+                PFile *Result = new PFile();
+                std::fseek(f, 0, SEEK_END);
+                int s = std::ftell(f)-16;
+                std::fseek(f, 12, SEEK_SET);
+                int os;
+                std::fread(&os, 1, 4, f);
+                Result->ReadUnpakData(f, s, os);
+                std::fclose(f);
+                return Result;
+        }
+//else
+//  Console->Print("Pak_ not found:%s", pakname.str().c_str());
+  
+//Console->Print("Serching package %s, file %s.%s", package.str().c_str(), name2.c_str(), ext.c_str());
+        f = std::fopen(package.str().c_str(), "rb");
+        if(f)
+        {
+                //std::string filename = name;
+                std::string filename = name2 + "." + ext;
+                           //filename.append(ext);
+
+                PPakFileHeader *file = 0;
+                PPakFileList *list = CachePak(std::string(package.str()), f);
+                for(PPakFileList::iterator i=list->begin(); i!=list->end(); i++)
+                {
+                        PPakFileHeader *h = i->second;
+                        if(!strcasecmp(i->first.c_str(), filename.c_str()))
+                        {
+                                file = h;
+                                break;
+                        }
+                }
+                PFile *Result = 0;
+                if(list && file)
+                {
+                        Result = new PFile();
+                        std::fseek(f, file->mOffset, SEEK_SET);
+                        Result->ReadUnpakData(f, file->mCompressedSize, file->mUncompressedSize);
+//Console->Print("%s, %s: file found", package.str().c_str(), filename.c_str());
+                }
+                else
+                {
+                        if(!list)
+                                //Console->Print("%s, %s: pak error", Package.c_str(), File);
+                                Console->Print("%s, %s: pak error", package.str().c_str(), File);
+//else
+//if(!file)
+//Console->Print("%s, %s: file not found", Package.c_str(), File);
+//  Console->Print("%s, %s: file not found", package.str().c_str(), filename.c_str());
+                }
+
+                std::fclose(f);
+                return Result;
+        }
+
+        return 0;
+}
+
+bool PFileSystem::Close(PFile *File)
+{
+       delete File;
+       return true;
+}
+
index 00366bd..6cd0100 100644 (file)
@@ -1,55 +1,55 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-#include <vector>\r
-\r
-class PFile {\r
-       friend class PFileSystem;\r
-private:\r
-       std::vector<int8_t> mBuffer;\r
-       uint32_t mDataSize;\r
-       uint32_t mDataOffs;\r
-       bool ReadData(FILE *F, uint32_t Size);\r
-       bool ReadUnpakData(FILE *F, uint32_t Size, uint32_t UncSize);\r
-\r
-public:\r
-       PFile();\r
-       ~PFile();\r
-       inline bool Eof() { return mDataOffs>=mDataSize; }\r
-       int Read(void *Dest, uint32_t DestSize);\r
-       void Seek(uint32_t Offset);\r
-       std::string ReadString();\r
-       inline uint32_t GetSize() const { return mDataSize; }\r
-};\r
-\r
-#pragma pack(push, 1)\r
-struct PPakHeader {\r
-       int mID;\r
-       int mNumFiles;\r
-};\r
-\r
-struct PPakFileHeader {\r
-       int mUnknown0;\r
-       int mOffset;\r
-       int mCompressedSize;\r
-       int mUncompressedSize;\r
-       int mNameLen;   // including 0\r
-       char *mFilename;\r
-};\r
-#pragma pack(pop)\r
-\r
-class PFileSystem {\r
-private:\r
-       typedef std::map<std::string, PPakFileHeader*> PPakFileList;\r
-       typedef std::map<std::string, PPakFileList*> PPakFiles;\r
-       PPakFiles mPaks;\r
-       PPakFileList *CachePak(const std::string &Pak, FILE *F);\r
-\r
-public:\r
-       PFileSystem();\r
-       ~PFileSystem();\r
-       PFile *Open(const std::string &Package, const char *File, std::string BasePath);\r
-       bool Close(PFile *File);\r
-       void ClearCache();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <vector>
+
+class PFile {
+       friend class PFileSystem;
+private:
+       std::vector<int8_t> mBuffer;
+       uint32_t mDataSize;
+       uint32_t mDataOffs;
+       bool ReadData(FILE *F, uint32_t Size);
+       bool ReadUnpakData(FILE *F, uint32_t Size, uint32_t UncSize);
+
+public:
+       PFile();
+       ~PFile();
+       inline bool Eof() { return mDataOffs>=mDataSize; }
+       int Read(void *Dest, uint32_t DestSize);
+       void Seek(uint32_t Offset);
+       std::string ReadString();
+       inline uint32_t GetSize() const { return mDataSize; }
+};
+
+#pragma pack(push, 1)
+struct PPakHeader {
+       int mID;
+       int mNumFiles;
+};
+
+struct PPakFileHeader {
+       int mUnknown0;
+       int mOffset;
+       int mCompressedSize;
+       int mUncompressedSize;
+       int mNameLen;   // including 0
+       char *mFilename;
+};
+#pragma pack(pop)
+
+class PFileSystem {
+private:
+       typedef std::map<std::string, PPakFileHeader*> PPakFileList;
+       typedef std::map<std::string, PPakFileList*> PPakFiles;
+       PPakFiles mPaks;
+       PPakFileList *CachePak(const std::string &Pak, FILE *F);
+
+public:
+       PFileSystem();
+       ~PFileSystem();
+       PFile *Open(const std::string &Package, const char *File, std::string BasePath);
+       bool Close(PFile *File);
+       void ClearCache();
+};
index 1f8fa3b..28b8049 100644 (file)
-#include <cstdarg>\r
-#include <cstring>\r
-#include <arpa/inet.h>\r
-#include "Common/Includes.hxx"\r
-\r
-uint32_t IPStringToDWord( const char *IP )\r
-{\r
-  if ( !IP )\r
-    return 0;\r
-\r
-  uint32_t a, b, c, d;\r
-  if ( std::sscanf( IP, "%u.%u.%u.%u", &a, &b, &c, &d ) != 4 )\r
-    return 0;\r
-\r
-  return ( d << 24 ) | ( c << 16 ) | ( b << 8 ) | a;\r
-}\r
-\r
-char *IPlongToString( const uint32_t IP )\r
-{\r
-  struct in_addr in_IP;\r
-\r
-  in_IP.s_addr = IP;\r
-  return inet_ntoa( in_IP );\r
-}\r
-\r
-//NEW\r
-//this function allow to print a packet\r
-//just for tracking values\r
-void PrintPacket( uint8_t *Packet, int PacketSize )\r
-{\r
-  Console->Print( "inside : PrintPacket" );\r
-\r
-  if ( PacketSize < 1 ){Console->Print( "Wrong packet" );}//do nothing\r
-  else\r
-  {\r
-    Console->Print( "PacketSize is : %d", PacketSize );\r
-\r
-    uint8_t value = 0;\r
-    for ( int i = 0;i < PacketSize;i++ )\r
-    {\r
-      value = *( uint8_t* ) & Packet[i];\r
-      Console->Print( "value[%d] is : %x", i, value );\r
-    }\r
-  }\r
-\r
-}//end function\r
-\r
-void CleanUpString(std::string *nString)\r
-{\r
-    if(!nString)\r
-        return;\r
-\r
-    // Skip if string is >" "<\r
-    if(nString->length() > 3)\r
-    {\r
-        size_t tfound;\r
-        std::string t_replacechr ("\"");\r
-\r
-        tfound = nString->find(t_replacechr);\r
-        while(tfound != std::string::npos)\r
-        {\r
-            nString->replace(tfound, 1, " ");\r
-            tfound = nString->find( t_replacechr, tfound +1 );\r
-        }\r
-        // Skip if string consists of spaces now\r
-        if(strncmp(nString->c_str(), "   ", 3) == 0)\r
-        {\r
-            // Set empty\r
-            *nString = "";\r
-        }\r
-        else\r
-        {\r
-            // Trim spaces\r
-            Trim(nString);\r
-        }\r
-    }\r
-    else\r
-    {\r
-        *nString = "";\r
-    }\r
-}\r
-\r
-\r
-void Trim( char *t )\r
-{\r
-  RTrim( t );\r
-  if ( strlen( t ) )\r
-    LTrim( t );\r
-}\r
-\r
-void Trim( std::string *stString )\r
-{\r
-  RTrim( stString );\r
-  if ( stString->length() )\r
-    LTrim( stString );\r
-}\r
-\r
-void RTrim( char *t )\r
-{\r
-  char *buf;\r
-\r
-  if ( !strlen( t ) ) return;\r
-\r
-  buf = t;\r
-  buf += strlen( t ) - 1;\r
-\r
-  while ( *buf == ' ' && strlen( t ) )\r
-    *buf-- = '\0';\r
-}\r
-\r
-void RTrim( std::string *stString )\r
-{\r
-  int i;       //Count VAR\r
-\r
-  if ( !stString->length() )   //If There Is No Length\r
-    return;\r
-\r
-  i = stString->length() - 1;   //Set The Counter To The String Length -1\r
-\r
-  while ( stString->substr( i, 1 ) == " " )  //While There Is Still " "\r
-  {\r
-    *stString = stString->substr( 0, i );  //Remove Off The End Of The String\r
-    i--;         //Advance The Counter\r
-  }\r
-\r
-}\r
-\r
-void LTrim( char *t )\r
-{\r
-  char tmp[2048];    //Temp Char VAR\r
-  char *buf;     //Pointer\r
-\r
-  if ( !strlen( t ) ) return;\r
-\r
-  strncpy( tmp, t, 2048 );\r
-  tmp[2047] = 0;\r
-  buf = tmp;\r
-\r
-  while ( *buf == ' ' && strlen( buf ) ) *buf++;\r
-\r
-  strncpy( t, buf, 2048 ); // just because without length is forbidden !\r
-}\r
-\r
-void LTrim( std::string *stString )\r
-{\r
-  unsigned int i;       //Count VAR\r
-  std::string buf;      //Temp String VAR\r
-\r
-  if ( !stString->length() ) return;    //If The Length Is 0\r
-\r
-  i = 0;             //Setup The Counter VAR\r
-\r
-  while ( stString->substr( i, 1 ) == " " )     //While " "\r
-    i++;            //Increase Counter\r
-\r
-  if ( i == stString->length() )     //If The Whole String Is " "\r
-  {\r
-    *stString = "";          //Return Blank String\r
-    return;\r
-  }\r
-\r
-  try\r
-  {\r
-    *stString = stString->substr( i, stString->length() - i ); //Send The String Back Without The Spaces\r
-  }\r
-  catch ( ... )\r
-  {\r
-    *stString = "";          //Return Blank String\r
-    return;\r
-  }\r
-\r
-}\r
-\r
-std::string GetAccessString( int level )\r
-{\r
-  switch ( level )\r
-  {\r
-    case 0: return "Unregistered";\r
-    case 1: return "Registered";\r
-    case 30: return "Volunteer";\r
-    case 50: return "Gamemaster";\r
-    case 100: return "Administrator";\r
-  }\r
-  return "Error";\r
-}\r
-\r
-std::string &Ssprintf( const char *fmt, ... )\r
-{\r
-  static std::string tmpstring;\r
-  char buff[1024];\r
-  va_list args;\r
-\r
-  va_start( args, fmt );\r
-  vsnprintf( buff, 1024, fmt, args );\r
-  va_end( args );\r
-  buff[1023] = '\0';\r
-  tmpstring = buff;\r
-  return tmpstring;\r
-}\r
-\r
-uint16_t DistanceApprox( const uint16_t x1, const uint16_t y1, const uint16_t z1, const uint16_t x2, const uint16_t y2, const uint16_t z2 )\r
-{\r
-  uint16_t DX, DY, DZ, DMax;\r
-  uint32_t DMinSum, DApprox;\r
-\r
-  DMax = DX = ( x1 >= x2 ) ? x1 - x2 : x2 - x1;\r
-  DMinSum = DY = ( y1 >= y2 ) ? y1 - y2 : y2 - y1;\r
-  DZ = ( z1 >= z2 ) ? z1 - z2 : z2 - z1;\r
-  if ( DX < DY )\r
-  {\r
-    DMax = DY;\r
-    DMinSum = DX;\r
-  }\r
-  if ( DMax < DZ )\r
-  {\r
-    DMinSum += DMax;\r
-    DMax = DZ;\r
-  }\r
-  else\r
-  {\r
-    DMinSum += DZ;\r
-  }\r
-\r
-  DApprox = DMax + ( uint32_t )( 0.33 * DMinSum );\r
-  if ( DApprox > 65535 )\r
-  {\r
-    DApprox = 65535;\r
-  }\r
-\r
-  // We use Dapprox = max(dx, dy) + K * min(dx, dy)\r
-  // Dapprox = (DX > DY) ? DX + (DY >> 1) : DY + (DX >> 1); // Fastest, but max error on dist is around 10% real dist\r
-  //Dapprox = (u16)((DX > DY) ? DX + 0.33*DY : DY + 0.33*DX); // max error on dist is around 5%, which should be enough\r
-  /*\r
-   // for dist approx debug\r
-  float fDX, fDY, fDZ, fDist;\r
-  fDX=(x1 - x2);\r
-  fDY=(y1 - y2);\r
-  fDZ=(z1 - z2);\r
-  fDist=sqrt(fDX*fDX + fDY*fDY + fDZ*fDZ);\r
-  if (fDist != 0) Console->Print("Dist: %f\tApprox: %d\tError: %d (%d%)", fDist, DApprox, (int)(DApprox-fDist), (int)(100*(DApprox-fDist)/fDist));\r
-  */\r
-\r
-  return ( uint16_t )DApprox;\r
-}\r
-\r
-/*** Portable pseudo-random number generator ***/\r
-// until native standardized C++ lib support\r
-\r
-uint32_t mInternalRand = 1;\r
-\r
-void InitRandom( uint32_t nInitialisationValue )\r
-{\r
-  mInternalRand = nInitialisationValue;\r
-}\r
-\r
-uint16_t GetRandom( uint16_t MaxVal, uint16_t MinVal )\r
-{\r
-  mInternalRand = mInternalRand * 1103515245 + 12345; //from rand() manpage\r
-  return ( uint16_t )( MinVal + (( mInternalRand >> 16 ) % 32768 % ( MaxVal - MinVal + 1 ) ) );\r
-}\r
-\r
-float GetRandomFloat()\r
-{\r
-  mInternalRand = mInternalRand * 1103515245 + 12345; //from rand() manpage\r
-  return (( float )(( mInternalRand >> 16 ) % 32768 ) / ( float )32768 );\r
-}\r
+#include <cstdarg>
+#include <cstring>
+#include <arpa/inet.h>
+#include "Common/Includes.hxx"
+
+uint32_t IPStringToDWord( const char *IP )
+{
+  if ( !IP )
+    return 0;
+
+  uint32_t a, b, c, d;
+  if ( std::sscanf( IP, "%u.%u.%u.%u", &a, &b, &c, &d ) != 4 )
+    return 0;
+
+  return ( d << 24 ) | ( c << 16 ) | ( b << 8 ) | a;
+}
+
+char *IPlongToString( const uint32_t IP )
+{
+  struct in_addr in_IP;
+
+  in_IP.s_addr = IP;
+  return inet_ntoa( in_IP );
+}
+
+//NEW
+//this function allow to print a packet
+//just for tracking values
+void PrintPacket( uint8_t *Packet, int PacketSize )
+{
+  Console->Print( "inside : PrintPacket" );
+
+  if ( PacketSize < 1 ){Console->Print( "Wrong packet" );}//do nothing
+  else
+  {
+    Console->Print( "PacketSize is : %d", PacketSize );
+
+    uint8_t value = 0;
+    for ( int i = 0;i < PacketSize;i++ )
+    {
+      value = *( uint8_t* ) & Packet[i];
+      Console->Print( "value[%d] is : %x", i, value );
+    }
+  }
+
+}//end function
+
+void CleanUpString(std::string *nString)
+{
+    if(!nString)
+        return;
+
+    // Skip if string is >" "<
+    if(nString->length() > 3)
+    {
+        size_t tfound;
+        std::string t_replacechr ("\"");
+
+        tfound = nString->find(t_replacechr);
+        while(tfound != std::string::npos)
+        {
+            nString->replace(tfound, 1, " ");
+            tfound = nString->find( t_replacechr, tfound +1 );
+        }
+        // Skip if string consists of spaces now
+        if(strncmp(nString->c_str(), "   ", 3) == 0)
+        {
+            // Set empty
+            *nString = "";
+        }
+        else
+        {
+            // Trim spaces
+            Trim(nString);
+        }
+    }
+    else
+    {
+        *nString = "";
+    }
+}
+
+
+void Trim( char *t )
+{
+  RTrim( t );
+  if ( strlen( t ) )
+    LTrim( t );
+}
+
+void Trim( std::string *stString )
+{
+  RTrim( stString );
+  if ( stString->length() )
+    LTrim( stString );
+}
+
+void RTrim( char *t )
+{
+  char *buf;
+
+  if ( !strlen( t ) ) return;
+
+  buf = t;
+  buf += strlen( t ) - 1;
+
+  while ( *buf == ' ' && strlen( t ) )
+    *buf-- = '\0';
+}
+
+void RTrim( std::string *stString )
+{
+  int i;       //Count VAR
+
+  if ( !stString->length() )   //If There Is No Length
+    return;
+
+  i = stString->length() - 1;   //Set The Counter To The String Length -1
+
+  while ( stString->substr( i, 1 ) == " " )  //While There Is Still " "
+  {
+    *stString = stString->substr( 0, i );  //Remove Off The End Of The String
+    i--;         //Advance The Counter
+  }
+
+}
+
+void LTrim( char *t )
+{
+  char tmp[2048];    //Temp Char VAR
+  char *buf;     //Pointer
+
+  if ( !strlen( t ) ) return;
+
+  strncpy( tmp, t, 2048 );
+  tmp[2047] = 0;
+  buf = tmp;
+
+  while ( *buf == ' ' && strlen( buf ) ) *buf++;
+
+  strncpy( t, buf, 2048 ); // just because without length is forbidden !
+}
+
+void LTrim( std::string *stString )
+{
+  unsigned int i;       //Count VAR
+  std::string buf;      //Temp String VAR
+
+  if ( !stString->length() ) return;    //If The Length Is 0
+
+  i = 0;             //Setup The Counter VAR
+
+  while ( stString->substr( i, 1 ) == " " )     //While " "
+    i++;            //Increase Counter
+
+  if ( i == stString->length() )     //If The Whole String Is " "
+  {
+    *stString = "";          //Return Blank String
+    return;
+  }
+
+  try
+  {
+    *stString = stString->substr( i, stString->length() - i ); //Send The String Back Without The Spaces
+  }
+  catch ( ... )
+  {
+    *stString = "";          //Return Blank String
+    return;
+  }
+
+}
+
+std::string GetAccessString( int level )
+{
+  switch ( level )
+  {
+    case 0: return "Unregistered";
+    case 1: return "Registered";
+    case 30: return "Volunteer";
+    case 50: return "Gamemaster";
+    case 100: return "Administrator";
+  }
+  return "Error";
+}
+
+std::string &Ssprintf( const char *fmt, ... )
+{
+  static std::string tmpstring;
+  char buff[1024];
+  va_list args;
+
+  va_start( args, fmt );
+  vsnprintf( buff, 1024, fmt, args );
+  va_end( args );
+  buff[1023] = '\0';
+  tmpstring = buff;
+  return tmpstring;
+}
+
+uint16_t DistanceApprox( const uint16_t x1, const uint16_t y1, const uint16_t z1, const uint16_t x2, const uint16_t y2, const uint16_t z2 )
+{
+  uint16_t DX, DY, DZ, DMax;
+  uint32_t DMinSum, DApprox;
+
+  DMax = DX = ( x1 >= x2 ) ? x1 - x2 : x2 - x1;
+  DMinSum = DY = ( y1 >= y2 ) ? y1 - y2 : y2 - y1;
+  DZ = ( z1 >= z2 ) ? z1 - z2 : z2 - z1;
+  if ( DX < DY )
+  {
+    DMax = DY;
+    DMinSum = DX;
+  }
+  if ( DMax < DZ )
+  {
+    DMinSum += DMax;
+    DMax = DZ;
+  }
+  else
+  {
+    DMinSum += DZ;
+  }
+
+  DApprox = DMax + ( uint32_t )( 0.33 * DMinSum );
+  if ( DApprox > 65535 )
+  {
+    DApprox = 65535;
+  }
+
+  // We use Dapprox = max(dx, dy) + K * min(dx, dy)
+  // Dapprox = (DX > DY) ? DX + (DY >> 1) : DY + (DX >> 1); // Fastest, but max error on dist is around 10% real dist
+  //Dapprox = (u16)((DX > DY) ? DX + 0.33*DY : DY + 0.33*DX); // max error on dist is around 5%, which should be enough
+  /*
+   // for dist approx debug
+  float fDX, fDY, fDZ, fDist;
+  fDX=(x1 - x2);
+  fDY=(y1 - y2);
+  fDZ=(z1 - z2);
+  fDist=sqrt(fDX*fDX + fDY*fDY + fDZ*fDZ);
+  if (fDist != 0) Console->Print("Dist: %f\tApprox: %d\tError: %d (%d%)", fDist, DApprox, (int)(DApprox-fDist), (int)(100*(DApprox-fDist)/fDist));
+  */
+
+  return ( uint16_t )DApprox;
+}
+
+/*** Portable pseudo-random number generator ***/
+// until native standardized C++ lib support
+
+uint32_t mInternalRand = 1;
+
+void InitRandom( uint32_t nInitialisationValue )
+{
+  mInternalRand = nInitialisationValue;
+}
+
+uint16_t GetRandom( uint16_t MaxVal, uint16_t MinVal )
+{
+  mInternalRand = mInternalRand * 1103515245 + 12345; //from rand() manpage
+  return ( uint16_t )( MinVal + (( mInternalRand >> 16 ) % 32768 % ( MaxVal - MinVal + 1 ) ) );
+}
+
+float GetRandomFloat()
+{
+  mInternalRand = mInternalRand * 1103515245 + 12345; //from rand() manpage
+  return (( float )(( mInternalRand >> 16 ) % 32768 ) / ( float )32768 );
+}
index 33bf941..e62b864 100644 (file)
@@ -1,29 +1,29 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-\r
-uint32_t IPStringToDWord(const char *IP);\r
-char *IPlongToString(const uint32_t IP);\r
-std::string GetAccessString(int32_t level);\r
-//void GetSVNRev(char *version);\r
-\r
-void PrintPacket(uint8_t *Packet, int32_t PacketSize);\r
-\r
-// Cleanup for strings read from .def\r
-void CleanUpString(std::string *nString);\r
-void Trim(char *t);\r
-void Trim(std::string *stString);\r
-void RTrim(char *t);\r
-void RTrim(std::string *stString);\r
-void LTrim(char *t);\r
-void LTrim(std::string *stString);\r
-std::string &Ssprintf(const char *fmt, ...);\r
-\r
-uint16_t DistanceApprox(const uint16_t x1, const uint16_t y1, const uint16_t z1, const uint16_t x2, const uint16_t y2, const uint16_t z2);\r
-float Distance(const float x1, const float y1, const float z1, const float x2, const float y2, const float z2);\r
-float Distance(const float x1, const float y1, const float x2, const float y2); // 2D only version\r
-\r
-void InitRandom(uint32_t nInitialisationValue);\r
-uint16_t GetRandom(uint16_t MaxVal, uint16_t MinVal = 0); // u16 value between MinVal and MaxVal (inclusive) with max range 32768\r
-float GetRandomFloat(); // f32 value between 0 and 1\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+uint32_t IPStringToDWord(const char *IP);
+char *IPlongToString(const uint32_t IP);
+std::string GetAccessString(int32_t level);
+//void GetSVNRev(char *version);
+
+void PrintPacket(uint8_t *Packet, int32_t PacketSize);
+
+// Cleanup for strings read from .def
+void CleanUpString(std::string *nString);
+void Trim(char *t);
+void Trim(std::string *stString);
+void RTrim(char *t);
+void RTrim(std::string *stString);
+void LTrim(char *t);
+void LTrim(std::string *stString);
+std::string &Ssprintf(const char *fmt, ...);
+
+uint16_t DistanceApprox(const uint16_t x1, const uint16_t y1, const uint16_t z1, const uint16_t x2, const uint16_t y2, const uint16_t z2);
+float Distance(const float x1, const float y1, const float z1, const float x2, const float y2, const float z2);
+float Distance(const float x1, const float y1, const float x2, const float y2); // 2D only version
+
+void InitRandom(uint32_t nInitialisationValue);
+uint16_t GetRandom(uint16_t MaxVal, uint16_t MinVal = 0); // u16 value between MinVal and MaxVal (inclusive) with max range 32768
+float GetRandomFloat(); // f32 value between 0 and 1
index 8e388fb..a2ca8c8 100644 (file)
@@ -1,43 +1,43 @@
-#pragma once\r
-\r
-#include <pthread.h>\r
-\r
-class Mutex {\r
-private:\r
-    mutable pthread_mutex_t mut;\r
-\r
-    void operator = (Mutex &mut) {}\r
-\r
-    Mutex(const Mutex &mut) {}\r
-\r
-public:\r
-    Mutex()\r
-    {\r
-        pthread_mutexattr_t attr;\r
-        pthread_mutexattr_init(&attr);\r
-        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);\r
-        pthread_mutex_init(&mut, &attr);\r
-        pthread_mutexattr_destroy(&attr);\r
-    }\r
-\r
-    virtual ~Mutex()\r
-    {\r
-        pthread_mutex_unlock(&mut);\r
-        pthread_mutex_destroy(&mut);\r
-    }\r
-\r
-    int Lock() const\r
-    {\r
-        return (pthread_mutex_lock(&mut));\r
-    }\r
-\r
-    int TryLock() const\r
-    {\r
-        return (pthread_mutex_trylock(&mut));\r
-    }\r
-\r
-    int Unlock() const\r
-    {\r
-        return (pthread_mutex_unlock(&mut));\r
-    }\r
-};\r
+#pragma once
+
+#include <pthread.h>
+
+class Mutex {
+private:
+    mutable pthread_mutex_t mut;
+
+    void operator = (Mutex &mut) {}
+
+    Mutex(const Mutex &mut) {}
+
+public:
+    Mutex()
+    {
+        pthread_mutexattr_t attr;
+        pthread_mutexattr_init(&attr);
+        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&mut, &attr);
+        pthread_mutexattr_destroy(&attr);
+    }
+
+    virtual ~Mutex()
+    {
+        pthread_mutex_unlock(&mut);
+        pthread_mutex_destroy(&mut);
+    }
+
+    int Lock() const
+    {
+        return (pthread_mutex_lock(&mut));
+    }
+
+    int TryLock() const
+    {
+        return (pthread_mutex_trylock(&mut));
+    }
+
+    int Unlock() const
+    {
+        return (pthread_mutex_unlock(&mut));
+    }
+};
index 023982d..89f71b6 100644 (file)
@@ -1,49 +1,49 @@
-#pragma once\r
-\r
-#include <semaphore.h>\r
-\r
-class Semaphore {\r
-private:\r
-    sem_t sem;\r
-\r
-public:\r
-    Semaphore(int init = 0)\r
-    {\r
-        sem_init(&sem, 0, init);\r
-    }\r
-\r
-    virtual ~Semaphore()\r
-    {\r
-        sem_destroy(&sem);\r
-    }\r
-\r
-    void Wait() const\r
-    {\r
-        sem_wait((sem_t *)&sem);\r
-    }\r
-\r
-    int TryWait() const\r
-    {\r
-        return (sem_trywait((sem_t *)&sem) ? errno : 0);\r
-    }\r
-\r
-    int Post() const\r
-    {\r
-        return (sem_post((sem_t *)&sem) ? errno : 0);\r
-    }\r
-\r
-    int GetValue() const\r
-    {\r
-        int val = -1;\r
-\r
-        sem_getvalue((sem_t *)&sem, &val);\r
-\r
-        return (val);\r
-    }\r
-\r
-    void Reset(int init = 0)\r
-    {\r
-        sem_destroy(&sem);\r
-        sem_init(&sem, 0, init);\r
-    }\r
-};\r
+#pragma once
+
+#include <semaphore.h>
+
+class Semaphore {
+private:
+    sem_t sem;
+
+public:
+    Semaphore(int init = 0)
+    {
+        sem_init(&sem, 0, init);
+    }
+
+    virtual ~Semaphore()
+    {
+        sem_destroy(&sem);
+    }
+
+    void Wait() const
+    {
+        sem_wait((sem_t *)&sem);
+    }
+
+    int TryWait() const
+    {
+        return (sem_trywait((sem_t *)&sem) ? errno : 0);
+    }
+
+    int Post() const
+    {
+        return (sem_post((sem_t *)&sem) ? errno : 0);
+    }
+
+    int GetValue() const
+    {
+        int val = -1;
+
+        sem_getvalue((sem_t *)&sem, &val);
+
+        return (val);
+    }
+
+    void Reset(int init = 0)
+    {
+        sem_destroy(&sem);
+        sem_init(&sem, 0, init);
+    }
+};
index 70c0e8a..5ddb652 100644 (file)
-#pragma once\r
-\r
-#include <mutex.h>\r
-#include <semaphore.h>\r
-#include <pthread.h>\r
-\r
-#define INVALID_HANDLE 0\r
-\r
-typedef void *(*pthread_fn)(void*);\r
-\r
-template <typename Thread_T>\r
-class Thread {\r
-       private:\r
-               typedef struct Instance;\r
-\r
-       public:\r
-               typedef Thread_T &Thread_;\r
-               typedef const Thread_T &Thread__;\r
-               typedef pthread_t Handle;\r
-               typedef void (*Handler)(Thread_);\r
-\r
-       protected:\r
-               Thread() {\r
-               }\r
-\r
-               virtual void ThreadMain(Thread_) = 0;\r
-\r
-               static void Exit() {\r
-                       pthread_exit(0);\r
-               }\r
-\r
-               static void TestCancel() {\r
-                       pthread_testcancel();\r
-               }\r
-\r
-               static Handle Self() {\r
-                       return(Handle)pthread_self();\r
-               }\r
-\r
-       public:\r
-               static int Create(const Handler &Func, Thread__ Param, Handle *const &H = 0,\r
-                                 const bool &CreateDetached = false, const unsigned int &StackSize = 0,\r
-                                 const bool &CancelEnable = false, const bool &CancelAsync = false) {\r
-                       M_Create().Lock();\r
-                       pthread_attr_t attr;\r
-                       pthread_attr_init(&attr);\r
-\r
-                       if(CreateDetached)\r
-                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);\r
-\r
-                       if(StackSize)\r
-                               pthread_attr_setstacksize(&attr, StackSize);\r
-\r
-                       Instance I(Param, 0, Func, CancelEnable, CancelAsync);\r
-\r
-                       Handle h = INVALID_HANDLE;\r
-                       int run = pthread_create((pthread_t *)&h, &attr, (pthread_fn)ThreadMainHandler, (void *)&I);\r
-\r
-                       pthread_attr_destroy(&attr);\r
-\r
-                       if(H)\r
-                               *H = h;\r
-                       if(!run)\r
-                               S_Create().Wait();\r
-\r
-                       M_Create().Unlock();\r
-\r
-                       return(errno);\r
-               }\r
-\r
-               int Create(Thread__ Param, Handle *const &H = 0, const bool &CreateDetached = false,\r
-                          const unsigned int &StackSize = 0, const bool &CancelEnable = false,\r
-                          const bool &CancelAsync = false ) const {\r
-                       M_Create().Lock();\r
-                       pthread_attr_t attr;\r
-                       pthread_attr_init(&attr);\r
-\r
-                       if(CreateDetached)\r
-                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);\r
-\r
-                       if(StackSize)\r
-                               pthread_attr_setstacksize(&attr, StackSize);\r
-\r
-                       Instance I(Param, const_cast<Thread *>(this), 0, CancelEnable, CancelAsync);\r
-\r
-                       Handle h = INVALID_HANDLE;\r
-                       int run = pthread_create((pthread_t *)&h, &attr, (pthread_fn)ThreadMainHandler, (void *)&I);\r
-\r
-                       pthread_attr_destroy(&attr);\r
-\r
-                       if(H)\r
-                               *H = h;\r
-                       if(!run)\r
-                               S_Create().Wait();\r
-\r
-                       M_Create().Unlock();\r
-\r
-                       return(errno);\r
-               }\r
-\r
-               static int Join(Handle H) {\r
-                       return(pthread_join(H, 0));\r
-               }\r
-\r
-               static int Kill(Handle H) {\r
-                       return(pthread_cancel(H));\r
-               }\r
-\r
-               static int Detach(Handle H) {\r
-                       return(pthread_detach(H));\r
-               }\r
-\r
-       private:\r
-               static const Mutex &M_Create() {\r
-                       static Mutex M;\r
-\r
-                       return(M);\r
-               }\r
-\r
-               static const Semaphore &S_Create() {\r
-                       static Semaphore S;\r
-\r
-                       return(S);\r
-               }\r
-\r
-               static void ThreadMainHandler(Instance *Param) {\r
-                       Instance I(*Param);\r
-                       Thread_T Data(I.Data);\r
-\r
-                       S_Create().Post();\r
-\r
-                       if(I.Flags & 1) {\r
-                               pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\r
-\r
-                               if(I.Flags & 2)\r
-                                       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);\r
-                               else\r
-                                       pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);\r
-                       }\r
-                       else\r
-                               pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);\r
-\r
-                       if(I.Owner)\r
-                               I.Owner->ThreadMain(Data);\r
-                       else\r
-                               I.pFN(Data);\r
-\r
-                       return(0);\r
-               }\r
-\r
-               struct Instance {\r
-                       Instance(Thread__ P, Thread<Thread_T> *const &O, const Thread<Thread_T>::Handler &pH = 0,\r
-                                const bool &CE = false, const bool &CA = false) : Data(P), Owner(O), pFN(pH),\r
-                                Flags(0) {\r
-                               if(CE)\r
-                                       Flags |= 1;\r
-                               if(CA)\r
-                                       Flags |= 2;\r
-                       }\r
-\r
-                       Thread__ Data;\r
-                       Thread<Thread_T> *Owner;\r
-                       Handler pFN;\r
-                       unsigned char Flags;\r
-               };\r
-};\r
+#pragma once
+
+#include <mutex.h>
+#include <semaphore.h>
+#include <pthread.h>
+
+#define INVALID_HANDLE 0
+
+typedef void *(*pthread_fn)(void*);
+
+template <typename Thread_T>
+class Thread {
+       private:
+               typedef struct Instance;
+
+       public:
+               typedef Thread_T &Thread_;
+               typedef const Thread_T &Thread__;
+               typedef pthread_t Handle;
+               typedef void (*Handler)(Thread_);
+
+       protected:
+               Thread() {
+               }
+
+               virtual void ThreadMain(Thread_) = 0;
+
+               static void Exit() {
+                       pthread_exit(0);
+               }
+
+               static void TestCancel() {
+                       pthread_testcancel();
+               }
+
+               static Handle Self() {
+                       return(Handle)pthread_self();
+               }
+
+       public:
+               static int Create(const Handler &Func, Thread__ Param, Handle *const &H = 0,
+                                 const bool &CreateDetached = false, const unsigned int &StackSize = 0,
+                                 const bool &CancelEnable = false, const bool &CancelAsync = false) {
+                       M_Create().Lock();
+                       pthread_attr_t attr;
+                       pthread_attr_init(&attr);
+
+                       if(CreateDetached)
+                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+                       if(StackSize)
+                               pthread_attr_setstacksize(&attr, StackSize);
+
+                       Instance I(Param, 0, Func, CancelEnable, CancelAsync);
+
+                       Handle h = INVALID_HANDLE;
+                       int run = pthread_create((pthread_t *)&h, &attr, (pthread_fn)ThreadMainHandler, (void *)&I);
+
+                       pthread_attr_destroy(&attr);
+
+                       if(H)
+                               *H = h;
+                       if(!run)
+                               S_Create().Wait();
+
+                       M_Create().Unlock();
+
+                       return(errno);
+               }
+
+               int Create(Thread__ Param, Handle *const &H = 0, const bool &CreateDetached = false,
+                          const unsigned int &StackSize = 0, const bool &CancelEnable = false,
+                          const bool &CancelAsync = false ) const {
+                       M_Create().Lock();
+                       pthread_attr_t attr;
+                       pthread_attr_init(&attr);
+
+                       if(CreateDetached)
+                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+                       if(StackSize)
+                               pthread_attr_setstacksize(&attr, StackSize);
+
+                       Instance I(Param, const_cast<Thread *>(this), 0, CancelEnable, CancelAsync);
+
+                       Handle h = INVALID_HANDLE;
+                       int run = pthread_create((pthread_t *)&h, &attr, (pthread_fn)ThreadMainHandler, (void *)&I);
+
+                       pthread_attr_destroy(&attr);
+
+                       if(H)
+                               *H = h;
+                       if(!run)
+                               S_Create().Wait();
+
+                       M_Create().Unlock();
+
+                       return(errno);
+               }
+
+               static int Join(Handle H) {
+                       return(pthread_join(H, 0));
+               }
+
+               static int Kill(Handle H) {
+                       return(pthread_cancel(H));
+               }
+
+               static int Detach(Handle H) {
+                       return(pthread_detach(H));
+               }
+
+       private:
+               static const Mutex &M_Create() {
+                       static Mutex M;
+
+                       return(M);
+               }
+
+               static const Semaphore &S_Create() {
+                       static Semaphore S;
+
+                       return(S);
+               }
+
+               static void ThreadMainHandler(Instance *Param) {
+                       Instance I(*Param);
+                       Thread_T Data(I.Data);
+
+                       S_Create().Post();
+
+                       if(I.Flags & 1) {
+                               pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+                               if(I.Flags & 2)
+                                       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+                               else
+                                       pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+                       }
+                       else
+                               pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+                       if(I.Owner)
+                               I.Owner->ThreadMain(Data);
+                       else
+                               I.pFN(Data);
+
+                       return(0);
+               }
+
+               struct Instance {
+                       Instance(Thread__ P, Thread<Thread_T> *const &O, const Thread<Thread_T>::Handler &pH = 0,
+                                const bool &CE = false, const bool &CA = false) : Data(P), Owner(O), pFN(pH),
+                                Flags(0) {
+                               if(CE)
+                                       Flags |= 1;
+                               if(CA)
+                                       Flags |= 2;
+                       }
+
+                       Thread__ Data;
+                       Thread<Thread_T> *Owner;
+                       Handler pFN;
+                       unsigned char Flags;
+               };
+};
index 684ebd2..6048471 100644 (file)
@@ -1,7 +1,7 @@
-#pragma once\r
-\r
-#include "Common/SVNrevision.hxx"\r
-\r
-#define TINNS_PATCH_VERSION "0.0.2 Dev"\r
-#define TINNS_INFO_VERSION "0.0.2 Dev"\r
-#define TINNS_GAME_VERSION "0.1.38 Dev"\r
+#pragma once
+
+#include "Common/SVNrevision.hxx"
+
+#define TINNS_PATCH_VERSION "0.0.2 Dev"
+#define TINNS_INFO_VERSION "0.0.2 Dev"
+#define TINNS_GAME_VERSION "0.1.38 Dev"
index 9f60614..50b0b11 100644 (file)
@@ -1,2 +1,2 @@
-ADD_EXECUTABLE          (getsvnrev getsvnrev.cpp)
+ADD_EXECUTABLE          (getsvnrev getsvnrev.cxx)
 ADD_EXECUTABLE          (cleandepfile cleandepfile.c)
similarity index 95%
rename from TinNS/Source/DevelopmentTools/getsvnrev.cpp
rename to TinNS/Source/DevelopmentTools/getsvnrev.cxx
index dc88289..501129d 100644 (file)
-/*\r
-       TinNS (TinNS is not a Neocron Server)\r
-       Copyright (C) 2005 Linux Addicted Community\r
-       maintainer Akiko <akiko@gmx.org>\r
-\r
-       This program is free software; you can redistribute it and/or\r
-       modify it under the terms of the GNU General Public License\r
-       as published by the Free Software Foundation; either version 2\r
-       of the License, or (at your option) any later version.\r
-\r
-       This program is distributed in the hope that it will be useful,\r
-       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-       GNU General Public License for more details.\r
-\r
-       You should have received a copy of the GNU General Public License\r
-       along with this program; if not, write to the Free Software\r
-       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
-       02110-1301, USA.\r
-*/\r
-\r
-\r
-\r
-/*\r
-       getsvnrev - a simple tool to read out actual SVN revision-number\r
-\r
-       Why?\r
-               Well for example my server doesnt have any SVN libs installed. Therefore,\r
-               the getsvnrev script fails. I need this little tool, and maybe someone else too ^^\r
-\r
-       Usage: \r
-               call getsvnrev either without parameters or with the directory you\r
-               want to know the SVN revision.\r
-       \r
-       Console output:\r
-               If no .svn directory is found, the tool returns 0.\r
-               Otherwise it will return the SVN revision of the target dir\r
-\r
-       MODIFIED: 22 Dec 2006 Namikon\r
-       REASON: - started this tool\r
-       MODIFIED: 09 Jun 2009 Akiko\r
-       REASON: - more C++ stylish\r
-               - missing libs (cstring, cstdlib)\r
-\r
-       TODO:\r
-               - Better way to get SVN rev than this (2nd number in file)\r
-*/\r
-\r
-\r
-#include <cstdio>\r
-#include <cstring>\r
-#include <cstdlib>\r
-#include <iostream>\r
-\r
-int main(int argc, char **argv)\r
-{\r
-       std::string targetdir;\r
-       FILE *f;\r
-\r
-        if(argc == 2)\r
-       {\r
-               int i = 0;\r
-               while(argv[1][i] != '\0') { i++; };\r
-               if(argv[1][i-1] == '/')\r
-               {\r
-                       targetdir = strcat(argv[1], ".svn/entries");\r
-               }\r
-               else\r
-               {\r
-                       targetdir = strcat(argv[1], "/.svn/entries");\r
-               }\r
-        }\r
-       else\r
-       {\r
-               targetdir = ".svn/entries";\r
-       }\r
-\r
-\r
-        if ((f = fopen(targetdir.c_str(), "r")) != NULL) {\r
-                char line[255];\r
-                int rev;\r
-               bool firstnrfound = false;\r
-               \r
-               do\r
-               {\r
-                  fgets (line, 255, f);\r
-                  rev = atoi(line);\r
-                  if(rev > 0 && firstnrfound == false)\r
-                  {\r
-                       firstnrfound = true;\r
-                       rev = 0;\r
-                   }\r
-               } while (rev == 0);\r
-               \r
-                fclose(f);\r
-\r
-                std::cout << rev << std::endl;\r
-        }\r
-       else\r
-       {\r
-               std::cout << "0" << std::endl;\r
-       }\r
-       return(0);\r
-}\r
+/*
+       TinNS (TinNS is not a Neocron Server)
+       Copyright (C) 2005 Linux Addicted Community
+       maintainer Akiko <akiko@gmx.org>
+
+       This program is free software; you can redistribute it and/or
+       modify it under the terms of the GNU General Public License
+       as published by the Free Software Foundation; either version 2
+       of the License, or (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+       02110-1301, USA.
+*/
+
+
+
+/*
+       getsvnrev - a simple tool to read out actual SVN revision-number
+
+       Why?
+               Well for example my server doesnt have any SVN libs installed. Therefore,
+               the getsvnrev script fails. I need this little tool, and maybe someone else too ^^
+
+       Usage: 
+               call getsvnrev either without parameters or with the directory you
+               want to know the SVN revision.
+       
+       Console output:
+               If no .svn directory is found, the tool returns 0.
+               Otherwise it will return the SVN revision of the target dir
+
+       MODIFIED: 22 Dec 2006 Namikon
+       REASON: - started this tool
+       MODIFIED: 09 Jun 2009 Akiko
+       REASON: - more C++ stylish
+               - missing libs (cstring, cstdlib)
+
+       TODO:
+               - Better way to get SVN rev than this (2nd number in file)
+*/
+
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+       std::string targetdir;
+       FILE *f;
+
+        if(argc == 2)
+       {
+               int i = 0;
+               while(argv[1][i] != '\0') { i++; };
+               if(argv[1][i-1] == '/')
+               {
+                       targetdir = strcat(argv[1], ".svn/entries");
+               }
+               else
+               {
+                       targetdir = strcat(argv[1], "/.svn/entries");
+               }
+        }
+       else
+       {
+               targetdir = ".svn/entries";
+       }
+
+
+        if ((f = fopen(targetdir.c_str(), "r")) != NULL) {
+                char line[255];
+                int rev;
+               bool firstnrfound = false;
+               
+               do
+               {
+                  fgets (line, 255, f);
+                  rev = atoi(line);
+                  if(rev > 0 && firstnrfound == false)
+                  {
+                       firstnrfound = true;
+                       rev = 0;
+                   }
+               } while (rev == 0);
+               
+                fclose(f);
+
+                std::cout << rev << std::endl;
+        }
+       else
+       {
+               std::cout << "0" << std::endl;
+       }
+       return(0);
+}
index 062599b..c3d66ef 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/*\r
-NOTE ABOUT ACCESS LEVELS IN THE MYSQL DATABASE:\r
-a_priv:\r
-0 = unregistered user\r
-1 = Registered user\r
-30 = volunteer\r
-50 = GM\r
-100 = Admin\r
-\r
-a_status:\r
-0 = Offline\r
-1 = Online\r
-2 = Banned\r
-*/\r
-\r
-/** Static members **/\r
-RegEx* PAccount::mUsernameRegexFilter = NULL;\r
-RegEx* PAccount::mPasswordRegexFilter = NULL;\r
-\r
-bool PAccount::SetUsernameRegexFilter(const char* RegexStr)\r
-{\r
-  if(mUsernameRegexFilter)\r
-  {\r
-    delete mUsernameRegexFilter;\r
-    mUsernameRegexFilter = NULL;\r
-  }\r
-\r
-  if(RegexStr)\r
-  {\r
-    try {\r
-      mUsernameRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);\r
-    }\r
-    catch (...) {\r
-      return false;\r
-    }\r
-  }\r
-  return true;\r
-}\r
-\r
-bool PAccount::SetPasswordRegexFilter(const char* RegexStr)\r
-{\r
-  if(mPasswordRegexFilter)\r
-  {\r
-    delete mPasswordRegexFilter;\r
-    mPasswordRegexFilter = NULL;\r
-  }\r
-\r
-  if(RegexStr)\r
-  {\r
-    try {\r
-      mPasswordRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);\r
-    }\r
-    catch (...) {\r
-      return false;\r
-    }\r
-  }\r
-  return true;\r
-}\r
-\r
-bool PAccount::IsUsernameWellFormed(const char *Username)\r
-{\r
-  if(mUsernameRegexFilter)\r
-  {\r
-    return mUsernameRegexFilter->Search(Username);\r
-  }\r
-  else\r
-    return true;\r
-}\r
-\r
-bool PAccount::IsPasswordWellFormed(const char *Password)\r
-{\r
-  if(mPasswordRegexFilter)\r
-  {\r
-    return mPasswordRegexFilter->Search(Password);\r
-  }\r
-  else\r
-    return true;\r
-}\r
-\r
-/** Instance members **/\r
-PAccount::PAccount()\r
-{\r
-    mID = 0;\r
-    mLevel = PAL_BANNED;\r
-  mStatus = PAS_OFFLINE;\r
-  mBannedUntil = 0;\r
-}\r
-\r
-PAccount::PAccount(const uint32_t AccountId)\r
-{\r
-  char query[256];\r
-  mID = 0;\r
-  snprintf(query, 256, "SELECT * FROM accounts WHERE a_id = %d LIMIT 1;", AccountId);\r
-  LoadFromQuery(query);\r
-}\r
-\r
-PAccount::PAccount(const char *Username)\r
-{\r
-  char query[256];\r
-  mID = 0;\r
-  if(IsUsernameWellFormed(Username)) {\r
-    char escUsername[256];\r
-    MySQL->EscapeString(Username, escUsername, 256);\r
-    snprintf(query, 256, "SELECT * FROM accounts WHERE a_username = '%s' LIMIT 1;", escUsername);\r
-    LoadFromQuery(query);\r
-  }\r
-}\r
-\r
-bool PAccount::LoadFromQuery(char* query)\r
-{\r
-  MYSQL_ROW row = 0;\r
-  MYSQL_RES *result = 0;\r
-\r
-  bool FinalResult = false;\r
-\r
-  result = MySQL->InfoResQuery(query);\r
-  if(result == NULL)\r
-  {\r
-      Console->Print(RED, BLACK, "Failed to load AccountData from SQL");\r
-      MySQL->ShowInfoSQLError();\r
-      return false;\r
-  }\r
-\r
-  if((row = mysql_fetch_row(result)))\r
-  {\r
-    mID = atoi(row[a_id]);\r
-    mName = row[a_username];\r
-    mPassword = row[a_password];\r
-\r
-    mBannedUntil = atoi(row[a_bandate]);\r
-    if(mBannedUntil > time(NULL))\r
-    {\r
-      mStatus = PAS_BANNED;\r
-      mLevel = PAL_BANNED;\r
-    }\r
-    else\r
-    {\r
-      mStatus = PAS_OFFLINE;\r
-      mLevel = atoi(row[a_priv]);\r
-    }\r
-\r
-    FinalResult = true;\r
-  }\r
-  else\r
-  {\r
-Console->Print(YELLOW, BLACK, "Failed to load AccountData from SQL; Nothing to load...");\r
-  }\r
-\r
-  MySQL->FreeInfoSQLResult(result);\r
-  return FinalResult;\r
-}\r
-\r
-bool PAccount::SetName(const std::string &Username)\r
-{\r
-  if(IsUsernameWellFormed(Username.c_str()))\r
-  {\r
-    mName = Username;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::SetPassword(const std::string &Password)\r
-{\r
-  if(IsPasswordWellFormed(Password.c_str()))\r
-  {\r
-    mPassword = Password;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::SetPasswordEncoded(const uint8_t* PasswordData, int PassLen, const uint8_t* Key)\r
-{\r
-    char Pass[128];\r
-\r
-    if(DecodePassword(PasswordData, PassLen, Key, Pass))\r
-  {\r
-        return SetPassword((std::string)Pass);\r
-    }\r
-    else\r
-    {\r
-        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);\r
-        return false;\r
-    }\r
-}\r
-\r
-bool PAccount::SetLevel(int newLevel)\r
-{\r
-  if((newLevel >= PAL_BANNED) && (newLevel <= PAL_ADMIN))\r
-  {\r
-    mLevel = newLevel;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-std::string PAccount::GetLevelString() const\r
-{\r
-    switch(mLevel)\r
-    {\r
-        case PAL_BANNED : return "banned";\r
-        case PAL_UNREGPLAYER : return "unregplayer";\r
-        case PAL_REGPLAYER : return "regplayer";\r
-        case PAL_VOLUNTEER : return "volunteer";\r
-        case PAL_GM : return "gm";\r
-        case PAL_ADMIN : return "admin";\r
-    }\r
-\r
-    return "custom";\r
-}\r
-\r
-bool PAccount::SetStatus(PAccountStatus Status)\r
-{\r
-  mStatus = Status;\r
-  return true;\r
-}\r
-\r
-bool PAccount::SetBannedUntilTime(std::time_t BannedUntil)\r
-{\r
-  if ((BannedUntil == 0) || (BannedUntil > std::time(NULL)))\r
-  {\r
-    mBannedUntil = BannedUntil;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::DecodePassword(const uint8_t* PasswordData, int PassLen, const uint8_t *Key, char* ClearPassword)\r
-{\r
-  ClearPassword[0] = 0;\r
-\r
-  if(PassLen < 128)\r
-    {\r
-        if(Key[0]>7) // TODO: >7 correct?\r
-        {\r
-            for(int i=0; i<PassLen; i+=2)\r
-                ClearPassword[i>>1] = (char)(((PasswordData[i]&0xf0)>>4)\r
-                    +((PasswordData[i+1]&0x0f)<<4)-Key[0]);\r
-            ClearPassword[PassLen>>1]=0;\r
-        }\r
-        else\r
-        {\r
-            for(int i=0; i<PassLen; i++)\r
-                ClearPassword[i] = (char)(PasswordData[i]-Key[0]);\r
-            ClearPassword[PassLen]=0;\r
-        }\r
-        return true;\r
-    }\r
-    else\r
-      return false;\r
-}\r
-\r
-bool PAccount::Authenticate(const uint8_t* PasswordData, int PassLen, const uint8_t *Key)\r
-{\r
-    char Pass[128];\r
-\r
-    if(DecodePassword(PasswordData, PassLen, Key, Pass))\r
-  {\r
-        return Authenticate(Pass);\r
-    }\r
-    else\r
-    {\r
-        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);\r
-        return false;\r
-    }\r
-}\r
-\r
-bool PAccount::Authenticate(const char *Password) const\r
-{\r
-    if(mID == 0) // User doesn't exist and that hasn't been checked !\r
-    {\r
-      Console->Print(RED, BLACK, "[Bug]: user %s doesn't exist and was not checked by code !", mName.c_str());\r
-      return false;\r
-    }\r
-\r
-    return(mPassword == Password);\r
-}\r
-\r
-bool PAccount::Create()\r
-{\r
-  if(Save(true)) {\r
-    mID = MySQL->GetLastInfoInsertId();\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::Save(bool CreateMode)\r
-{\r
-  char escUsername[256];\r
-  char escPassword[256];\r
-  MySQL->EscapeString(mName.c_str(), escUsername, 256);\r
-  MySQL->EscapeString(mPassword.c_str(), escPassword, 256);\r
-\r
-  std::string Query;\r
-  Query = CreateMode ? "INSERT INTO" : "UPDATE";\r
-  Query += "accounts SET ";\r
-  Query += Ssprintf(" accounts SET a_username='%s', a_password = '%s'", escUsername, escPassword);\r
-  Query += Ssprintf(", a_priv = %d, a_status = %d, a_bandate = %d", mLevel, mStatus, mBannedUntil);\r
-  if(!CreateMode )\r
-  {\r
-    Query += Ssprintf(" WHERE a_id = %d LIMIT 1", mID);\r
-  }\r
-\r
-  if(MySQL->InfoQuery(Query.c_str()))\r
-  {\r
-      Console->Print(RED, BLACK, "[Error] Failed to %s account %s (id %d)", CreateMode ? "create" : "update", mName.c_str(), mID);\r
-      MySQL->ShowInfoSQLError();\r
-      return false;\r
-  }\r
-  return true;\r
-}\r
-\r
-uint32_t PAccount::GetCharIdBySlot(const uint32_t SlotId)\r
-{\r
-  char query[256];\r
-  uint32_t CharId = 0;\r
-\r
-  MYSQL_ROW row = 0;\r
-  MYSQL_RES *result = 0;\r
-\r
-  snprintf(query, 256, "SELECT c_id FROM characters WHERE a_id = %d AND c_slot = %d LIMIT 1;", mID, SlotId);\r
-\r
-  result = MySQL->GameResQuery(query);\r
-  if(result == NULL)\r
-  {\r
-      Console->Print(RED, BLACK, "Failed to load CharacterData from SQL");\r
-      MySQL->ShowGameSQLError();\r
-      return 0;\r
-  }\r
-\r
-  if((row = mysql_fetch_row(result)))\r
-  {\r
-    CharId = atoi(row[0]);\r
-  }\r
-\r
-  MySQL->FreeGameSQLResult(result);\r
-\r
-  /*** Temporary workaround to cope with DB where c_slot is not set ***/\r
-  if(!CharId)\r
-  {\r
-    snprintf(query, 256, "SELECT c_id FROM characters WHERE a_id = %d ORDER BY c_slot ASC, c_id ASC LIMIT %d, 1;", mID, SlotId);\r
-\r
-    result = MySQL->GameResQuery(query);\r
-    if(result == NULL)\r
-    {\r
-        Console->Print(RED, BLACK, "Failed to load CharacterData from SQL");\r
-        MySQL->ShowGameSQLError();\r
-        return 0;\r
-    }\r
-\r
-    if((row = mysql_fetch_row(result)))\r
-    {\r
-      CharId = atoi(row[0]);\r
-    }\r
-\r
-    MySQL->FreeGameSQLResult(result);\r
-  }\r
-  /*** End of workaround ***/\r
-\r
-  return CharId;\r
-}\r
-\r
-\r
-std::string PAccount::GetBannedTime() const\r
-{\r
-  const char* unit[5] = {"seconds", "minutes", "hours", "days", "weeks"};\r
-\r
-  std::time_t timediff = mBannedUntil - std::time(NULL);\r
-  if(timediff <=0)\r
-  {\r
-    return "0 more seconds. Please relog";\r
-  }\r
-\r
-  long counter;\r
-  int type;\r
-\r
-  if(timediff > 86400)   // days\r
-  {\r
-    counter = timediff / 86400;\r
-    type = 3;\r
-  }\r
-  else if(timediff > 3600)    // hours\r
-  {\r
-    counter = timediff / 3600;\r
-    type = 2;\r
-  }\r
-  else if(timediff > 60)      // Minutes\r
-  {\r
-    counter  = timediff / 60;\r
-    type = 1;\r
-  }\r
-  else      // Seconds\r
-  {\r
-    counter = timediff;\r
-    type = 0;\r
-  }\r
-\r
-  return Ssprintf("%d more %s", counter, unit[type]);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/*
+NOTE ABOUT ACCESS LEVELS IN THE MYSQL DATABASE:
+a_priv:
+0 = unregistered user
+1 = Registered user
+30 = volunteer
+50 = GM
+100 = Admin
+
+a_status:
+0 = Offline
+1 = Online
+2 = Banned
+*/
+
+/** Static members **/
+RegEx* PAccount::mUsernameRegexFilter = NULL;
+RegEx* PAccount::mPasswordRegexFilter = NULL;
+
+bool PAccount::SetUsernameRegexFilter(const char* RegexStr)
+{
+  if(mUsernameRegexFilter)
+  {
+    delete mUsernameRegexFilter;
+    mUsernameRegexFilter = NULL;
+  }
+
+  if(RegexStr)
+  {
+    try {
+      mUsernameRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);
+    }
+    catch (...) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool PAccount::SetPasswordRegexFilter(const char* RegexStr)
+{
+  if(mPasswordRegexFilter)
+  {
+    delete mPasswordRegexFilter;
+    mPasswordRegexFilter = NULL;
+  }
+
+  if(RegexStr)
+  {
+    try {
+      mPasswordRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);
+    }
+    catch (...) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool PAccount::IsUsernameWellFormed(const char *Username)
+{
+  if(mUsernameRegexFilter)
+  {
+    return mUsernameRegexFilter->Search(Username);
+  }
+  else
+    return true;
+}
+
+bool PAccount::IsPasswordWellFormed(const char *Password)
+{
+  if(mPasswordRegexFilter)
+  {
+    return mPasswordRegexFilter->Search(Password);
+  }
+  else
+    return true;
+}
+
+/** Instance members **/
+PAccount::PAccount()
+{
+    mID = 0;
+    mLevel = PAL_BANNED;
+  mStatus = PAS_OFFLINE;
+  mBannedUntil = 0;
+}
+
+PAccount::PAccount(const uint32_t AccountId)
+{
+  char query[256];
+  mID = 0;
+  snprintf(query, 256, "SELECT * FROM accounts WHERE a_id = %d LIMIT 1;", AccountId);
+  LoadFromQuery(query);
+}
+
+PAccount::PAccount(const char *Username)
+{
+  char query[256];
+  mID = 0;
+  if(IsUsernameWellFormed(Username)) {
+    char escUsername[256];
+    MySQL->EscapeString(Username, escUsername, 256);
+    snprintf(query, 256, "SELECT * FROM accounts WHERE a_username = '%s' LIMIT 1;", escUsername);
+    LoadFromQuery(query);
+  }
+}
+
+bool PAccount::LoadFromQuery(char* query)
+{
+  MYSQL_ROW row = 0;
+  MYSQL_RES *result = 0;
+
+  bool FinalResult = false;
+
+  result = MySQL->InfoResQuery(query);
+  if(result == NULL)
+  {
+      Console->Print(RED, BLACK, "Failed to load AccountData from SQL");
+      MySQL->ShowInfoSQLError();
+      return false;
+  }
+
+  if((row = mysql_fetch_row(result)))
+  {
+    mID = atoi(row[a_id]);
+    mName = row[a_username];
+    mPassword = row[a_password];
+
+    mBannedUntil = atoi(row[a_bandate]);
+    if(mBannedUntil > time(NULL))
+    {
+      mStatus = PAS_BANNED;
+      mLevel = PAL_BANNED;
+    }
+    else
+    {
+      mStatus = PAS_OFFLINE;
+      mLevel = atoi(row[a_priv]);
+    }
+
+    FinalResult = true;
+  }
+  else
+  {
+Console->Print(YELLOW, BLACK, "Failed to load AccountData from SQL; Nothing to load...");
+  }
+
+  MySQL->FreeInfoSQLResult(result);
+  return FinalResult;
+}
+
+bool PAccount::SetName(const std::string &Username)
+{
+  if(IsUsernameWellFormed(Username.c_str()))
+  {
+    mName = Username;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::SetPassword(const std::string &Password)
+{
+  if(IsPasswordWellFormed(Password.c_str()))
+  {
+    mPassword = Password;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::SetPasswordEncoded(const uint8_t* PasswordData, int PassLen, const uint8_t* Key)
+{
+    char Pass[128];
+
+    if(DecodePassword(PasswordData, PassLen, Key, Pass))
+  {
+        return SetPassword((std::string)Pass);
+    }
+    else
+    {
+        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);
+        return false;
+    }
+}
+
+bool PAccount::SetLevel(int newLevel)
+{
+  if((newLevel >= PAL_BANNED) && (newLevel <= PAL_ADMIN))
+  {
+    mLevel = newLevel;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+std::string PAccount::GetLevelString() const
+{
+    switch(mLevel)
+    {
+        case PAL_BANNED : return "banned";
+        case PAL_UNREGPLAYER : return "unregplayer";
+        case PAL_REGPLAYER : return "regplayer";
+        case PAL_VOLUNTEER : return "volunteer";
+        case PAL_GM : return "gm";
+        case PAL_ADMIN : return "admin";
+    }
+
+    return "custom";
+}
+
+bool PAccount::SetStatus(PAccountStatus Status)
+{
+  mStatus = Status;
+  return true;
+}
+
+bool PAccount::SetBannedUntilTime(std::time_t BannedUntil)
+{
+  if ((BannedUntil == 0) || (BannedUntil > std::time(NULL)))
+  {
+    mBannedUntil = BannedUntil;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::DecodePassword(const uint8_t* PasswordData, int PassLen, const uint8_t *Key, char* ClearPassword)
+{
+  ClearPassword[0] = 0;
+
+  if(PassLen < 128)
+    {
+        if(Key[0]>7) // TODO: >7 correct?
+        {
+            for(int i=0; i<PassLen; i+=2)
+                ClearPassword[i>>1] = (char)(((PasswordData[i]&0xf0)>>4)
+                    +((PasswordData[i+1]&0x0f)<<4)-Key[0]);
+            ClearPassword[PassLen>>1]=0;
+        }
+        else
+        {
+            for(int i=0; i<PassLen; i++)
+                ClearPassword[i] = (char)(PasswordData[i]-Key[0]);
+            ClearPassword[PassLen]=0;
+        }
+        return true;
+    }
+    else
+      return false;
+}
+
+bool PAccount::Authenticate(const uint8_t* PasswordData, int PassLen, const uint8_t *Key)
+{
+    char Pass[128];
+
+    if(DecodePassword(PasswordData, PassLen, Key, Pass))
+  {
+        return Authenticate(Pass);
+    }
+    else
+    {
+        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);
+        return false;
+    }
+}
+
+bool PAccount::Authenticate(const char *Password) const
+{
+    if(mID == 0) // User doesn't exist and that hasn't been checked !
+    {
+      Console->Print(RED, BLACK, "[Bug]: user %s doesn't exist and was not checked by code !", mName.c_str());
+      return false;
+    }
+
+    return(mPassword == Password);
+}
+
+bool PAccount::Create()
+{
+  if(Save(true)) {
+    mID = MySQL->GetLastInfoInsertId();
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::Save(bool CreateMode)
+{
+  char escUsername[256];
+  char escPassword[256];
+  MySQL->EscapeString(mName.c_str(), escUsername, 256);
+  MySQL->EscapeString(mPassword.c_str(), escPassword, 256);
+
+  std::string Query;
+  Query = CreateMode ? "INSERT INTO" : "UPDATE";
+  Query += "accounts SET ";
+  Query += Ssprintf(" accounts SET a_username='%s', a_password = '%s'", escUsername, escPassword);
+  Query += Ssprintf(", a_priv = %d, a_status = %d, a_bandate = %d", mLevel, mStatus, mBannedUntil);
+  if(!CreateMode )
+  {
+    Query += Ssprintf(" WHERE a_id = %d LIMIT 1", mID);
+  }
+
+  if(MySQL->InfoQuery(Query.c_str()))
+  {
+      Console->Print(RED, BLACK, "[Error] Failed to %s account %s (id %d)", CreateMode ? "create" : "update", mName.c_str(), mID);
+      MySQL->ShowInfoSQLError();
+      return false;
+  }
+  return true;
+}
+
+uint32_t PAccount::GetCharIdBySlot(const uint32_t SlotId)
+{
+  char query[256];
+  uint32_t CharId = 0;
+
+  MYSQL_ROW row = 0;
+  MYSQL_RES *result = 0;
+
+  snprintf(query, 256, "SELECT c_id FROM characters WHERE a_id = %d AND c_slot = %d LIMIT 1;", mID, SlotId);
+
+  result = MySQL->GameResQuery(query);
+  if(result == NULL)
+  {
+      Console->Print(RED, BLACK, "Failed to load CharacterData from SQL");
+      MySQL->ShowGameSQLError();
+      return 0;
+  }
+
+  if((row = mysql_fetch_row(result)))
+  {
+    CharId = atoi(row[0]);
+  }
+
+  MySQL->FreeGameSQLResult(result);
+
+  /*** Temporary workaround to cope with DB where c_slot is not set ***/
+  if(!CharId)
+  {
+    snprintf(query, 256, "SELECT c_id FROM characters WHERE a_id = %d ORDER BY c_slot ASC, c_id ASC LIMIT %d, 1;", mID, SlotId);
+
+    result = MySQL->GameResQuery(query);
+    if(result == NULL)
+    {
+        Console->Print(RED, BLACK, "Failed to load CharacterData from SQL");
+        MySQL->ShowGameSQLError();
+        return 0;
+    }
+
+    if((row = mysql_fetch_row(result)))
+    {
+      CharId = atoi(row[0]);
+    }
+
+    MySQL->FreeGameSQLResult(result);
+  }
+  /*** End of workaround ***/
+
+  return CharId;
+}
+
+
+std::string PAccount::GetBannedTime() const
+{
+  const char* unit[5] = {"seconds", "minutes", "hours", "days", "weeks"};
+
+  std::time_t timediff = mBannedUntil - std::time(NULL);
+  if(timediff <=0)
+  {
+    return "0 more seconds. Please relog";
+  }
+
+  long counter;
+  int type;
+
+  if(timediff > 86400)   // days
+  {
+    counter = timediff / 86400;
+    type = 3;
+  }
+  else if(timediff > 3600)    // hours
+  {
+    counter = timediff / 3600;
+    type = 2;
+  }
+  else if(timediff > 60)      // Minutes
+  {
+    counter  = timediff / 60;
+    type = 1;
+  }
+  else      // Seconds
+  {
+    counter = timediff;
+    type = 0;
+  }
+
+  return Ssprintf("%d more %s", counter, unit[type]);
+}
index 7301c1e..1c0c0e3 100644 (file)
-#pragma once\r
-\r
-#include <chrono>\r
-#include <cstdint>\r
-#include <string>\r
-\r
-class RegEx;\r
-\r
-/*\r
-0 = unregistered user\r
-1 = Registered user\r
-30 = volunteer\r
-50 = GM\r
-100 = Admin\r
-*/\r
-\r
-// New way of AccountLevel handling:\r
-// Every level is possible, the following values are only edge values. We need a bit control about that\r
-#define PAL_BANNED -1\r
-#define PAL_UNREGPLAYER 0\r
-#define PAL_REGPLAYER 1\r
-#define PAL_VOLUNTEER 30 // Special Rank: 50/50\r
-#define PAL_GM 50 // Special Rank: 120/120\r
-#define PAL_ADMIN 100 // Special Rank: 127/127\r
-\r
-// Max number of char slots per account\r
-#define MAX_CHARS_PER_ACCOUNT  4\r
-\r
-/*\r
-0 = Offline\r
-1 = Online\r
-2 = Banned\r
-*/\r
-\r
-enum PAccountStatus\r
-{\r
-    PAS_OFFLINE = 0,\r
-    PAS_ONLINE = 1,\r
-    PAS_BANNED = 2\r
-};\r
-\r
-class PAccount {\r
-    private :\r
-    // SQL Layout\r
-    enum {\r
-        a_id,\r
-        a_username,\r
-        a_password,\r
-        a_priv,\r
-        a_status,\r
-        a_bandate\r
-    };\r
-\r
-    // static members\r
-      static RegEx* mUsernameRegexFilter;\r
-      static RegEx* mPasswordRegexFilter;\r
-\r
-      // instance members\r
-      uint32_t mID;\r
-      std::string mName;\r
-      std::string mPassword;\r
-    int mLevel;\r
-    PAccountStatus mStatus;\r
-    time_t mBannedUntil;\r
-\r
-    bool LoadFromQuery(char* query);\r
-    bool DecodePassword(const uint8_t* PasswordData, int PassLen, const uint8_t *Key, char* ClearPassword);\r
-\r
-    public :\r
-      PAccount();\r
-      PAccount(const uint32_t AccountId);\r
-      PAccount(const char *Username);\r
-\r
-      static bool SetUsernameRegexFilter(const char* RegexStr);\r
-        static bool SetPasswordRegexFilter(const char* RegexStr);\r
-        static bool IsUsernameWellFormed(const char *Username);\r
-        static bool IsPasswordWellFormed(const char *Password);\r
-\r
-        inline uint32_t GetID() const { return mID; }\r
-        bool SetName(const std::string &Pass);\r
-        inline const std::string &GetName() const { return mName; }\r
-        bool SetPassword(const std::string &Pass);\r
-        bool SetPasswordEncoded(const uint8_t* PasswordData, int PassLen, const uint8_t *Key);\r
-        inline const std::string &GetPassword() const { return mPassword; }\r
-    bool SetLevel(int newLevel);\r
-        inline int GetLevel() const { return mLevel; }\r
-        std::string GetLevelString() const;\r
-    bool SetStatus(PAccountStatus Status);\r
-        inline PAccountStatus GetStatus() const { return mStatus; }\r
-        bool SetBannedUntilTime(time_t BannedUntil);\r
-    inline bool IsBanned() const { return (mBannedUntil > std::time(NULL)); }\r
-    std::string GetBannedTime() const;\r
-\r
-        bool Authenticate(const uint8_t* PasswordData, int PassLen, const uint8_t *Key);\r
-        bool Authenticate(const char *Password) const;\r
-\r
-        bool Create();\r
-    bool Save(bool CreateMode = false);\r
-\r
-    uint32_t GetCharIdBySlot(const uint32_t SlotId);\r
-};\r
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#include <string>
+
+class RegEx;
+
+/*
+0 = unregistered user
+1 = Registered user
+30 = volunteer
+50 = GM
+100 = Admin
+*/
+
+// New way of AccountLevel handling:
+// Every level is possible, the following values are only edge values. We need a bit control about that
+#define PAL_BANNED -1
+#define PAL_UNREGPLAYER 0
+#define PAL_REGPLAYER 1
+#define PAL_VOLUNTEER 30 // Special Rank: 50/50
+#define PAL_GM 50 // Special Rank: 120/120
+#define PAL_ADMIN 100 // Special Rank: 127/127
+
+// Max number of char slots per account
+#define MAX_CHARS_PER_ACCOUNT  4
+
+/*
+0 = Offline
+1 = Online
+2 = Banned
+*/
+
+enum PAccountStatus
+{
+    PAS_OFFLINE = 0,
+    PAS_ONLINE = 1,
+    PAS_BANNED = 2
+};
+
+class PAccount {
+    private :
+    // SQL Layout
+    enum {
+        a_id,
+        a_username,
+        a_password,
+        a_priv,
+        a_status,
+        a_bandate
+    };
+
+    // static members
+      static RegEx* mUsernameRegexFilter;
+      static RegEx* mPasswordRegexFilter;
+
+      // instance members
+      uint32_t mID;
+      std::string mName;
+      std::string mPassword;
+    int mLevel;
+    PAccountStatus mStatus;
+    time_t mBannedUntil;
+
+    bool LoadFromQuery(char* query);
+    bool DecodePassword(const uint8_t* PasswordData, int PassLen, const uint8_t *Key, char* ClearPassword);
+
+    public :
+      PAccount();
+      PAccount(const uint32_t AccountId);
+      PAccount(const char *Username);
+
+      static bool SetUsernameRegexFilter(const char* RegexStr);
+        static bool SetPasswordRegexFilter(const char* RegexStr);
+        static bool IsUsernameWellFormed(const char *Username);
+        static bool IsPasswordWellFormed(const char *Password);
+
+        inline uint32_t GetID() const { return mID; }
+        bool SetName(const std::string &Pass);
+        inline const std::string &GetName() const { return mName; }
+        bool SetPassword(const std::string &Pass);
+        bool SetPasswordEncoded(const uint8_t* PasswordData, int PassLen, const uint8_t *Key);
+        inline const std::string &GetPassword() const { return mPassword; }
+    bool SetLevel(int newLevel);
+        inline int GetLevel() const { return mLevel; }
+        std::string GetLevelString() const;
+    bool SetStatus(PAccountStatus Status);
+        inline PAccountStatus GetStatus() const { return mStatus; }
+        bool SetBannedUntilTime(time_t BannedUntil);
+    inline bool IsBanned() const { return (mBannedUntil > std::time(NULL)); }
+    std::string GetBannedTime() const;
+
+        bool Authenticate(const uint8_t* PasswordData, int PassLen, const uint8_t *Key);
+        bool Authenticate(const char *Password) const;
+
+        bool Create();
+    bool Save(bool CreateMode = false);
+
+    uint32_t GetCharIdBySlot(const uint32_t SlotId);
+};
index 062ecc3..7c0f45a 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PAppartements::PAppartements()\r
-{\r
-}\r
-\r
-//PAppartements::~PAppartements() {};\r
-\r
-uint32_t PAppartements::CreateBaseAppartement(uint32_t nCharID, std::string nPassword, uint8_t nFactionID)\r
-{\r
-  typedef std::vector< std::pair<int, int> > PAppVector; //<AppType, AppPlace>\r
-\r
-  PAppVector CandidateApts;\r
-  CandidateApts.reserve(32);\r
-  uint16_t j;\r
-  int AppType;\r
-\r
-  for (std::map<int, PDefAppartement*>::const_iterator i=GameDefs->Appartements()->ConstIteratorBegin(); i!=GameDefs->Appartements()->ConstIteratorEnd(); i++)\r
-  {\r
-    if (i->second->GetFaction() == nFactionID)\r
-    {\r
-      for (j = 0; j < i->second->GetPlaceCount(); j++)\r
-      {\r
-        AppType = i->second->GetID();\r
-        if ((AppType < 220) || (AppType >= 250))\r
-        {\r
-if (gDevDebug) Console->Print("Added potential Apt of type %d in place %d", AppType, i->second->GetPlace(j));\r
-          CandidateApts.push_back(std::make_pair(AppType, i->second->GetPlace(j)));\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  if(CandidateApts.size())\r
-  {\r
-    j = GetRandom(CandidateApts.size()-1);\r
-if (gDevDebug) Console->Print("Apt n� %d chosen in %d for faction %d", j+1, CandidateApts.size(), nFactionID);\r
-\r
-if (gDevDebug) Console->Print("Choosed Apt of type %d in place %d", CandidateApts[j].first, CandidateApts[j].second);\r
-\r
-    char escPassword[256];\r
-    MySQL->EscapeString(nPassword.c_str(), escPassword, 256);\r
-    char query[256];\r
-    snprintf(query, 256, "INSERT INTO apartments (apt_id,apt_location,apt_type,apt_password, apt_owner) VALUES (NULL,'%d','%d','%s','%d');", CandidateApts[j].second, CandidateApts[j].first, escPassword, nCharID);\r
-    if ( MySQL->GameQuery(query) )\r
-    {\r
-        Console->Print(RED, BLACK, "PAppartements::CreateBaseAppartement could not add some appartement entry in the database");\r
-        Console->Print("Query was:");\r
-        Console->Print("%s", query);\r
-        MySQL->ShowGameSQLError();\r
-        return 0;\r
-    }\r
-    return (MySQL->GetLastGameInsertId());\r
-  }\r
-  else\r
-    return 0;\r
-}\r
-\r
-void PAppartements::DeleteCharAppartements(uint32_t nCharID)\r
-{\r
-    char query[256];\r
-    snprintf(query, 256, "DELETE FROM apartments WHERE (apt_owner='%u');", nCharID);\r
-    if ( MySQL->GameQuery(query) )\r
-    {\r
-        Console->Print(RED, BLACK, "PAppartements::DeleteCharAppartements could not delete some char %d appartement(s) entry from the database", nCharID);\r
-        Console->Print("Query was:");\r
-        Console->Print("%s", query);\r
-        MySQL->ShowGameSQLError();\r
-    }\r
-    else\r
-if (gDevDebug) Console->Print(YELLOW, BLACK, "PAppartements::DeleteCharAppartements does not delete appartements content yet");      \r
-}\r
-\r
-bool PAppartements::CanFreelyEnter(PChar* nChar, uint32_t nLocation)\r
-{\r
-  uint32_t OwnerID = GetAptOwner(nLocation);\r
-  return (OwnerID == nChar->GetID());\r
-\r
-  // here we could manage Clan appartements access too.\r
-}\r
-\r
-int PAppartements::GetAptID(unsigned int AptLoc, const uint8_t *pass)\r
-{\r
-    int type;\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    char query[255];\r
-\r
-    if(!strcmp((const char*)pass, "Exit"))\r
-        return 1;\r
-\r
-    char escPassword[255];\r
-    MySQL->EscapeString((char*)pass, escPassword, 255);\r
-    snprintf(query, 255, "SELECT apt_id FROM apartments WHERE apt_location = %i AND apt_password = '%s'", AptLoc, escPassword);\r
-    result = MySQL->GameResQuery(query);\r
-\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get AppartmentID; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        MySQL->ShowGameSQLError();\r
-        return 0;\r
-    }\r
-\r
-    if(mysql_num_rows(result) == 0)\r
-    {\r
-        MySQL->FreeGameSQLResult(result);\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        row = mysql_fetch_row(result);\r
-        type = atoi(row[0]);\r
-        MySQL->FreeGameSQLResult(result);\r
-    }\r
-\r
-    return (type + PWorlds::mAptBaseWorldId);\r
-}\r
-\r
-int PAppartements::GetAptType(int AptID)\r
-{\r
-    int type;\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    char query[255];\r
-\r
-    snprintf(query, 225, "SELECT apt_type FROM apartments WHERE apt_id = %i", AptID - PWorlds::mAptBaseWorldId);\r
-    result = MySQL->GameResQuery(query);\r
-\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get AppartmentType; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        MySQL->ShowGameSQLError();\r
-        return 0;\r
-    }\r
-\r
-    if(mysql_num_rows(result) == 0)\r
-    {\r
-        MySQL->FreeGameSQLResult(result);\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        row = mysql_fetch_row(result);\r
-        type = atoi(row[0]);\r
-        MySQL->FreeGameSQLResult(result);\r
-    }\r
-\r
-    return type;\r
-}\r
-\r
-int PAppartements::GetAptOwner(int loc)\r
-{\r
-    int owner;\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    char query[255];\r
-\r
-    snprintf (query, 255, "SELECT apt_owner FROM apartments WHERE apt_id = %i", loc - PWorlds::mAptBaseWorldId);\r
-\r
-    result = MySQL->GameResQuery(query);\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get AppartmentOwner; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        MySQL->ShowGameSQLError();\r
-        return 0;\r
-    }\r
-\r
-    if(mysql_num_rows(result) == 0)\r
-    {\r
-        MySQL->FreeGameSQLResult(result);\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        row = mysql_fetch_row(result);\r
-        owner = atoi(row[0]);\r
-        MySQL->FreeGameSQLResult(result);\r
-    }\r
-\r
-    return owner;\r
-}\r
-\r
-int PAppartements::GetAptLocation(int loc)\r
-{\r
-    int Location;\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    char query[255];\r
-\r
-    if((uint32_t)loc > PWorlds::mAptBaseWorldId)\r
-        loc = loc - PWorlds::mAptBaseWorldId;\r
-\r
-    snprintf (query, 255, "SELECT apt_location FROM apartments WHERE apt_id = %i", loc);\r
-\r
-//Console->Print("Q: %s", query);\r
-    result = MySQL->GameResQuery(query);\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get AppartmentLocation; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        MySQL->ShowGameSQLError();\r
-        return 0;\r
-    }\r
-\r
-    if(mysql_num_rows(result) == 0)\r
-    {\r
-        MySQL->FreeGameSQLResult(result);\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        row = mysql_fetch_row(result);\r
-        Location = atoi(row[0]);\r
-        MySQL->FreeGameSQLResult(result);\r
-    }\r
-\r
-    return Location;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PAppartements::PAppartements()
+{
+}
+
+//PAppartements::~PAppartements() {};
+
+uint32_t PAppartements::CreateBaseAppartement(uint32_t nCharID, std::string nPassword, uint8_t nFactionID)
+{
+  typedef std::vector< std::pair<int, int> > PAppVector; //<AppType, AppPlace>
+
+  PAppVector CandidateApts;
+  CandidateApts.reserve(32);
+  uint16_t j;
+  int AppType;
+
+  for (std::map<int, PDefAppartement*>::const_iterator i=GameDefs->Appartements()->ConstIteratorBegin(); i!=GameDefs->Appartements()->ConstIteratorEnd(); i++)
+  {
+    if (i->second->GetFaction() == nFactionID)
+    {
+      for (j = 0; j < i->second->GetPlaceCount(); j++)
+      {
+        AppType = i->second->GetID();
+        if ((AppType < 220) || (AppType >= 250))
+        {
+if (gDevDebug) Console->Print("Added potential Apt of type %d in place %d", AppType, i->second->GetPlace(j));
+          CandidateApts.push_back(std::make_pair(AppType, i->second->GetPlace(j)));
+        }
+      }
+    }
+  }
+
+  if(CandidateApts.size())
+  {
+    j = GetRandom(CandidateApts.size()-1);
+if (gDevDebug) Console->Print("Apt n� %d chosen in %d for faction %d", j+1, CandidateApts.size(), nFactionID);
+
+if (gDevDebug) Console->Print("Choosed Apt of type %d in place %d", CandidateApts[j].first, CandidateApts[j].second);
+
+    char escPassword[256];
+    MySQL->EscapeString(nPassword.c_str(), escPassword, 256);
+    char query[256];
+    snprintf(query, 256, "INSERT INTO apartments (apt_id,apt_location,apt_type,apt_password, apt_owner) VALUES (NULL,'%d','%d','%s','%d');", CandidateApts[j].second, CandidateApts[j].first, escPassword, nCharID);
+    if ( MySQL->GameQuery(query) )
+    {
+        Console->Print(RED, BLACK, "PAppartements::CreateBaseAppartement could not add some appartement entry in the database");
+        Console->Print("Query was:");
+        Console->Print("%s", query);
+        MySQL->ShowGameSQLError();
+        return 0;
+    }
+    return (MySQL->GetLastGameInsertId());
+  }
+  else
+    return 0;
+}
+
+void PAppartements::DeleteCharAppartements(uint32_t nCharID)
+{
+    char query[256];
+    snprintf(query, 256, "DELETE FROM apartments WHERE (apt_owner='%u');", nCharID);
+    if ( MySQL->GameQuery(query) )
+    {
+        Console->Print(RED, BLACK, "PAppartements::DeleteCharAppartements could not delete some char %d appartement(s) entry from the database", nCharID);
+        Console->Print("Query was:");
+        Console->Print("%s", query);
+        MySQL->ShowGameSQLError();
+    }
+    else
+if (gDevDebug) Console->Print(YELLOW, BLACK, "PAppartements::DeleteCharAppartements does not delete appartements content yet");      
+}
+
+bool PAppartements::CanFreelyEnter(PChar* nChar, uint32_t nLocation)
+{
+  uint32_t OwnerID = GetAptOwner(nLocation);
+  return (OwnerID == nChar->GetID());
+
+  // here we could manage Clan appartements access too.
+}
+
+int PAppartements::GetAptID(unsigned int AptLoc, const uint8_t *pass)
+{
+    int type;
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    char query[255];
+
+    if(!strcmp((const char*)pass, "Exit"))
+        return 1;
+
+    char escPassword[255];
+    MySQL->EscapeString((char*)pass, escPassword, 255);
+    snprintf(query, 255, "SELECT apt_id FROM apartments WHERE apt_location = %i AND apt_password = '%s'", AptLoc, escPassword);
+    result = MySQL->GameResQuery(query);
+
+    if(!result)
+    {
+        Console->Print("%s Cannot get AppartmentID; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        MySQL->ShowGameSQLError();
+        return 0;
+    }
+
+    if(mysql_num_rows(result) == 0)
+    {
+        MySQL->FreeGameSQLResult(result);
+        return 0;
+    }
+    else
+    {
+        row = mysql_fetch_row(result);
+        type = atoi(row[0]);
+        MySQL->FreeGameSQLResult(result);
+    }
+
+    return (type + PWorlds::mAptBaseWorldId);
+}
+
+int PAppartements::GetAptType(int AptID)
+{
+    int type;
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    char query[255];
+
+    snprintf(query, 225, "SELECT apt_type FROM apartments WHERE apt_id = %i", AptID - PWorlds::mAptBaseWorldId);
+    result = MySQL->GameResQuery(query);
+
+    if(!result)
+    {
+        Console->Print("%s Cannot get AppartmentType; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        MySQL->ShowGameSQLError();
+        return 0;
+    }
+
+    if(mysql_num_rows(result) == 0)
+    {
+        MySQL->FreeGameSQLResult(result);
+        return 0;
+    }
+    else
+    {
+        row = mysql_fetch_row(result);
+        type = atoi(row[0]);
+        MySQL->FreeGameSQLResult(result);
+    }
+
+    return type;
+}
+
+int PAppartements::GetAptOwner(int loc)
+{
+    int owner;
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    char query[255];
+
+    snprintf (query, 255, "SELECT apt_owner FROM apartments WHERE apt_id = %i", loc - PWorlds::mAptBaseWorldId);
+
+    result = MySQL->GameResQuery(query);
+    if(!result)
+    {
+        Console->Print("%s Cannot get AppartmentOwner; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        MySQL->ShowGameSQLError();
+        return 0;
+    }
+
+    if(mysql_num_rows(result) == 0)
+    {
+        MySQL->FreeGameSQLResult(result);
+        return 0;
+    }
+    else
+    {
+        row = mysql_fetch_row(result);
+        owner = atoi(row[0]);
+        MySQL->FreeGameSQLResult(result);
+    }
+
+    return owner;
+}
+
+int PAppartements::GetAptLocation(int loc)
+{
+    int Location;
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    char query[255];
+
+    if((uint32_t)loc > PWorlds::mAptBaseWorldId)
+        loc = loc - PWorlds::mAptBaseWorldId;
+
+    snprintf (query, 255, "SELECT apt_location FROM apartments WHERE apt_id = %i", loc);
+
+//Console->Print("Q: %s", query);
+    result = MySQL->GameResQuery(query);
+    if(!result)
+    {
+        Console->Print("%s Cannot get AppartmentLocation; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        MySQL->ShowGameSQLError();
+        return 0;
+    }
+
+    if(mysql_num_rows(result) == 0)
+    {
+        MySQL->FreeGameSQLResult(result);
+        return 0;
+    }
+    else
+    {
+        row = mysql_fetch_row(result);
+        Location = atoi(row[0]);
+        MySQL->FreeGameSQLResult(result);
+    }
+
+    return Location;
+}
index 9643be0..9ea301b 100644 (file)
@@ -1,20 +1,20 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-\r
-class PChar;\r
-\r
-class PAppartements {\r
-public:\r
-    PAppartements();\r
-    //~PAppartements();\r
-\r
-    uint32_t CreateBaseAppartement(uint32_t nCharID, std::string nPassword, uint8_t nFactionID);\r
-    void DeleteCharAppartements(uint32_t nCharID);\r
-    bool CanFreelyEnter(PChar* nChar, uint32_t nLocation);\r
-    int GetAptID(unsigned int AptLoc, const uint8_t *pass);\r
-    int GetAptType(int AptID);\r
-    int GetAptOwner(int loc);\r
-    int GetAptLocation(int loc);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+class PChar;
+
+class PAppartements {
+public:
+    PAppartements();
+    //~PAppartements();
+
+    uint32_t CreateBaseAppartement(uint32_t nCharID, std::string nPassword, uint8_t nFactionID);
+    void DeleteCharAppartements(uint32_t nCharID);
+    bool CanFreelyEnter(PChar* nChar, uint32_t nLocation);
+    int GetAptID(unsigned int AptLoc, const uint8_t *pass);
+    int GetAptType(int AptID);
+    int GetAptOwner(int loc);
+    int GetAptLocation(int loc);
+};
index 54f32f4..79ac545 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PBuddyList::PBuddyList(uint32_t nOwnerCharID)\r
-{\r
-    mOwnerCharID = nOwnerCharID;\r
-    mListMaxSize = mListSize = 0;\r
-    mCharIDList = NULL;\r
-}\r
-\r
-PBuddyList::~PBuddyList()\r
-{\r
-\r
-    if (mCharIDList)\r
-        delete[] mCharIDList;\r
-}\r
-\r
-bool PBuddyList::AddChar(uint32_t nBuddyCharID)\r
-{\r
-    char query[256];\r
-\r
-    if ((FindEntry(nBuddyCharID) >= mListSize) && (mListSize < 255))\r
-    {\r
-        if (mListSize == mListMaxSize)\r
-        {\r
-            IncreaseMaxSize();\r
-        }\r
-        mCharIDList[mListSize++] = nBuddyCharID;\r
-\r
-        snprintf(query, 256, "INSERT INTO buddy_list (bud_id,bud_charid,bud_buddyid) VALUES (NULL,'%u','%u');", mOwnerCharID, nBuddyCharID);\r
-        if ( MySQL->GameQuery(query) )\r
-        {\r
-            Console->Print(RED, BLACK, "PBuddyList::AddChar could not add some buddylisdt entry in the database");\r
-            Console->Print("Query was:");\r
-            Console->Print("%s", query);\r
-            MySQL->ShowGameSQLError();\r
-            return false;\r
-        }\r
-\r
-        return true;\r
-    }\r
-    else\r
-        return false;\r
-}\r
-\r
-bool PBuddyList::RemoveChar(uint32_t nBuddyCharID)\r
-{\r
-    char query[256];\r
-    uint8_t rEntry, i;\r
-\r
-    if ((rEntry = FindEntry(nBuddyCharID)) < mListSize)\r
-    {\r
-        --mListSize;\r
-        for (i = rEntry; i < mListSize; i++)\r
-        {\r
-            mCharIDList[i] = mCharIDList[i+1];\r
-        }\r
-        // Remove from DB here\r
-        snprintf(query, 256, "DELETE FROM buddy_list WHERE ((bud_charid='%u') AND (bud_buddyid='%u')) LIMIT 1;", mOwnerCharID, nBuddyCharID);\r
-        if ( MySQL->GameQuery(query) )\r
-        {\r
-            Console->Print(RED, BLACK, "PBuddyList::AddChar could not delete some buddylist entry from the database");\r
-            Console->Print("Query was:");\r
-            Console->Print("%s", query);\r
-            MySQL->ShowGameSQLError();\r
-            return false;\r
-        }\r
-\r
-        return true;\r
-    }\r
-    else\r
-        return false;\r
-}\r
-\r
-bool PBuddyList::SQLLoad()\r
-{\r
-    char query[256];\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    uint8_t EntriesNum;\r
-\r
-    snprintf(query, 256, "SELECT * FROM buddy_list WHERE (bud_charid='%u')", mOwnerCharID);\r
-    result = MySQL->GameResQuery(query);\r
-    if(result == NULL)\r
-    {\r
-        Console->Print(RED, BLACK, "PBuddyList::SQLLoad could not load buddylist entry from the database");\r
-        Console->Print("Query was:");\r
-        Console->Print("%s", query);\r
-        MySQL->ShowGameSQLError();\r
-        return false;\r
-    }\r
-    //Console->Print(GREEN, BLACK, "PBuddyList::SQLLoad Loading buddylist for char %d", mOwnerCharID);\r
-    mListSize = 0;\r
-    if((EntriesNum = mysql_num_rows(result)))\r
-    {\r
-        IncreaseMaxSize(EntriesNum);\r
-\r
-        while((row = mysql_fetch_row(result)))\r
-        {\r
-            mCharIDList[mListSize++] = atoi(row[bud_buddyid]);\r
-            //Console->Print(GREEN, BLACK, "PBuddyList::SQLLoad Buddylist entry %d : char %d", mListSize, mCharIDList[mListSize-1]);\r
-        }\r
-    }\r
-    MySQL->FreeGameSQLResult(result);\r
-    return true;\r
-}\r
-\r
-void PBuddyList::IncreaseMaxSize(uint8_t nNewMax)\r
-{\r
-    uint16_t tmpSize;\r
-\r
-    if (!nNewMax)\r
-    {\r
-        tmpSize = mListMaxSize + BUDDYLIST_ALLOC_SIZE;\r
-    }\r
-    else if (nNewMax > mListMaxSize)\r
-    {\r
-        tmpSize = nNewMax / BUDDYLIST_ALLOC_SIZE;\r
-        if (nNewMax % BUDDYLIST_ALLOC_SIZE)\r
-            ++tmpSize;\r
-        tmpSize *= BUDDYLIST_ALLOC_SIZE;\r
-    }\r
-    else\r
-        return;\r
-\r
-    mListMaxSize = (tmpSize < 256) ? tmpSize : 255;\r
-\r
-    uint32_t* tmpList = new uint32_t[mListMaxSize];\r
-    if (mCharIDList)\r
-    {\r
-        if (mListSize)\r
-        {\r
-            memcpy(tmpList, mCharIDList, sizeof(uint32_t) * mListSize);\r
-        }\r
-\r
-        delete[] mCharIDList;\r
-    }\r
-    mCharIDList = tmpList;\r
-}\r
-\r
-uint8_t PBuddyList::FindEntry(uint32_t CharID)\r
-{\r
-    uint8_t i = 255;\r
-\r
-    if (mCharIDList)\r
-    {\r
-        for (i = 0; i < mListSize; i++)\r
-        {\r
-            if (mCharIDList[i] == CharID)\r
-                break;\r
-        }\r
-    }\r
-\r
-    return i;\r
-}\r
-\r
-bool PBuddyList::IsInBuddy(uint32_t CharID)\r
-{\r
-    if (mCharIDList)\r
-    {\r
-        for (uint8_t i = 0; i < mListSize; i++)\r
-        {\r
-            if (mCharIDList[i] == CharID)\r
-                return true;\r
-        }\r
-    }\r
-    return false;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PBuddyList::PBuddyList(uint32_t nOwnerCharID)
+{
+    mOwnerCharID = nOwnerCharID;
+    mListMaxSize = mListSize = 0;
+    mCharIDList = NULL;
+}
+
+PBuddyList::~PBuddyList()
+{
+
+    if (mCharIDList)
+        delete[] mCharIDList;
+}
+
+bool PBuddyList::AddChar(uint32_t nBuddyCharID)
+{
+    char query[256];
+
+    if ((FindEntry(nBuddyCharID) >= mListSize) && (mListSize < 255))
+    {
+        if (mListSize == mListMaxSize)
+        {
+            IncreaseMaxSize();
+        }
+        mCharIDList[mListSize++] = nBuddyCharID;
+
+        snprintf(query, 256, "INSERT INTO buddy_list (bud_id,bud_charid,bud_buddyid) VALUES (NULL,'%u','%u');", mOwnerCharID, nBuddyCharID);
+        if ( MySQL->GameQuery(query) )
+        {
+            Console->Print(RED, BLACK, "PBuddyList::AddChar could not add some buddylisdt entry in the database");
+            Console->Print("Query was:");
+            Console->Print("%s", query);
+            MySQL->ShowGameSQLError();
+            return false;
+        }
+
+        return true;
+    }
+    else
+        return false;
+}
+
+bool PBuddyList::RemoveChar(uint32_t nBuddyCharID)
+{
+    char query[256];
+    uint8_t rEntry, i;
+
+    if ((rEntry = FindEntry(nBuddyCharID)) < mListSize)
+    {
+        --mListSize;
+        for (i = rEntry; i < mListSize; i++)
+        {
+            mCharIDList[i] = mCharIDList[i+1];
+        }
+        // Remove from DB here
+        snprintf(query, 256, "DELETE FROM buddy_list WHERE ((bud_charid='%u') AND (bud_buddyid='%u')) LIMIT 1;", mOwnerCharID, nBuddyCharID);
+        if ( MySQL->GameQuery(query) )
+        {
+            Console->Print(RED, BLACK, "PBuddyList::AddChar could not delete some buddylist entry from the database");
+            Console->Print("Query was:");
+            Console->Print("%s", query);
+            MySQL->ShowGameSQLError();
+            return false;
+        }
+
+        return true;
+    }
+    else
+        return false;
+}
+
+bool PBuddyList::SQLLoad()
+{
+    char query[256];
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    uint8_t EntriesNum;
+
+    snprintf(query, 256, "SELECT * FROM buddy_list WHERE (bud_charid='%u')", mOwnerCharID);
+    result = MySQL->GameResQuery(query);
+    if(result == NULL)
+    {
+        Console->Print(RED, BLACK, "PBuddyList::SQLLoad could not load buddylist entry from the database");
+        Console->Print("Query was:");
+        Console->Print("%s", query);
+        MySQL->ShowGameSQLError();
+        return false;
+    }
+    //Console->Print(GREEN, BLACK, "PBuddyList::SQLLoad Loading buddylist for char %d", mOwnerCharID);
+    mListSize = 0;
+    if((EntriesNum = mysql_num_rows(result)))
+    {
+        IncreaseMaxSize(EntriesNum);
+
+        while((row = mysql_fetch_row(result)))
+        {
+            mCharIDList[mListSize++] = atoi(row[bud_buddyid]);
+            //Console->Print(GREEN, BLACK, "PBuddyList::SQLLoad Buddylist entry %d : char %d", mListSize, mCharIDList[mListSize-1]);
+        }
+    }
+    MySQL->FreeGameSQLResult(result);
+    return true;
+}
+
+void PBuddyList::IncreaseMaxSize(uint8_t nNewMax)
+{
+    uint16_t tmpSize;
+
+    if (!nNewMax)
+    {
+        tmpSize = mListMaxSize + BUDDYLIST_ALLOC_SIZE;
+    }
+    else if (nNewMax > mListMaxSize)
+    {
+        tmpSize = nNewMax / BUDDYLIST_ALLOC_SIZE;
+        if (nNewMax % BUDDYLIST_ALLOC_SIZE)
+            ++tmpSize;
+        tmpSize *= BUDDYLIST_ALLOC_SIZE;
+    }
+    else
+        return;
+
+    mListMaxSize = (tmpSize < 256) ? tmpSize : 255;
+
+    uint32_t* tmpList = new uint32_t[mListMaxSize];
+    if (mCharIDList)
+    {
+        if (mListSize)
+        {
+            memcpy(tmpList, mCharIDList, sizeof(uint32_t) * mListSize);
+        }
+
+        delete[] mCharIDList;
+    }
+    mCharIDList = tmpList;
+}
+
+uint8_t PBuddyList::FindEntry(uint32_t CharID)
+{
+    uint8_t i = 255;
+
+    if (mCharIDList)
+    {
+        for (i = 0; i < mListSize; i++)
+        {
+            if (mCharIDList[i] == CharID)
+                break;
+        }
+    }
+
+    return i;
+}
+
+bool PBuddyList::IsInBuddy(uint32_t CharID)
+{
+    if (mCharIDList)
+    {
+        for (uint8_t i = 0; i < mListSize; i++)
+        {
+            if (mCharIDList[i] == CharID)
+                return true;
+        }
+    }
+    return false;
+}
index 257c23d..21455bd 100644 (file)
@@ -1,35 +1,35 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-#define BUDDYLIST_ALLOC_SIZE 4 // atomicity of list entries allocation\r
-\r
-class PBuddyList {\r
-  private:\r
-    enum { // buddy_list DB Table fields\r
-        bud_id = 0,\r
-        bud_charid,\r
-        bud_buddyid\r
-    };\r
-\r
-    uint32_t mOwnerCharID;\r
-    uint8_t mListMaxSize;\r
-    uint8_t mListSize;\r
-    uint32_t* mCharIDList;\r
-\r
-    void IncreaseMaxSize(uint8_t nNewMax = 0);\r
-    uint8_t FindEntry(uint32_t CharID);\r
-\r
-  public:\r
-    PBuddyList(uint32_t nOwnerCharID);\r
-    ~PBuddyList();\r
-    bool AddChar(uint32_t nBuddyCharID);\r
-    bool RemoveChar(uint32_t nBuddyCharID);\r
-    inline uint8_t Count() { return mListSize; }\r
-    uint16_t GetListDataSize() { return (sizeof(uint32_t) * mListSize); }\r
-    const void* GetListData() { return (const void*)mCharIDList; }\r
-    bool SQLLoad();\r
-\r
-    bool IsInBuddy(uint32_t CharID);\r
-//    bool SQLSave();\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+#define BUDDYLIST_ALLOC_SIZE 4 // atomicity of list entries allocation
+
+class PBuddyList {
+  private:
+    enum { // buddy_list DB Table fields
+        bud_id = 0,
+        bud_charid,
+        bud_buddyid
+    };
+
+    uint32_t mOwnerCharID;
+    uint8_t mListMaxSize;
+    uint8_t mListSize;
+    uint32_t* mCharIDList;
+
+    void IncreaseMaxSize(uint8_t nNewMax = 0);
+    uint8_t FindEntry(uint32_t CharID);
+
+  public:
+    PBuddyList(uint32_t nOwnerCharID);
+    ~PBuddyList();
+    bool AddChar(uint32_t nBuddyCharID);
+    bool RemoveChar(uint32_t nBuddyCharID);
+    inline uint8_t Count() { return mListSize; }
+    uint16_t GetListDataSize() { return (sizeof(uint32_t) * mListSize); }
+    const void* GetListData() { return (const void*)mCharIDList; }
+    bool SQLLoad();
+
+    bool IsInBuddy(uint32_t CharID);
+//    bool SQLSave();
+};
index cd9f727..f247f8a 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// PCharCoordinates\r
-void PCharCoordinates::SetInterpolate( PCharCoordinates& Pos1, PCharCoordinates& Pos2, float nCoef )\r
-{\r
-  if (( nCoef < 0 ) || ( nCoef > 1 ) )\r
-  {\r
-    Console->Print( RED, BLACK, "[Error] PCharCoordinates::Interpolate : Invalid nCoef value: %f", nCoef );\r
-    nCoef = 0;\r
-  }\r
-  float rCoef = 1 - nCoef;\r
-\r
-  mY = ( uint16_t )( rCoef * Pos1.mY + nCoef * Pos2.mY );\r
-  mZ = ( uint16_t )( rCoef * Pos1.mZ + nCoef * Pos2.mZ );\r
-  mX = ( uint16_t )( rCoef * Pos1.mX + nCoef * Pos2.mX );\r
-  mUD = ( uint8_t )( rCoef * Pos1.mUD + nCoef * Pos2.mUD );\r
-  if ( abs( Pos1.mLR - Pos2.mLR ) < 90 )\r
-  {\r
-    mLR = ( uint8_t )( rCoef * Pos1.mLR + nCoef * Pos2.mLR );\r
-  }\r
-  else\r
-  {\r
-    mLR = ( uint8_t )(( uint16_t )( rCoef * ( 180.0 + ( float )Pos1.mLR ) + nCoef * Pos2.mLR ) % 180 );\r
-  }\r
-}\r
-\r
-uint16_t mY;     // Y-Position in world\r
-uint16_t mZ;     // Z-Position in world\r
-uint16_t mX;     // X-Position in world\r
-uint8_t mUD;     // Up - Mid - Down (d6 - 80 - 2a)\r
-uint8_t mLR;     // Compass direction (S..E..N..W..S [0-45-90-135-179])\r
-uint8_t mAct;    // Last user action state\r
-\r
-void PCharCoordinates::SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD, uint8_t nLR )\r
-{\r
-  mY = nY;\r
-  mZ = nZ;\r
-  mX = nX;\r
-  mUD = nUD;\r
-  if ( mUD < 0x2a )\r
-  {\r
-    mUD = 0x2a;\r
-  }\r
-  else if ( mUD > 0xd6 )\r
-  {\r
-    mUD = 0xd6;\r
-  }\r
-  mLR = nLR % 180;\r
-}\r
-\r
-\r
-// SQL Layout\r
-enum\r
-{\r
-    c_id,\r
-    c_name,\r
-    c_str_lvl,\r
-    c_str_pts,\r
-    c_int_lvl,\r
-    c_int_pts,\r
-    c_dex_lvl,\r
-    c_dex_pts,\r
-    c_con_lvl,\r
-    c_con_pts,\r
-    c_psi_lvl,\r
-    c_psi_pts,\r
-    a_id,\r
-    c_class,\r
-    c_profession,\r
-    c_sex,\r
-    c_location,\r
-    c_mc,\r
-    c_hc,\r
-    c_tra,\r
-    c_pc,\r
-    c_rc,\r
-    c_tc,\r
-    c_vhc,\r
-    c_agl,\r
-    c_rep,\r
-    c_rec,\r
-    c_rcl,\r
-    c_atl,\r
-    c_end,\r
-    c_for,\r
-    c_fir,\r
-    c_enr,\r
-    c_xrr,\r
-    c_por,\r
-    c_hlt,\r
-    c_hck,\r
-    c_brt,\r
-    c_psu,\r
-    c_wep,\r
-    c_cst,\r
-    c_res,\r
-    c_imp,\r
-    c_ppu,\r
-    c_apu,\r
-    c_mst,\r
-    c_ppw,\r
-    c_psr,\r
-    c_wpw,\r
-    c_apt,\r
-    c_cash,\r
-    c_head,\r
-    c_torso,\r
-    c_legs,\r
-    c_str_xp,\r
-    c_int_xp,\r
-    c_dex_xp,\r
-    c_psi_xp,\r
-    c_con_xp,\r
-    c_pos_x,\r
-    c_pos_y,\r
-    c_pos_z,\r
-    c_angle_ud,\r
-    c_angle_lr,\r
-    c_faction,\r
-    c_slot,\r
-    c_online,\r
-    c_clan,\r
-    c_soullight\r
-};\r
-\r
-RegEx* PChar::mCharnameRegexFilter = NULL;\r
-\r
-PChar::PChar()\r
-{\r
-  mID = 0;\r
-  mAccount = 0;\r
-  mGender = 0;\r
-  mClass = 0;\r
-  mProfession = 1;\r
-  mFaction = 1;\r
-  //mModel = 0;\r
-  //mType = 0;\r
-  mRealHead = 0;  // Base Skin elements, in complement of (computed) mType\r
-  mRealTorso = 0; // " Head shouldn't be changeable, except in case of surgery !!!\r
-  mRealLegs = 0;  // "\r
-  mSkin = 0;  // Current Skin elements\r
-  mHead = 0;  // "\r
-  mTorso = 0; // "\r
-  mLegs = 0;  // "\r
-  mHeadColor = mTorsoColor = mLegsColor = 0; // "\r
-  mHeadDarkness = mTorsoDarkness = mLegsDarkness = 0; // "\r
-\r
-  mBodyEffect = 0;\r
-  mBodyEffectDensity = 0;\r
-  mQuickBeltActiveSlot = INV_WORN_QB_NONE;\r
-\r
-  mLookingAt = 0;\r
-  mLookAtTimestamp = 0;\r
-  mLastUsedWorldObjectId = 0;\r
-\r
-  mSpeedOverride = 255; // means no override. Value 0 can be used to forbid any move.\r
-\r
-  mLocationLeased = false; // temp until char on-demand load/unload\r
-  mLocation = 0;\r
-  mStartApt = 0;\r
-  mPrimaryApt = 0;\r
-  mCash = 0;\r
-\r
-  mSeatInUseType = seat_none;\r
-  mSeatInUseObjectId = 0;\r
-  mSeatInUseSeatId = 0;\r
-  mVhcAccessRequestList = NULL;\r
-\r
-  mContainerInExclusiveUse = NULL;\r
-\r
-  mIsOnline = false;\r
-  mDirtyFlag = false;\r
-\r
-  mShunned = false;\r
-  mJailed = false;\r
-\r
-  mDialogNPC = 0;\r
-  mCurrentDialogNode = 0;\r
-\r
-  Skill = new PSkillHandler();\r
-  mBuddyList = NULL;\r
-  mGenrepList = NULL;\r
-\r
-  // Required for initial OOC Broadcast welcome message.\r
-  //Gets overwritten as soon as the first PingPacket arrives\r
-  mActiveChatChannels = 262144;\r
-  mClanLevel = 0;\r
-  mClanID = 0;\r
-}\r
-\r
-PChar::~PChar()\r
-{\r
-  // Addition; Set char's online status to OFFLINE\r
-  char sqlqry[50];\r
-  snprintf(sqlqry, 50, "UPDATE characters SET c_online = 0 WHERE c_id = %d", mID);\r
-  MySQL->GameQuery(sqlqry);\r
-\r
-  delete Skill;\r
-  delete mBuddyList;\r
-  delete mGenrepList;\r
-  delete mVhcAccessRequestList;\r
-\r
-  if ( mContainerInExclusiveUse )\r
-  {\r
-    mContainerInExclusiveUse->EndUse( mID );\r
-    Console->Print( RED, BLACK, "Warning: PChar::~PChar : Char still had exclusive use of container. Now freed." );\r
-  }\r
-\r
-  if ( mSeatInUseType != seat_none )\r
-  {\r
-    Console->Print( RED, BLACK, "Warning: PChar::~PChar : Char still using seat %d of vhc or chair %d.", mSeatInUseSeatId, mSeatInUseObjectId );\r
-  }\r
-}\r
-\r
-bool PChar::SetCharnameRegexFilter( const char* RegexStr )\r
-{\r
-  if ( mCharnameRegexFilter )\r
-  {\r
-    delete mCharnameRegexFilter;\r
-    mCharnameRegexFilter = NULL;\r
-  }\r
-\r
-  if ( RegexStr )\r
-  {\r
-    try\r
-    {\r
-      mCharnameRegexFilter = new RegEx( RegexStr, PCRE_CASELESS );\r
-    }\r
-    catch ( ... )\r
-    {\r
-      return false;\r
-    }\r
-  }\r
-  return true;\r
-}\r
-\r
-bool PChar::IsCharnameWellFormed( const char *Charname )\r
-{\r
-  if ( mCharnameRegexFilter )\r
-  {\r
-    return mCharnameRegexFilter->Search( Charname );\r
-  }\r
-  else\r
-    return true;\r
-}\r
-\r
-void PChar::SetProfession( uint32_t Profession )\r
-{\r
-  const PDefCharKind *def = GameDefs->CharKinds()->GetDef( Profession );\r
-  if ( def == NULL )\r
-  {\r
-    Console->Print( RED, BLACK, "Char %d: Invalid profession %d", mID, Profession );\r
-    mProfession = 10;\r
-    mClass = 0;\r
-  }\r
-  else\r
-  {\r
-    mProfession = Profession;\r
-    mClass = def->GetType();\r
-  }\r
-  SetDirtyFlag();\r
-}\r
-\r
-uint32_t PChar::GetSkinFromCharType( uint32_t nType )\r
-{\r
-  const PDefCharacter* nDefCharacter = GameDefs->Chars()->GetDef( nType );\r
-  if ( nDefCharacter )\r
-  {\r
-    return (( uint32_t )( nDefCharacter->GetModel() ) );\r
-  }\r
-  else\r
-    return 0;\r
-}\r
-\r
-inline uint32_t PChar::GetBaseModel()\r
-{\r
-  return GetSkinFromCharType( GetType() );\r
-}\r
-\r
-void PChar::SetRealLook( uint32_t nHead, uint32_t nTorso, uint32_t nLegs )\r
-{\r
-  mRealHead = nHead;\r
-  mRealTorso = nTorso;\r
-  mRealLegs = nLegs;\r
-  SetDirtyFlag();\r
-  ResetCurrentLook();\r
-}\r
-\r
-void PChar::GetRealLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs )\r
-{\r
-  nSkin = GetBaseModel();\r
-  nHead = mRealHead;\r
-  nTorso = mRealTorso;\r
-  nLegs = mRealLegs;\r
-}\r
-\r
-void PChar::SetCurrentLookFromCharType( uint32_t nType )\r
-{\r
-  int iHead, iTorso, iLegs;\r
-  uint32_t nSkin, nHead, nTorso, nLegs;\r
-  uint8_t nColor, nBrightness;\r
-\r
-  const PDefCharacter* nDefCharacter = GameDefs->Chars()->GetDef( nType );\r
-  if ( nDefCharacter )\r
-  {\r
-    nSkin = ( uint32_t ) nDefCharacter->GetModel();\r
-    iHead = nDefCharacter->GetHead();\r
-    iTorso = nDefCharacter->GetTorso();\r
-    iLegs = nDefCharacter->GetLegs();\r
-    nColor = ( uint8_t )( 0xff & nDefCharacter->GetColor() );\r
-    nBrightness = ( uint8_t )( 0xff & nDefCharacter->GetBrightness() );\r
-\r
-\r
-    if (( iHead < 0 ) || ( iTorso < 0 ) || ( iLegs < 0 ) )\r
-    {\r
-      nHead = nTorso = nLegs = 0;\r
-    }\r
-    else\r
-    {\r
-      nHead = iHead % 10;\r
-      nTorso = iTorso % 10;\r
-      nLegs = iLegs % 10;\r
-    }\r
-\r
-    SetCurrentLook( nSkin, nHead, nTorso, nLegs );\r
-    SetCurrentBodyColor( nColor, nColor, nColor, nBrightness, nBrightness, nBrightness );\r
-  }\r
-}\r
-\r
-void PChar::SetCurrentLook( uint32_t nSkin, uint32_t nHead, uint32_t nTorso, uint32_t nLegs )\r
-{\r
-  mSkin = nSkin;\r
-  mHead = nHead;\r
-  mTorso = nTorso;\r
-  mLegs = nLegs;\r
-  // Ingame skin update will be done automagically in the normal update flow\r
-  // A flag could also be set somewhere (preferably in Char si that we don't have to care if ingame or not)\r
-  //    to request quicker ingame update\r
-}\r
-\r
-void PChar::ResetCurrentLook()\r
-{\r
-  SetCurrentLook( GetSkinFromCharType( GetType() ), mRealHead, mRealTorso, mRealLegs );\r
-}\r
-\r
-// GetCurrentLook will later have to take Power Armors and GM overrides into account\r
-void PChar::GetCurrentLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs )\r
-{\r
-  nSkin = mSkin;\r
-  nHead = mHead;\r
-  nTorso = mTorso;\r
-  nLegs = mLegs;\r
-}\r
-\r
-void PChar::SetCurrentBodyColor( uint8_t nHeadColor, uint8_t nTorsoColor, uint8_t nLegsColor, uint8_t nHeadDarkness, uint8_t nTorsoDarkness, uint8_t nLegsDarkness )\r
-{\r
-  mHeadColor = nHeadColor;\r
-  mTorsoColor = nTorsoColor;\r
-  mLegsColor = nLegsColor;\r
-  mHeadDarkness = nHeadDarkness;\r
-  mTorsoDarkness = nTorsoDarkness;\r
-  mLegsDarkness = nLegsDarkness;\r
-}\r
-\r
-void PChar::GetCurrentBodyColor( uint8_t &nHeadColor, uint8_t &nTorsoColor, uint8_t &nLegsColor, uint8_t &nHeadDarkness, uint8_t &nTorsoDarkness, uint8_t &nLegsDarkness )\r
-{\r
-  nHeadColor = mHeadColor;\r
-  nTorsoColor = mTorsoColor;\r
-  nLegsColor = mLegsColor;\r
-  nHeadDarkness = mHeadDarkness;\r
-  nTorsoDarkness = mTorsoDarkness;\r
-  nLegsDarkness = mLegsDarkness;\r
-}\r
-\r
-void PChar::SetBaseSkills()\r
-{\r
-  const PDefCharKind *def = GameDefs->CharKinds()->GetDef( mProfession );\r
-  //Console->Print(YELLOW, BLACK, "PChar::SetBaseSkills() Profession: %d",def->GetIndex());\r
-  if ( def == NULL )\r
-  {\r
-    Console->Print( RED, BLACK, "PChar::SetBaseSkills: GetCharKindDef=NULL" );\r
-    return;\r
-  }\r
-  Skill->SetMainSkill( MS_INT, def->GetSkillInfo( MS_INT ).mStart );\r
-  Skill->SetMainSkill( MS_CON, def->GetSkillInfo( MS_CON ).mStart );\r
-  Skill->SetMainSkill( MS_DEX, def->GetSkillInfo( MS_DEX ).mStart );\r
-  Skill->SetMainSkill( MS_STR, def->GetSkillInfo( MS_STR ).mStart );\r
-  Skill->SetMainSkill( MS_PSI, def->GetSkillInfo( MS_PSI ).mStart );\r
-  // management of SP needed ? NC Client seem to calculate what remains ...\r
-  // or put SP setting after subskill setting ?\r
-  /* Skill->SetSP(MS_INT, (short) ??? ));\r
-  Skill->SetSP(MS_CON, ((short) ??? ));\r
-  Skill->SetSP(MS_DEX, (short) ??? ));\r
-  Skill->SetSP(MS_STR, (short) ??? ));\r
-  Skill->SetSP(MS_PSI, ((short) ??? )); */\r
-  // what about XPs ?\r
-  /* Skill->SetXP(MS_INT, ??? ));\r
-  Skill->SetXP(MS_CON, ??? ));\r
-  Skill->SetXP(MS_DEX, ??? ));\r
-  Skill->SetXP(MS_STR, ??? ));\r
-  Skill->SetXP(MS_PSI, ??? )); */\r
-  Console->Print( YELLOW, BLACK, "PChar::SetBaseSkills() not fully functionnal - unused skill points will be lost" );\r
-}\r
-\r
-void PChar::SetBaseSubskills( uint8_t NSZNb, const char* NonZeroSubskills )\r
-{\r
-  int i;\r
-\r
-  if ( NSZNb == 0 )\r
-    return;\r
-\r
-  for ( i = 0; i < NSZNb; i++ )\r
-  {\r
-    Skill->SetSubSkill(( SUB_SKILLS ) NonZeroSubskills[2 * i], ( int ) NonZeroSubskills[2 * i +1] );\r
-  }\r
-}\r
-\r
-void PChar::SetBaseInventory()\r
-{\r
-  uint8_t i;\r
-  uint32_t BaseItemID;\r
-  const PDefCharKind *def = GameDefs->CharKinds()->GetDef( mProfession );\r
-\r
-  //mCash = 5000;\r
-  mCash = def->GetStartMoney();\r
-\r
-  for ( i = 0; i < 8 ; i++ )\r
-  {\r
-    BaseItemID = def->GetStartInventory( i );\r
-    if ( BaseItemID )\r
-    {\r
-      if ( gDevDebug ) Console->Print( GREEN, BLACK, "Adding item %d to base inventory", BaseItemID );\r
-      PItem* NewItem = new PItem( BaseItemID );\r
-      if ( NewItem->GetItemID() )\r
-      {\r
-        NewItem->MakeItemStandard( 120, 180 ); // global quality range\r
-        mInventory.AddItem( NewItem );\r
-      }\r
-      else\r
-      {\r
-        Console->Print( RED, BLACK, "Invalid item ID %d in base inventory for profession %d", BaseItemID, mProfession );\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-void PChar::LoadClanLevel()\r
-{\r
-    MYSQL_RES *result;\r
-    char query[200];\r
-\r
-    snprintf(query, 200, "SELECT cll_level FROM clanlevels WHERE cll_charid = %d AND cll_clanid = %d", mID, mClanID);\r
-    result = MySQL->GameResQuery( query );\r
-    if ( result == NULL )\r
-    {\r
-        mClanID = 0;\r
-        Console->Print( RED, BLACK, "PChar::GetClanLevel could not load ClanLevel from the database" );\r
-        Console->Print( "Query was:" );\r
-        Console->Print( "%s", query );\r
-        MySQL->ShowGameSQLError();\r
-        return;\r
-    }\r
-    else if(mysql_num_rows(result) == 0)\r
-    {\r
-        mClanID = 0;\r
-        Console->Print( RED, BLACK, "PChar::GetClanLevel No level entry found for clan!" );\r
-        return;\r
-    }\r
-    mClanLevel = atoi(mysql_fetch_row(result)[0]);\r
-    if (gDevDebug) Console->Print("Loaded ClanLevel %d for char %d, clan %d", mClanLevel, mID, mClanID);\r
-}\r
-\r
-bool PChar::SQLLoad( int CharID )\r
-{\r
-  MYSQL_RES *result;\r
-  MYSQL_ROW row;\r
-  char query[1024];\r
-\r
-  snprintf( query, 1024, "SELECT * FROM characters WHERE c_id = %d LIMIT 1", CharID );\r
-  result = MySQL->GameResQuery( query );\r
-  if ( result == NULL )\r
-  {\r
-    Console->Print( RED, BLACK, "PChar::SQLLoad could not load Chardata from the database" );\r
-    Console->Print( "Query was:" );\r
-    Console->Print( "%s", query );\r
-    MySQL->ShowGameSQLError();\r
-    return false;\r
-  }\r
-  if (( row = mysql_fetch_row( result ) ) )\r
-  {\r
-    SetID( CharID );\r
-    SetName( row[c_name] );\r
-    SetAccount( atoi( row[a_id] ) );\r
-\r
-    // Gender\r
-    int genvalue = atoi( row[c_sex] );\r
-    if (( genvalue == 0 ) || ( genvalue == 1 ) )\r
-      mGender = static_cast<uint32_t>( genvalue );\r
-    else\r
-    {\r
-      Console->Print( RED, BLACK, "Bad gender value: %d (Char ID %d)", genvalue, mID );\r
-      mGender = 0;\r
-    }\r
-\r
-    // Profession\r
-    int profvalue = atoi( row[c_profession] );\r
-    SetProfession( static_cast<uint32_t>( profvalue ) );\r
-\r
-    // Class\r
-    //int classvalue = atoi(row[c_class]);\r
-    //if(classvalue < 4)\r
-    //    mClass = static_cast<uint32_t>(classvalue);\r
-    //else\r
-    //{\r
-    //  Console->Print(RED, BLACK, "Bad class value: %d (Char ID %d)", classvalue, mID);\r
-    //  classvalue = 0;\r
-    //}\r
-\r
-    // Faction\r
-    int facvalue = atoi( row[c_faction] );\r
-    if ( GameDefs->Factions()->GetDef( facvalue ) )\r
-      mFaction = static_cast<uint32_t>( facvalue );\r
-    else\r
-      mFaction = 1;\r
-\r
-    /* // Model\r
-    int modvalue = atoi(row[c_model]);\r
-    mModel = static_cast<uint32_t>(modvalue);\r
-    mModel = 10; */\r
-    int headvalue = atoi( row[c_head] );\r
-    int torsovalue = atoi( row[c_torso] );\r
-    int legsvalue = atoi( row[c_legs] );\r
-    SetRealLook( static_cast<uint32_t>( headvalue ), static_cast<uint32_t>( torsovalue ), static_cast<uint32_t>( legsvalue ) );\r
-\r
-    // Type\r
-    /*\r
-    int typevalue = std::atoi(row[c_type]);\r
-    mType = static_cast<uint32_t>(typevalue);\r
-    //mType = 1; */\r
-\r
-    // Location\r
-    int locvalue = atoi( row[c_location] );\r
-    mLocation = static_cast<uint32_t>( locvalue );\r
-\r
-//This assumption is not so good ... hardcoding jailed state linked with location ...\r
-    if ( mLocation == 550 || mLocation == 551 )\r
-      mJailed = true;\r
-\r
-    int posvalue = atoi( row[c_pos_x] );\r
-    Coords.mX = static_cast<uint16_t>( posvalue );\r
-    posvalue = atoi( row[c_pos_y] );\r
-    Coords.mY = static_cast<uint16_t>( posvalue );\r
-    posvalue = atoi( row[c_pos_z] );\r
-    Coords.mZ = static_cast<uint16_t>( posvalue );\r
-    posvalue = atoi( row[c_angle_ud] );\r
-    Coords.mUD = static_cast<uint8_t>( posvalue );\r
-    posvalue = atoi( row[c_angle_lr] );\r
-    Coords.mLR = static_cast<uint8_t>( posvalue );\r
-\r
-    int primapt = atoi( row[c_apt] );\r
-    mPrimaryApt = static_cast<uint32_t>( primapt );\r
-    mStartApt = mPrimaryApt;\r
-\r
-    mSoullight = atoi( row[c_soullight] );\r
-    mClanID = atoi( row[c_clan] );\r
-    if(mClanID > 0)\r
-        LoadClanLevel();\r
-\r
-    // Cash\r
-    float cashvalue = atof( row[c_cash] );\r
-    mCash = static_cast<uint32_t>( cashvalue );\r
-\r
-    // ---------------------------------------------\r
-    // Loading skills --- MAIN Skills with SP and XP\r
-    // ---------------------------------------------\r
-    Skill->SetMainSkill( MS_INT, atoi( row[c_int_lvl] ) );\r
-    Skill->SetMainSkill( MS_CON, atoi( row[c_con_lvl] ) );\r
-    Skill->SetMainSkill( MS_DEX, atoi( row[c_dex_lvl] ) );\r
-    Skill->SetMainSkill( MS_STR, atoi( row[c_str_lvl] ) );\r
-    Skill->SetMainSkill( MS_PSI, atoi( row[c_psi_lvl] ) );\r
-    // ---------------------------------------------\r
-    Skill->SetSP( MS_INT, ( short )atoi( row[c_int_pts] ) );\r
-    Skill->SetSP( MS_CON, ( short )atoi( row[c_con_pts] ) );\r
-    Skill->SetSP( MS_DEX, ( short )atoi( row[c_dex_pts] ) );\r
-    Skill->SetSP( MS_STR, ( short )atoi( row[c_str_pts] ) );\r
-    Skill->SetSP( MS_PSI, ( short )atoi( row[c_psi_pts] ) );\r
-    // ---------------------------------------------\r
-    Skill->SetXP( MS_INT, atof( row[c_int_xp] ) );\r
-    Skill->SetXP( MS_CON, atof( row[c_con_xp] ) );\r
-    Skill->SetXP( MS_DEX, atof( row[c_dex_xp] ) );\r
-    Skill->SetXP( MS_STR, atof( row[c_str_xp] ) );\r
-    Skill->SetXP( MS_PSI, atof( row[c_psi_xp] ) );\r
-    // ---------------------------------------------\r
-    // SubSkills\r
-    // ---------------------------------------------\r
-    Skill->SetSubSkill( SK_MC, atoi( row[c_mc] ) );\r
-    Skill->SetSubSkill( SK_HC, atoi( row[c_hc] ) );\r
-    Skill->SetSubSkill( SK_TRA, atoi( row[c_tra] ) );\r
-    Skill->SetSubSkill( SK_FOR, atoi( row[c_for] ) );\r
-    Skill->SetSubSkill( SK_PC, atoi( row[c_pc] ) );\r
-    Skill->SetSubSkill( SK_RC, atoi( row[c_rc] ) );\r
-    Skill->SetSubSkill( SK_TC, atoi( row[c_tc] ) );\r
-    Skill->SetSubSkill( SK_VHC, atoi( row[c_vhc] ) );\r
-    Skill->SetSubSkill( SK_AGL, atoi( row[c_agl] ) );\r
-    Skill->SetSubSkill( SK_REP, atoi( row[c_rep] ) );\r
-    Skill->SetSubSkill( SK_REC, atoi( row[c_rec] ) );\r
-    Skill->SetSubSkill( SK_RCL, atoi( row[c_rcl] ) );\r
-    Skill->SetSubSkill( SK_ATL, atoi( row[c_atl] ) );\r
-    Skill->SetSubSkill( SK_END, atoi( row[c_end] ) );\r
-    Skill->SetSubSkill( SK_FIR, atoi( row[c_fir] ) );\r
-    Skill->SetSubSkill( SK_ENR, atoi( row[c_enr] ) );\r
-    Skill->SetSubSkill( SK_XRR, atoi( row[c_xrr] ) );\r
-    Skill->SetSubSkill( SK_POR, atoi( row[c_por] ) );\r
-    Skill->SetSubSkill( SK_HLT, atoi( row[c_hlt] ) );\r
-    Skill->SetSubSkill( SK_HCK, atoi( row[c_hck] ) );\r
-    Skill->SetSubSkill( SK_BRT, atoi( row[c_brt] ) );\r
-    Skill->SetSubSkill( SK_PSU, atoi( row[c_psu] ) );\r
-    Skill->SetSubSkill( SK_WEP, atoi( row[c_wep] ) );\r
-    Skill->SetSubSkill( SK_CST, atoi( row[c_cst] ) );\r
-    Skill->SetSubSkill( SK_RES, atoi( row[c_res] ) );\r
-    Skill->SetSubSkill( SK_IMP, atoi( row[c_imp] ) );\r
-    Skill->SetSubSkill( SK_PPU, atoi( row[c_ppu] ) );\r
-    Skill->SetSubSkill( SK_APU, atoi( row[c_apu] ) );\r
-    Skill->SetSubSkill( SK_MST, atoi( row[c_mst] ) );\r
-    Skill->SetSubSkill( SK_PPW, atoi( row[c_ppw] ) );\r
-    Skill->SetSubSkill( SK_PSR, atoi( row[c_psr] ) );\r
-    Skill->SetSubSkill( SK_WPW, atoi( row[c_wpw] ) );\r
-    // --------------------------------------------\r
-    // Inventory\r
-    // ---------------------------------------------\r
-    mInventory.SetCharId( mID );\r
-    mInventory.SQLLoad();\r
-\r
-    // temp value forcing, not get/saved from DB atm\r
-    mCombatRank = ( uint8_t )( random() % 127 ); // bad result there on randomness\r
-    mSynaptic = 0;\r
-    mIsDead = false;\r
-\r
-    mDirectCharID = 0; // until saved/loaded with char\r
-    mBuddyList = new PBuddyList( mID );\r
-    if ( !mBuddyList->SQLLoad() )\r
-    {\r
-      Console->Print( RED, BLACK, "Char ID %d : Can't load buddy list", mID );\r
-    }\r
-    //to add: Chats settings\r
-\r
-    mGenrepList = new PGenrepList( mID );\r
-    if ( !mGenrepList->SQLLoad() )\r
-    {\r
-      Console->Print( RED, BLACK, "Char ID %d : Can't load genrep list", mID );\r
-    }\r
-\r
-  }\r
-  MySQL->FreeGameSQLResult( result );\r
-\r
-  // Addition; Set char's online status to ONLINE\r
-  char sqlqry[50];\r
-  snprintf(sqlqry, 50, "UPDATE characters SET c_online = 1 WHERE c_id = %d", mID);\r
-  MySQL->GameQuery(sqlqry);\r
-\r
-  return true;\r
-}\r
-\r
-bool PChar::SQLCreate() // Specific method for creation in order to avoid existence check with each save\r
-{\r
-  std::string query, queryv;\r
-\r
-  query = "INSERT INTO characters (c_id";\r
-  queryv = ") VALUES (NULL";\r
-\r
-  query += ",c_name";\r
-  queryv = queryv + ",'" + mName + "'";\r
-\r
-  query += ",a_id";\r
-  queryv += Ssprintf( ",'%u'", mAccount );\r
-  query += ",c_class";\r
-  queryv += Ssprintf( ",'%u'", mClass );\r
-  query += ",c_sex";\r
-  queryv += Ssprintf( ",'%u'", mGender );\r
-  query += ",c_profession";\r
-  queryv += Ssprintf( ",'%u'", mProfession );\r
-  query += ",c_faction";\r
-  queryv += Ssprintf( ",'%u'", mFaction );\r
-  query += ",c_head";\r
-  queryv += Ssprintf( ",'%u'", mRealHead );\r
-  query += ",c_torso";\r
-  queryv += Ssprintf( ",'%u'", mRealTorso );\r
-  query += ",c_legs";\r
-  queryv += Ssprintf( ",'%u'", mRealLegs );\r
-  //query += ",c_model";\r
-  //queryv += Ssprintf(",'%u'", mModel);\r
-  //query += ",c_type";\r
-  //queryv += Ssprintf(",'%u'", mType);\r
-  query += ",c_location";\r
-  queryv += Ssprintf( ",'%u'", mLocation );\r
-  query += ",c_cash";\r
-  queryv += Ssprintf( ",'%u'", mCash );\r
-  query += ",c_slot";\r
-  queryv += Ssprintf( ",'%u'", mSlot );\r
-\r
-  query = query + queryv + ");";\r
-\r
-  if ( MySQL->GameQuery( query.c_str() ) )\r
-  {\r
-    Console->Print( RED, BLACK, "PChar::SQLCreate could not add char %s to database", mName.c_str() );\r
-    Console->Print( "Query was:" );\r
-    Console->Print( "%s", query.c_str() );\r
-    MySQL->ShowGameSQLError();\r
-    return false;\r
-  }\r
-  else\r
-  {\r
-    mID = MySQL->GetLastGameInsertId();\r
-//Console->Print(GREEN, BLACK, "New char %s got ID %d", mName.c_str(), mID);\r
-    mDirtyFlag = true;\r
-    return true;\r
-  }\r
-}\r
-\r
-bool PChar::CreateNewChar( uint32_t Account, const std::string &Name, uint32_t Gender, uint32_t Profession, uint32_t Faction,\r
-                           uint32_t Head, uint32_t Torso, uint32_t Legs, uint8_t NZSNb, const char *NonZeroSubskills, uint32_t Slot )\r
-{\r
-  SetName( Name );\r
-  SetGender( Gender );\r
-  SetProfession( Profession );\r
-  SetFaction( Faction );\r
-  SetRealLook( Head, Torso, Legs );\r
-  SetBaseSkills();\r
-  SetBaseSubskills( NZSNb, NonZeroSubskills );\r
-  SetBaseInventory();\r
-  SetAccount( Account );\r
-  SetCharSlot( Slot );\r
-  mLocation = Config->GetOptionInt( "new_char_location" );\r
-\r
-  // This part will have to be rewritten with proper methods\r
-  mSoullight = 10;\r
-  mCombatRank = ( uint8_t )( random() % 80 ); // bad result there on randomness\r
-  mSynaptic = 0;\r
-  mIsDead = false;\r
-\r
-  mDirectCharID = 0; // until saved/loaded with char\r
-\r
-  SetDirtyFlag();\r
-\r
-  if ( SQLCreate() ) // mID isn't defined before that\r
-  {\r
-    mBuddyList = new PBuddyList( mID );\r
-    mGenrepList = new PGenrepList( mID );\r
-    mStartApt = mPrimaryApt = Appartements->CreateBaseAppartement( mID, mName, mFaction );\r
-    mInventory.SetCharId( mID );\r
-\r
-    if ( mStartApt && SQLSave() && mInventory.SQLSave() )\r
-    {\r
-      return true;\r
-    }\r
-    else\r
-    {\r
-      Console->Print( YELLOW, BLACK, "New char %s (id %d) : creation aborted", mName.c_str(), mID );\r
-      if ( mID )\r
-      {\r
-        SQLDelete();\r
-        if ( mStartApt )\r
-        {\r
-          Appartements->DeleteCharAppartements( mID );\r
-        }\r
-      }\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-bool PChar::SQLSave()\r
-{\r
-  std::string query;\r
-  //std::string ts;\r
-\r
-  /* TODO:\r
-    - Mostly at creation/load :\r
-              c_apt, (or when first GR to primary apt to avoid creation of unused apt?)\r
-              (c_slot)\r
-    - At save/load :\r
-              SoulLight ???\r
-              FactionSymp[] ???\r
-              Chest change: style, brightness, color\r
-              Legs change: style, brightness, color\r
-              mHealt, mStamina, mMana (not in DB !!!)\r
-              How to compute MaxHealth etc. ?\r
-  */\r
-  query = "UPDATE characters SET";\r
-\r
-  query += Ssprintf( " c_location='%u'", mLocation );\r
-  query += Ssprintf( ",c_pos_x='%u'", Coords.mX );\r
-  query += Ssprintf( ",c_pos_y='%u'", Coords.mY );\r
-  query += Ssprintf( ",c_pos_z='%u'", Coords.mZ );\r
-  query += Ssprintf( ",c_angle_ud='%u'", Coords.mUD );\r
-  query += Ssprintf( ",c_angle_lr='%u'", Coords.mLR );\r
-  query += Ssprintf( ",c_cash='%u'", mCash );\r
-  query += Ssprintf( ",c_apt='%u'", mPrimaryApt );\r
-\r
-  query += Ssprintf( ",c_head='%u'", mRealHead );\r
-  query += Ssprintf( ",c_torso='%u'", mRealTorso );\r
-  query += Ssprintf( ",c_legs='%u'", mRealLegs );\r
-\r
-  query += Ssprintf( ",c_faction='%u'", mFaction );\r
-\r
-  /* This group of fiels shouldn't change in-game\r
-  query = query + ",c_name='" + mName + "'";\r
-  query += Ssprintf(",a_id='%u'", mAccount);\r
-  query += Ssprintf(",c_class='%u'", mClass);\r
-  query += Ssprintf(",c_sex='%u'", mGender);\r
-  query += Ssprintf(",c_profession='%u'", mProfession);\r
-  query += Ssprintf(",c_slot='%u'", mSlot);\r
-  // query += Ssprintf(",c_model='%u'", mModel);\r
-  // query += Ssprintf(",c_type='%u'", mType);\r
-  */\r
-\r
-  // ---------------------------------------------\r
-  // Saving skills --- MAIN Skills with SP and XP\r
-  // ---------------------------------------------\r
-  query += Ssprintf( ",c_int_lvl='%u'", Skill->GetMainSkill( MS_INT ) );\r
-  query += Ssprintf( ",c_con_lvl='%u'", Skill->GetMainSkill( MS_CON ) );\r
-  query += Ssprintf( ",c_dex_lvl='%u'", Skill->GetMainSkill( MS_DEX ) );\r
-  query += Ssprintf( ",c_str_lvl='%u'", Skill->GetMainSkill( MS_STR ) );\r
-  query += Ssprintf( ",c_psi_lvl='%u'", Skill->GetMainSkill( MS_PSI ) );\r
-  // ---------------------------------------------\r
-  query += Ssprintf( ",c_int_pts='%u'", Skill->GetSP( MS_INT ) );\r
-  query += Ssprintf( ",c_con_pts='%u'", Skill->GetSP( MS_CON ) );\r
-  query += Ssprintf( ",c_dex_pts='%u'", Skill->GetSP( MS_DEX ) );\r
-  query += Ssprintf( ",c_str_pts='%u'", Skill->GetSP( MS_STR ) );\r
-  query += Ssprintf( ",c_psi_pts='%u'", Skill->GetSP( MS_PSI ) );\r
-  // ---------------------------------------------\r
-  query += Ssprintf( ",c_int_xp='%u'", Skill->GetXP( MS_INT ) );\r
-  query += Ssprintf( ",c_con_xp='%u'", Skill->GetXP( MS_CON ) );\r
-  query += Ssprintf( ",c_dex_xp='%u'", Skill->GetXP( MS_DEX ) );\r
-  query += Ssprintf( ",c_str_xp='%u'", Skill->GetXP( MS_STR ) );\r
-  query += Ssprintf( ",c_psi_xp='%u'", Skill->GetXP( MS_PSI ) );\r
-  // ---------------------------------------------\r
-  // SubSkills\r
-  // ---------------------------------------------\r
-  query += Ssprintf( ",c_mc='%u'", Skill->GetSubSkill( SK_MC ) );\r
-  query += Ssprintf( ",c_hc='%u'", Skill->GetSubSkill( SK_HC ) );\r
-  query += Ssprintf( ",c_tra='%u'", Skill->GetSubSkill( SK_TRA ) );\r
-  query += Ssprintf( ",c_for='%u'", Skill->GetSubSkill( SK_FOR ) );\r
-  query += Ssprintf( ",c_pc='%u'", Skill->GetSubSkill( SK_PC ) );\r
-  query += Ssprintf( ",c_rc='%u'", Skill->GetSubSkill( SK_RC ) );\r
-  query += Ssprintf( ",c_tc='%u'", Skill->GetSubSkill( SK_TC ) );\r
-  query += Ssprintf( ",c_vhc='%u'", Skill->GetSubSkill( SK_VHC ) );\r
-  query += Ssprintf( ",c_agl='%u'", Skill->GetSubSkill( SK_AGL ) );\r
-  query += Ssprintf( ",c_rep='%u'", Skill->GetSubSkill( SK_REP ) );\r
-  query += Ssprintf( ",c_rec='%u'", Skill->GetSubSkill( SK_REC ) );\r
-  query += Ssprintf( ",c_rcl='%u'", Skill->GetSubSkill( SK_RCL ) );\r
-  query += Ssprintf( ",c_atl='%u'", Skill->GetSubSkill( SK_ATL ) );\r
-  query += Ssprintf( ",c_end='%u'", Skill->GetSubSkill( SK_END ) );\r
-  query += Ssprintf( ",c_fir='%u'", Skill->GetSubSkill( SK_FIR ) );\r
-  query += Ssprintf( ",c_enr='%u'", Skill->GetSubSkill( SK_ENR ) );\r
-  query += Ssprintf( ",c_xrr='%u'", Skill->GetSubSkill( SK_XRR ) );\r
-  query += Ssprintf( ",c_por='%u'", Skill->GetSubSkill( SK_POR ) );\r
-  query += Ssprintf( ",c_htl='%u'", Skill->GetSubSkill( SK_HLT ) );\r
-  query += Ssprintf( ",c_hck='%u'", Skill->GetSubSkill( SK_HCK ) );\r
-  query += Ssprintf( ",c_brt='%u'", Skill->GetSubSkill( SK_BRT ) );\r
-  query += Ssprintf( ",c_psu='%u'", Skill->GetSubSkill( SK_PSU ) );\r
-  query += Ssprintf( ",c_wep='%u'", Skill->GetSubSkill( SK_WEP ) );\r
-  query += Ssprintf( ",c_cst='%u'", Skill->GetSubSkill( SK_CST ) );\r
-  query += Ssprintf( ",c_res='%u'", Skill->GetSubSkill( SK_RES ) );\r
-  query += Ssprintf( ",c_imp='%u'", Skill->GetSubSkill( SK_IMP ) );\r
-  query += Ssprintf( ",c_ppu='%u'", Skill->GetSubSkill( SK_PPU ) );\r
-  query += Ssprintf( ",c_apu='%u'", Skill->GetSubSkill( SK_APU ) );\r
-  query += Ssprintf( ",c_mst='%u'", Skill->GetSubSkill( SK_MST ) );\r
-  query += Ssprintf( ",c_ppw='%u'", Skill->GetSubSkill( SK_PPW ) );\r
-  query += Ssprintf( ",c_psr='%u'", Skill->GetSubSkill( SK_PSR ) );\r
-  query += Ssprintf( ",c_wpw='%u'", Skill->GetSubSkill( SK_WPW ) );\r
-  // ---------------------------------------------\r
-\r
-  query += Ssprintf( " WHERE c_id='%u' LIMIT 1;", mID );\r
-\r
-  if ( MySQL->GameQuery( query.c_str() ) )\r
-  {\r
-    Console->Print( RED, BLACK, "PChar::SQLSave could not save char %s (%u) to database", mName.c_str(), mID );\r
-    Console->Print( "Query was:" );\r
-    Console->Print( "%s", query.c_str() );\r
-    MySQL->ShowGameSQLError();\r
-    return false;\r
-  }\r
-\r
-  // Chats settings (?), directs\r
-\r
-  mDirtyFlag = false;\r
-  return true;\r
-}\r
-\r
-bool PChar::SQLDelete()\r
-{\r
-  return true;\r
-}\r
-\r
-void PChar::SetOnlineStatus( bool IsOnline )\r
-{\r
-  // Deactivated, until Maxx added c_isonline row to `characters`\r
-  //char query[255];\r
-  int onlinestatus = 0;\r
-\r
-  if ( IsOnline )\r
-  {\r
-    onlinestatus = 0; // Strange ????\r
-    mIsOnline = true;\r
-  }\r
-  else\r
-  {\r
-    onlinestatus = 1; // Strange ????\r
-    mIsOnline = false;\r
-  }\r
-\r
-//    snprintf(query, 255, "UPDATE charlist SET c_isonline = %d WHERE a_id = %d AND c_id = %d", onlinestatus, mAccount, mID);\r
-//    if(MySQL->Query(query))\r
-//    {\r
-//        Console->Print("Error: Cant set onlinestatus to '%d' for Account: %d, Char: %d", onlinestatus, mAccount, mID);\r
-//        MySQL->ShowSQLError();\r
-//        return;\r
-//    }\r
-  return;\r
-}\r
-\r
-uint8_t PChar::GetCombatRank()\r
-{\r
-    // Override for Special Account Levels\r
-    PAccount Acc(mAccount);\r
-    if(Acc.GetLevel() == PAL_ADMIN)\r
-        return 127;\r
-    else if(Acc.GetLevel() >= PAL_GM)\r
-        return 120;\r
-    else if(Acc.GetLevel() >= PAL_VOLUNTEER)\r
-        return 50;\r
-    else\r
-        return mCombatRank;\r
-}\r
-\r
-\r
-uint8_t PChar::GetMainRank()\r
-{\r
-    // Override for Special Account Levels\r
-    PAccount Acc(mAccount);\r
-    if(Acc.GetLevel() == PAL_ADMIN)\r
-        return 127;\r
-    else if(Acc.GetLevel() >= PAL_GM)\r
-        return 120;\r
-    else if(Acc.GetLevel() >= PAL_VOLUNTEER)\r
-        return 50;\r
-    else\r
-    {\r
-      uint16_t total;\r
-      total  = Skill->GetMainSkill( MS_STR ) + Skill->GetMainSkill( MS_DEX );\r
-      total += Skill->GetMainSkill( MS_CON ) + Skill->GetMainSkill( MS_INT );\r
-      total += Skill->GetMainSkill( MS_PSI );\r
-      return (( uint8_t )( total / 5 ) );\r
-    }\r
-}\r
-\r
-bool PChar::AddGenrep(uint16_t nWorldID, uint16_t nStationID)\r
-{\r
-    return mGenrepList->AddGenrep(nWorldID, nStationID );\r
-}\r
-\r
-uint16_t PChar::GetGenrepListDataSize()\r
-{\r
-    return mGenrepList->GetListDataSize();\r
-}\r
-\r
-const void *PChar::GetGenrepListData()\r
-{\r
-    return mGenrepList->GetListData();\r
-}\r
-\r
-uint8_t PChar::GetGenrepCount()\r
-{\r
-    return mGenrepList->Count();\r
-}\r
-\r
-uint32_t PChar::AddCash( uint32_t nAmount )\r
-{\r
-    return SetCash(nAmount + mCash);\r
-}\r
-\r
-uint32_t PChar::TakeCash( uint32_t nAmount )\r
-{\r
-    if(nAmount > mCash)\r
-    {\r
-        //Tries to take away more cash that user has, set to zero\r
-        return SetCash(0);\r
-    }\r
-    else\r
-    {\r
-        return SetCash(mCash-nAmount);\r
-    }\r
-}\r
-\r
-uint32_t PChar::SetCash( uint32_t nCash )\r
-{\r
-  //Console->Print("Trying to set cash to nCash: %d", nCash);\r
-  if (( int )nCash > Config->GetOptionInt( "max_cash" ) )\r
-  {\r
-    //Console->Print("Newcash would be more than dynamic maxcash, setting to maxcash");\r
-    mCash = ( uint32_t )Config->GetOptionInt( "max_cash" );\r
-  }\r
-  else if ( nCash > MAXCASH )\r
-  {\r
-    //Console->Print("Newcash would be more than hardcoded maxcash, setting to maxcash");\r
-    mCash = MAXCASH;\r
-  }\r
-  else\r
-  {\r
-    //Console->Print("Allright, setting to new value");\r
-    mCash = nCash;\r
-  }\r
-  //Console->Print("Returning mCash: %d", mCash);\r
-  return mCash;\r
-}\r
-\r
-\r
-bool PChar::SetQuickBeltActiveSlot( uint8_t nSlotID )\r
-{\r
-  if (( nSlotID == INV_WORN_QB_HAND ) || ( nSlotID == INV_WORN_QB_NONE ) )\r
-  {\r
-    mQuickBeltActiveSlot = nSlotID;\r
-    return true;\r
-  }\r
-  else if ( nSlotID <= ( INV_WORN_QB_END - INV_WORN_QB_START ) )\r
-  {\r
-    PContainer* tWorn = mInventory.GetContainer( INV_LOC_WORN );\r
-\r
-    if ( ! tWorn->IsSlotFree( nSlotID ) ) // => TODO: MUST ALSO CHECK that item is currently usable and can be held in hand\r
-    {\r
-      mQuickBeltActiveSlot = nSlotID;\r
-      return true;\r
-    }\r
-    else\r
-    {\r
-      Console->Print( "SetQuickBeltActiveSlot: SlotID %d greater than %d or free (%d)", nSlotID, INV_WORN_QB_END - INV_WORN_QB_START, tWorn->IsSlotFree( nSlotID ) );\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-PSeatType PChar::GetSeatInUse( uint32_t* nObjectId, uint8_t* nSeatId )\r
-{\r
-  if ( nObjectId )\r
-  {\r
-    *nObjectId = mSeatInUseObjectId;\r
-  }\r
-  if ( nSeatId )\r
-  {\r
-    *nSeatId = mSeatInUseSeatId;\r
-  }\r
-\r
-  return mSeatInUseType;\r
-}\r
-\r
-void PChar::SetSeatInUse( PSeatType nSeatType, uint32_t nObjectId, uint8_t nSeatId )\r
-{\r
-  mSeatInUseType = nSeatType;\r
-  mSeatInUseObjectId = nObjectId;\r
-  mSeatInUseSeatId = nSeatId;\r
-}\r
-\r
-PVhcAccessRequestList* PChar::GetVhcAccessRequestList()\r
-{\r
-  if( ! mVhcAccessRequestList )\r
-    mVhcAccessRequestList = new PVhcAccessRequestList();\r
-\r
-  return mVhcAccessRequestList;\r
-}\r
-\r
-void PChar::SetLookingAt( uint16_t nLocalCharID )\r
-{\r
-  mLookingAt = nLocalCharID;\r
-  mLookAtTimestamp = std::time( NULL );\r
-}\r
-\r
-uint16_t PChar::GetLookingAt( uint16_t nMaxDelaySec )\r
-{\r
-  return ((( mLookAtTimestamp + nMaxDelaySec ) >= std::time( NULL ) ) ? mLookingAt : 0 );\r
-}\r
-\r
-// ===================================\r
-\r
-PChars::PChars()\r
-{\r
-  mLastID = 0;\r
-  mLastSave = std::time( NULL );\r
-\r
-  mAutoSavePeriod = Config->GetOptionInt( "auto_save_period" );\r
-  if ( mAutoSavePeriod < 0 )\r
-  {\r
-    Console->Print( "%s auto_save_period (%d) must be strict positive.", Console->ColorText( RED, BLACK, "[Error]" ), mAutoSavePeriod );\r
-    mAutoSavePeriod = 0;\r
-  }\r
-  else if ( mAutoSavePeriod > 3600 )\r
-  {\r
-    Console->Print( "%s auto_save_period (%d) too high. Forced to 3600 sec.", Console->ColorText( YELLOW, BLACK, "[Warning]" ), mAutoSavePeriod );\r
-    mAutoSavePeriod = 0;\r
-  }\r
-\r
-  if ( mAutoSavePeriod == 0 )\r
-  {\r
-    Console->Print( "%s Auto-save disabled.", Console->ColorText( YELLOW, BLACK, "[Info]" ) );\r
-  }\r
-  else if ( mAutoSavePeriod < 60 )\r
-  {\r
-    Console->Print( "%s auto_save_period (%d) is low and might lead to high server load.", Console->ColorText( YELLOW, BLACK, "[Warning]" ), mAutoSavePeriod );\r
-  }\r
-\r
-}\r
-\r
-PChars::~PChars()\r
-{\r
-  for ( CharMap::iterator i = mChars.begin(); i != mChars.end(); i++ )\r
-    delete i->second;\r
-}\r
-\r
-bool PChars::LoadChar( uint32_t CharID )\r
-{\r
-  if ( !CharID )\r
-    return false;\r
-\r
-  PChar *nChar = new PChar();\r
-  if ( nChar->SQLLoad( CharID ) )\r
-  {\r
-    nChar->SetDirtyFlag( false );\r
-    return AddChar( nChar );\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Could not load char id %d from database", CharID );\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PChars::AddChar( PChar* nChar )\r
-{\r
-  if ( !nChar )\r
-    return false;\r
-\r
-  mLastID = std::max( mLastID, nChar->GetID() );\r
-  if ( mChars.insert( std::make_pair( nChar->GetID(), nChar ) ).second )\r
-  {\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Char: %s (id %d) added", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nChar->GetName().c_str() , nChar->GetID() );\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Trying to load char twice : %s (id %d)", nChar->GetName().c_str(), nChar->GetID() );\r
-    return false;\r
-  }\r
-}\r
-\r
-PChar* PChars::RemoveChar( uint32_t CharID )\r
-{\r
-  PChar* Result = NULL;\r
-\r
-  CharMap::iterator i = mChars.find( CharID );\r
-  if ( i != mChars.end() )\r
-  {\r
-    Result = i->second;\r
-    mChars.erase( i );\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Char: %s (id %d) removed", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), Result->GetName().c_str() , Result->GetID() );\r
-  }\r
-\r
-  return Result;\r
-}\r
-\r
-void PChars::SQLSave()\r
-{\r
-  // saves all dirty-flagged chars\r
-  int nDirtyChars = 0, nSavedChars = 0;\r
-  int nDirtyInv = 0, nSavedInv = 0;\r
-\r
-  for ( CharMap::const_iterator i = mChars.begin(); i != mChars.end(); i++ )\r
-  {\r
-    PChar* Char = i->second;\r
-    if ( Char->IsDirty() )\r
-    {\r
-      ++nDirtyChars;\r
-      if ( Char->SQLSave() )\r
-        ++nSavedChars;\r
-    }\r
-    if ( Char->GetInventory()->IsDirty() )\r
-    {\r
-      ++nDirtyInv;\r
-      if ( Char->GetInventory()->SQLSave() )\r
-        ++nSavedInv;\r
-    }\r
-  }\r
-  Console->Print( "%s %i chars saved on %i dirty, %i inventories saved on %i dirty", Console->ColorText( GREEN, BLACK, "[DEBUG]" ), nSavedChars, nDirtyChars, nSavedInv, nDirtyInv );\r
-  return;\r
-}\r
-\r
-PChar* PChars::GetChar( uint32_t CharID ) const\r
-{\r
-  PChar *Result = 0;\r
-  CharMap::const_iterator i = mChars.find( CharID );\r
-  if ( i != mChars.end() )\r
-    Result = i->second;\r
-\r
-  return Result;\r
-}\r
-\r
-PChar* PChars::GetChar( const std::string &Name ) const\r
-{\r
-  PChar *Result = 0;\r
-  for ( CharMap::const_iterator i = mChars.begin(); i != mChars.end(); i++ )\r
-  {\r
-    if ( !/*std::*/strcasecmp( i->second->GetName().c_str(), Name.c_str() ) )\r
-    {\r
-      Result = i->second;\r
-      break;\r
-    }\r
-  }\r
-  return Result;\r
-}\r
-\r
-bool PChars::CharExist( const std::string &Name ) const\r
-{\r
-  char query[256];\r
-  int EntriesNb;\r
-  MYSQL_RES *result = 0;\r
-\r
-  char escUsername[256];\r
-  MySQL->EscapeString( Name.c_str(), escUsername, 256 );\r
-  snprintf( query, 256, "SELECT 1 FROM characters WHERE c_name = '%s' LIMIT 1;", escUsername );\r
-\r
-  result = MySQL->GameResQuery( query );\r
-  if ( result == NULL )\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Failed to get CharacterData from SQL" );\r
-    MySQL->ShowGameSQLError();\r
-    return true;\r
-  }\r
-\r
-  EntriesNb = mysql_num_rows( result );\r
-  MySQL->FreeGameSQLResult( result );\r
-  return( EntriesNb > 0 );\r
-}\r
-\r
-void PChars::Update()\r
-{\r
-  std::time_t t = std::time( NULL ); // changed to time() to have real time instead of cpu used time\r
-\r
-  if ( mAutoSavePeriod && (( t - mLastSave ) >= mAutoSavePeriod ) )\r
-  {\r
-    bool NeedSave = false;\r
-    for ( CharMap::const_iterator i = mChars.begin(); i != mChars.end(); i++ )\r
-    {\r
-      if ( i->second->IsAnyDirty() )\r
-      {\r
-        NeedSave = true;\r
-        break;\r
-      }\r
-    }\r
-\r
-    if ( NeedSave )\r
-    {\r
-      if ( gDevDebug ) Console->Print( "%s Some characters need autosaving...", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-      SQLSave();\r
-      if ( gDevDebug ) Console->Print( "%s Autosave done.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    }\r
-    mLastSave = t;\r
-  }\r
-}\r
-\r
-//MAX_CHARS_PER_ACCOUNT\r
-int PChars::GetCharProfiles( const uint32_t AccountID, PCharProfile* CharSlotsArray, const uint8_t ArraySize )\r
-{\r
-  char query[256];\r
-  int EntriesNb = 0;\r
-\r
-  MYSQL_ROW row = 0;\r
-  MYSQL_RES *result = 0;\r
-\r
-  snprintf( query, 256, "SELECT * FROM characters WHERE a_id = %d ORDER BY c_slot ASC", AccountID );\r
-\r
-  result = MySQL->GameResQuery( query );\r
-  if ( result == NULL )\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Failed to load CharacterData from SQL" );\r
-    MySQL->ShowGameSQLError();\r
-    return 0;\r
-  }\r
-\r
-  //EntriesNb = mysql_num_rows(result);\r
-  int SlotID;\r
-  uint32_t CharID;\r
-  PChar* tmpChar = new PChar();\r
-\r
-  while (( row = mysql_fetch_row( result ) ) )\r
-  {\r
-    SlotID = atoi( row[c_slot] );\r
-    CharID = atoi( row[c_id] );\r
-    if (( SlotID >= 0 ) && ( SlotID < ArraySize ) )\r
-    {\r
-      if ( !CharSlotsArray[SlotID].in_use )\r
-      {\r
-        tmpChar->SetID( CharID );\r
-        tmpChar->SetGender( atoi( row[c_sex] ) );\r
-        tmpChar->SetProfession( atoi( row[c_profession] ) );\r
-\r
-        CharSlotsArray[SlotID].CharID = CharID;\r
-        CharSlotsArray[SlotID].Type = tmpChar->GetType();\r
-        CharSlotsArray[SlotID].Location = static_cast<uint32_t>( atoi( row[c_location] ) );\r
-        CharSlotsArray[SlotID].Head = atoi( row[c_head] );\r
-        CharSlotsArray[SlotID].Torso = atoi( row[c_torso] );\r
-        CharSlotsArray[SlotID].Legs = atoi( row[c_legs] );\r
-        CharSlotsArray[SlotID].Name = row[c_name];\r
-        CharSlotsArray[SlotID].NameLen = CharSlotsArray[SlotID].Name.length() + 1;\r
-\r
-        CharSlotsArray[SlotID].in_use = true;\r
-        ++EntriesNb;\r
-      }\r
-      else\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Warning]Character %d using slot %d already used by char %d - Ignored", \\r
-                        CharID, SlotID, CharSlotsArray[SlotID].CharID );\r
-      }\r
-    }\r
-    else\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Warning]Character %d using invialid slot %d - Ignored", CharID, SlotID );\r
-    }\r
-  }\r
-\r
-  delete tmpChar;\r
-  MySQL->FreeGameSQLResult( result );\r
-  return EntriesNb;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// PCharCoordinates
+void PCharCoordinates::SetInterpolate( PCharCoordinates& Pos1, PCharCoordinates& Pos2, float nCoef )
+{
+  if (( nCoef < 0 ) || ( nCoef > 1 ) )
+  {
+    Console->Print( RED, BLACK, "[Error] PCharCoordinates::Interpolate : Invalid nCoef value: %f", nCoef );
+    nCoef = 0;
+  }
+  float rCoef = 1 - nCoef;
+
+  mY = ( uint16_t )( rCoef * Pos1.mY + nCoef * Pos2.mY );
+  mZ = ( uint16_t )( rCoef * Pos1.mZ + nCoef * Pos2.mZ );
+  mX = ( uint16_t )( rCoef * Pos1.mX + nCoef * Pos2.mX );
+  mUD = ( uint8_t )( rCoef * Pos1.mUD + nCoef * Pos2.mUD );
+  if ( abs( Pos1.mLR - Pos2.mLR ) < 90 )
+  {
+    mLR = ( uint8_t )( rCoef * Pos1.mLR + nCoef * Pos2.mLR );
+  }
+  else
+  {
+    mLR = ( uint8_t )(( uint16_t )( rCoef * ( 180.0 + ( float )Pos1.mLR ) + nCoef * Pos2.mLR ) % 180 );
+  }
+}
+
+uint16_t mY;     // Y-Position in world
+uint16_t mZ;     // Z-Position in world
+uint16_t mX;     // X-Position in world
+uint8_t mUD;     // Up - Mid - Down (d6 - 80 - 2a)
+uint8_t mLR;     // Compass direction (S..E..N..W..S [0-45-90-135-179])
+uint8_t mAct;    // Last user action state
+
+void PCharCoordinates::SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD, uint8_t nLR )
+{
+  mY = nY;
+  mZ = nZ;
+  mX = nX;
+  mUD = nUD;
+  if ( mUD < 0x2a )
+  {
+    mUD = 0x2a;
+  }
+  else if ( mUD > 0xd6 )
+  {
+    mUD = 0xd6;
+  }
+  mLR = nLR % 180;
+}
+
+
+// SQL Layout
+enum
+{
+    c_id,
+    c_name,
+    c_str_lvl,
+    c_str_pts,
+    c_int_lvl,
+    c_int_pts,
+    c_dex_lvl,
+    c_dex_pts,
+    c_con_lvl,
+    c_con_pts,
+    c_psi_lvl,
+    c_psi_pts,
+    a_id,
+    c_class,
+    c_profession,
+    c_sex,
+    c_location,
+    c_mc,
+    c_hc,
+    c_tra,
+    c_pc,
+    c_rc,
+    c_tc,
+    c_vhc,
+    c_agl,
+    c_rep,
+    c_rec,
+    c_rcl,
+    c_atl,
+    c_end,
+    c_for,
+    c_fir,
+    c_enr,
+    c_xrr,
+    c_por,
+    c_hlt,
+    c_hck,
+    c_brt,
+    c_psu,
+    c_wep,
+    c_cst,
+    c_res,
+    c_imp,
+    c_ppu,
+    c_apu,
+    c_mst,
+    c_ppw,
+    c_psr,
+    c_wpw,
+    c_apt,
+    c_cash,
+    c_head,
+    c_torso,
+    c_legs,
+    c_str_xp,
+    c_int_xp,
+    c_dex_xp,
+    c_psi_xp,
+    c_con_xp,
+    c_pos_x,
+    c_pos_y,
+    c_pos_z,
+    c_angle_ud,
+    c_angle_lr,
+    c_faction,
+    c_slot,
+    c_online,
+    c_clan,
+    c_soullight
+};
+
+RegEx* PChar::mCharnameRegexFilter = NULL;
+
+PChar::PChar()
+{
+  mID = 0;
+  mAccount = 0;
+  mGender = 0;
+  mClass = 0;
+  mProfession = 1;
+  mFaction = 1;
+  //mModel = 0;
+  //mType = 0;
+  mRealHead = 0;  // Base Skin elements, in complement of (computed) mType
+  mRealTorso = 0; // " Head shouldn't be changeable, except in case of surgery !!!
+  mRealLegs = 0;  // "
+  mSkin = 0;  // Current Skin elements
+  mHead = 0;  // "
+  mTorso = 0; // "
+  mLegs = 0;  // "
+  mHeadColor = mTorsoColor = mLegsColor = 0; // "
+  mHeadDarkness = mTorsoDarkness = mLegsDarkness = 0; // "
+
+  mBodyEffect = 0;
+  mBodyEffectDensity = 0;
+  mQuickBeltActiveSlot = INV_WORN_QB_NONE;
+
+  mLookingAt = 0;
+  mLookAtTimestamp = 0;
+  mLastUsedWorldObjectId = 0;
+
+  mSpeedOverride = 255; // means no override. Value 0 can be used to forbid any move.
+
+  mLocationLeased = false; // temp until char on-demand load/unload
+  mLocation = 0;
+  mStartApt = 0;
+  mPrimaryApt = 0;
+  mCash = 0;
+
+  mSeatInUseType = seat_none;
+  mSeatInUseObjectId = 0;
+  mSeatInUseSeatId = 0;
+  mVhcAccessRequestList = NULL;
+
+  mContainerInExclusiveUse = NULL;
+
+  mIsOnline = false;
+  mDirtyFlag = false;
+
+  mShunned = false;
+  mJailed = false;
+
+  mDialogNPC = 0;
+  mCurrentDialogNode = 0;
+
+  Skill = new PSkillHandler();
+  mBuddyList = NULL;
+  mGenrepList = NULL;
+
+  // Required for initial OOC Broadcast welcome message.
+  //Gets overwritten as soon as the first PingPacket arrives
+  mActiveChatChannels = 262144;
+  mClanLevel = 0;
+  mClanID = 0;
+}
+
+PChar::~PChar()
+{
+  // Addition; Set char's online status to OFFLINE
+  char sqlqry[50];
+  snprintf(sqlqry, 50, "UPDATE characters SET c_online = 0 WHERE c_id = %d", mID);
+  MySQL->GameQuery(sqlqry);
+
+  delete Skill;
+  delete mBuddyList;
+  delete mGenrepList;
+  delete mVhcAccessRequestList;
+
+  if ( mContainerInExclusiveUse )
+  {
+    mContainerInExclusiveUse->EndUse( mID );
+    Console->Print( RED, BLACK, "Warning: PChar::~PChar : Char still had exclusive use of container. Now freed." );
+  }
+
+  if ( mSeatInUseType != seat_none )
+  {
+    Console->Print( RED, BLACK, "Warning: PChar::~PChar : Char still using seat %d of vhc or chair %d.", mSeatInUseSeatId, mSeatInUseObjectId );
+  }
+}
+
+bool PChar::SetCharnameRegexFilter( const char* RegexStr )
+{
+  if ( mCharnameRegexFilter )
+  {
+    delete mCharnameRegexFilter;
+    mCharnameRegexFilter = NULL;
+  }
+
+  if ( RegexStr )
+  {
+    try
+    {
+      mCharnameRegexFilter = new RegEx( RegexStr, PCRE_CASELESS );
+    }
+    catch ( ... )
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool PChar::IsCharnameWellFormed( const char *Charname )
+{
+  if ( mCharnameRegexFilter )
+  {
+    return mCharnameRegexFilter->Search( Charname );
+  }
+  else
+    return true;
+}
+
+void PChar::SetProfession( uint32_t Profession )
+{
+  const PDefCharKind *def = GameDefs->CharKinds()->GetDef( Profession );
+  if ( def == NULL )
+  {
+    Console->Print( RED, BLACK, "Char %d: Invalid profession %d", mID, Profession );
+    mProfession = 10;
+    mClass = 0;
+  }
+  else
+  {
+    mProfession = Profession;
+    mClass = def->GetType();
+  }
+  SetDirtyFlag();
+}
+
+uint32_t PChar::GetSkinFromCharType( uint32_t nType )
+{
+  const PDefCharacter* nDefCharacter = GameDefs->Chars()->GetDef( nType );
+  if ( nDefCharacter )
+  {
+    return (( uint32_t )( nDefCharacter->GetModel() ) );
+  }
+  else
+    return 0;
+}
+
+inline uint32_t PChar::GetBaseModel()
+{
+  return GetSkinFromCharType( GetType() );
+}
+
+void PChar::SetRealLook( uint32_t nHead, uint32_t nTorso, uint32_t nLegs )
+{
+  mRealHead = nHead;
+  mRealTorso = nTorso;
+  mRealLegs = nLegs;
+  SetDirtyFlag();
+  ResetCurrentLook();
+}
+
+void PChar::GetRealLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs )
+{
+  nSkin = GetBaseModel();
+  nHead = mRealHead;
+  nTorso = mRealTorso;
+  nLegs = mRealLegs;
+}
+
+void PChar::SetCurrentLookFromCharType( uint32_t nType )
+{
+  int iHead, iTorso, iLegs;
+  uint32_t nSkin, nHead, nTorso, nLegs;
+  uint8_t nColor, nBrightness;
+
+  const PDefCharacter* nDefCharacter = GameDefs->Chars()->GetDef( nType );
+  if ( nDefCharacter )
+  {
+    nSkin = ( uint32_t ) nDefCharacter->GetModel();
+    iHead = nDefCharacter->GetHead();
+    iTorso = nDefCharacter->GetTorso();
+    iLegs = nDefCharacter->GetLegs();
+    nColor = ( uint8_t )( 0xff & nDefCharacter->GetColor() );
+    nBrightness = ( uint8_t )( 0xff & nDefCharacter->GetBrightness() );
+
+
+    if (( iHead < 0 ) || ( iTorso < 0 ) || ( iLegs < 0 ) )
+    {
+      nHead = nTorso = nLegs = 0;
+    }
+    else
+    {
+      nHead = iHead % 10;
+      nTorso = iTorso % 10;
+      nLegs = iLegs % 10;
+    }
+
+    SetCurrentLook( nSkin, nHead, nTorso, nLegs );
+    SetCurrentBodyColor( nColor, nColor, nColor, nBrightness, nBrightness, nBrightness );
+  }
+}
+
+void PChar::SetCurrentLook( uint32_t nSkin, uint32_t nHead, uint32_t nTorso, uint32_t nLegs )
+{
+  mSkin = nSkin;
+  mHead = nHead;
+  mTorso = nTorso;
+  mLegs = nLegs;
+  // Ingame skin update will be done automagically in the normal update flow
+  // A flag could also be set somewhere (preferably in Char si that we don't have to care if ingame or not)
+  //    to request quicker ingame update
+}
+
+void PChar::ResetCurrentLook()
+{
+  SetCurrentLook( GetSkinFromCharType( GetType() ), mRealHead, mRealTorso, mRealLegs );
+}
+
+// GetCurrentLook will later have to take Power Armors and GM overrides into account
+void PChar::GetCurrentLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs )
+{
+  nSkin = mSkin;
+  nHead = mHead;
+  nTorso = mTorso;
+  nLegs = mLegs;
+}
+
+void PChar::SetCurrentBodyColor( uint8_t nHeadColor, uint8_t nTorsoColor, uint8_t nLegsColor, uint8_t nHeadDarkness, uint8_t nTorsoDarkness, uint8_t nLegsDarkness )
+{
+  mHeadColor = nHeadColor;
+  mTorsoColor = nTorsoColor;
+  mLegsColor = nLegsColor;
+  mHeadDarkness = nHeadDarkness;
+  mTorsoDarkness = nTorsoDarkness;
+  mLegsDarkness = nLegsDarkness;
+}
+
+void PChar::GetCurrentBodyColor( uint8_t &nHeadColor, uint8_t &nTorsoColor, uint8_t &nLegsColor, uint8_t &nHeadDarkness, uint8_t &nTorsoDarkness, uint8_t &nLegsDarkness )
+{
+  nHeadColor = mHeadColor;
+  nTorsoColor = mTorsoColor;
+  nLegsColor = mLegsColor;
+  nHeadDarkness = mHeadDarkness;
+  nTorsoDarkness = mTorsoDarkness;
+  nLegsDarkness = mLegsDarkness;
+}
+
+void PChar::SetBaseSkills()
+{
+  const PDefCharKind *def = GameDefs->CharKinds()->GetDef( mProfession );
+  //Console->Print(YELLOW, BLACK, "PChar::SetBaseSkills() Profession: %d",def->GetIndex());
+  if ( def == NULL )
+  {
+    Console->Print( RED, BLACK, "PChar::SetBaseSkills: GetCharKindDef=NULL" );
+    return;
+  }
+  Skill->SetMainSkill( MS_INT, def->GetSkillInfo( MS_INT ).mStart );
+  Skill->SetMainSkill( MS_CON, def->GetSkillInfo( MS_CON ).mStart );
+  Skill->SetMainSkill( MS_DEX, def->GetSkillInfo( MS_DEX ).mStart );
+  Skill->SetMainSkill( MS_STR, def->GetSkillInfo( MS_STR ).mStart );
+  Skill->SetMainSkill( MS_PSI, def->GetSkillInfo( MS_PSI ).mStart );
+  // management of SP needed ? NC Client seem to calculate what remains ...
+  // or put SP setting after subskill setting ?
+  /* Skill->SetSP(MS_INT, (short) ??? ));
+  Skill->SetSP(MS_CON, ((short) ??? ));
+  Skill->SetSP(MS_DEX, (short) ??? ));
+  Skill->SetSP(MS_STR, (short) ??? ));
+  Skill->SetSP(MS_PSI, ((short) ??? )); */
+  // what about XPs ?
+  /* Skill->SetXP(MS_INT, ??? ));
+  Skill->SetXP(MS_CON, ??? ));
+  Skill->SetXP(MS_DEX, ??? ));
+  Skill->SetXP(MS_STR, ??? ));
+  Skill->SetXP(MS_PSI, ??? )); */
+  Console->Print( YELLOW, BLACK, "PChar::SetBaseSkills() not fully functionnal - unused skill points will be lost" );
+}
+
+void PChar::SetBaseSubskills( uint8_t NSZNb, const char* NonZeroSubskills )
+{
+  int i;
+
+  if ( NSZNb == 0 )
+    return;
+
+  for ( i = 0; i < NSZNb; i++ )
+  {
+    Skill->SetSubSkill(( SUB_SKILLS ) NonZeroSubskills[2 * i], ( int ) NonZeroSubskills[2 * i +1] );
+  }
+}
+
+void PChar::SetBaseInventory()
+{
+  uint8_t i;
+  uint32_t BaseItemID;
+  const PDefCharKind *def = GameDefs->CharKinds()->GetDef( mProfession );
+
+  //mCash = 5000;
+  mCash = def->GetStartMoney();
+
+  for ( i = 0; i < 8 ; i++ )
+  {
+    BaseItemID = def->GetStartInventory( i );
+    if ( BaseItemID )
+    {
+      if ( gDevDebug ) Console->Print( GREEN, BLACK, "Adding item %d to base inventory", BaseItemID );
+      PItem* NewItem = new PItem( BaseItemID );
+      if ( NewItem->GetItemID() )
+      {
+        NewItem->MakeItemStandard( 120, 180 ); // global quality range
+        mInventory.AddItem( NewItem );
+      }
+      else
+      {
+        Console->Print( RED, BLACK, "Invalid item ID %d in base inventory for profession %d", BaseItemID, mProfession );
+      }
+    }
+  }
+}
+
+void PChar::LoadClanLevel()
+{
+    MYSQL_RES *result;
+    char query[200];
+
+    snprintf(query, 200, "SELECT cll_level FROM clanlevels WHERE cll_charid = %d AND cll_clanid = %d", mID, mClanID);
+    result = MySQL->GameResQuery( query );
+    if ( result == NULL )
+    {
+        mClanID = 0;
+        Console->Print( RED, BLACK, "PChar::GetClanLevel could not load ClanLevel from the database" );
+        Console->Print( "Query was:" );
+        Console->Print( "%s", query );
+        MySQL->ShowGameSQLError();
+        return;
+    }
+    else if(mysql_num_rows(result) == 0)
+    {
+        mClanID = 0;
+        Console->Print( RED, BLACK, "PChar::GetClanLevel No level entry found for clan!" );
+        return;
+    }
+    mClanLevel = atoi(mysql_fetch_row(result)[0]);
+    if (gDevDebug) Console->Print("Loaded ClanLevel %d for char %d, clan %d", mClanLevel, mID, mClanID);
+}
+
+bool PChar::SQLLoad( int CharID )
+{
+  MYSQL_RES *result;
+  MYSQL_ROW row;
+  char query[1024];
+
+  snprintf( query, 1024, "SELECT * FROM characters WHERE c_id = %d LIMIT 1", CharID );
+  result = MySQL->GameResQuery( query );
+  if ( result == NULL )
+  {
+    Console->Print( RED, BLACK, "PChar::SQLLoad could not load Chardata from the database" );
+    Console->Print( "Query was:" );
+    Console->Print( "%s", query );
+    MySQL->ShowGameSQLError();
+    return false;
+  }
+  if (( row = mysql_fetch_row( result ) ) )
+  {
+    SetID( CharID );
+    SetName( row[c_name] );
+    SetAccount( atoi( row[a_id] ) );
+
+    // Gender
+    int genvalue = atoi( row[c_sex] );
+    if (( genvalue == 0 ) || ( genvalue == 1 ) )
+      mGender = static_cast<uint32_t>( genvalue );
+    else
+    {
+      Console->Print( RED, BLACK, "Bad gender value: %d (Char ID %d)", genvalue, mID );
+      mGender = 0;
+    }
+
+    // Profession
+    int profvalue = atoi( row[c_profession] );
+    SetProfession( static_cast<uint32_t>( profvalue ) );
+
+    // Class
+    //int classvalue = atoi(row[c_class]);
+    //if(classvalue < 4)
+    //    mClass = static_cast<uint32_t>(classvalue);
+    //else
+    //{
+    //  Console->Print(RED, BLACK, "Bad class value: %d (Char ID %d)", classvalue, mID);
+    //  classvalue = 0;
+    //}
+
+    // Faction
+    int facvalue = atoi( row[c_faction] );
+    if ( GameDefs->Factions()->GetDef( facvalue ) )
+      mFaction = static_cast<uint32_t>( facvalue );
+    else
+      mFaction = 1;
+
+    /* // Model
+    int modvalue = atoi(row[c_model]);
+    mModel = static_cast<uint32_t>(modvalue);
+    mModel = 10; */
+    int headvalue = atoi( row[c_head] );
+    int torsovalue = atoi( row[c_torso] );
+    int legsvalue = atoi( row[c_legs] );
+    SetRealLook( static_cast<uint32_t>( headvalue ), static_cast<uint32_t>( torsovalue ), static_cast<uint32_t>( legsvalue ) );
+
+    // Type
+    /*
+    int typevalue = std::atoi(row[c_type]);
+    mType = static_cast<uint32_t>(typevalue);
+    //mType = 1; */
+
+    // Location
+    int locvalue = atoi( row[c_location] );
+    mLocation = static_cast<uint32_t>( locvalue );
+
+//This assumption is not so good ... hardcoding jailed state linked with location ...
+    if ( mLocation == 550 || mLocation == 551 )
+      mJailed = true;
+
+    int posvalue = atoi( row[c_pos_x] );
+    Coords.mX = static_cast<uint16_t>( posvalue );
+    posvalue = atoi( row[c_pos_y] );
+    Coords.mY = static_cast<uint16_t>( posvalue );
+    posvalue = atoi( row[c_pos_z] );
+    Coords.mZ = static_cast<uint16_t>( posvalue );
+    posvalue = atoi( row[c_angle_ud] );
+    Coords.mUD = static_cast<uint8_t>( posvalue );
+    posvalue = atoi( row[c_angle_lr] );
+    Coords.mLR = static_cast<uint8_t>( posvalue );
+
+    int primapt = atoi( row[c_apt] );
+    mPrimaryApt = static_cast<uint32_t>( primapt );
+    mStartApt = mPrimaryApt;
+
+    mSoullight = atoi( row[c_soullight] );
+    mClanID = atoi( row[c_clan] );
+    if(mClanID > 0)
+        LoadClanLevel();
+
+    // Cash
+    float cashvalue = atof( row[c_cash] );
+    mCash = static_cast<uint32_t>( cashvalue );
+
+    // ---------------------------------------------
+    // Loading skills --- MAIN Skills with SP and XP
+    // ---------------------------------------------
+    Skill->SetMainSkill( MS_INT, atoi( row[c_int_lvl] ) );
+    Skill->SetMainSkill( MS_CON, atoi( row[c_con_lvl] ) );
+    Skill->SetMainSkill( MS_DEX, atoi( row[c_dex_lvl] ) );
+    Skill->SetMainSkill( MS_STR, atoi( row[c_str_lvl] ) );
+    Skill->SetMainSkill( MS_PSI, atoi( row[c_psi_lvl] ) );
+    // ---------------------------------------------
+    Skill->SetSP( MS_INT, ( short )atoi( row[c_int_pts] ) );
+    Skill->SetSP( MS_CON, ( short )atoi( row[c_con_pts] ) );
+    Skill->SetSP( MS_DEX, ( short )atoi( row[c_dex_pts] ) );
+    Skill->SetSP( MS_STR, ( short )atoi( row[c_str_pts] ) );
+    Skill->SetSP( MS_PSI, ( short )atoi( row[c_psi_pts] ) );
+    // ---------------------------------------------
+    Skill->SetXP( MS_INT, atof( row[c_int_xp] ) );
+    Skill->SetXP( MS_CON, atof( row[c_con_xp] ) );
+    Skill->SetXP( MS_DEX, atof( row[c_dex_xp] ) );
+    Skill->SetXP( MS_STR, atof( row[c_str_xp] ) );
+    Skill->SetXP( MS_PSI, atof( row[c_psi_xp] ) );
+    // ---------------------------------------------
+    // SubSkills
+    // ---------------------------------------------
+    Skill->SetSubSkill( SK_MC, atoi( row[c_mc] ) );
+    Skill->SetSubSkill( SK_HC, atoi( row[c_hc] ) );
+    Skill->SetSubSkill( SK_TRA, atoi( row[c_tra] ) );
+    Skill->SetSubSkill( SK_FOR, atoi( row[c_for] ) );
+    Skill->SetSubSkill( SK_PC, atoi( row[c_pc] ) );
+    Skill->SetSubSkill( SK_RC, atoi( row[c_rc] ) );
+    Skill->SetSubSkill( SK_TC, atoi( row[c_tc] ) );
+    Skill->SetSubSkill( SK_VHC, atoi( row[c_vhc] ) );
+    Skill->SetSubSkill( SK_AGL, atoi( row[c_agl] ) );
+    Skill->SetSubSkill( SK_REP, atoi( row[c_rep] ) );
+    Skill->SetSubSkill( SK_REC, atoi( row[c_rec] ) );
+    Skill->SetSubSkill( SK_RCL, atoi( row[c_rcl] ) );
+    Skill->SetSubSkill( SK_ATL, atoi( row[c_atl] ) );
+    Skill->SetSubSkill( SK_END, atoi( row[c_end] ) );
+    Skill->SetSubSkill( SK_FIR, atoi( row[c_fir] ) );
+    Skill->SetSubSkill( SK_ENR, atoi( row[c_enr] ) );
+    Skill->SetSubSkill( SK_XRR, atoi( row[c_xrr] ) );
+    Skill->SetSubSkill( SK_POR, atoi( row[c_por] ) );
+    Skill->SetSubSkill( SK_HLT, atoi( row[c_hlt] ) );
+    Skill->SetSubSkill( SK_HCK, atoi( row[c_hck] ) );
+    Skill->SetSubSkill( SK_BRT, atoi( row[c_brt] ) );
+    Skill->SetSubSkill( SK_PSU, atoi( row[c_psu] ) );
+    Skill->SetSubSkill( SK_WEP, atoi( row[c_wep] ) );
+    Skill->SetSubSkill( SK_CST, atoi( row[c_cst] ) );
+    Skill->SetSubSkill( SK_RES, atoi( row[c_res] ) );
+    Skill->SetSubSkill( SK_IMP, atoi( row[c_imp] ) );
+    Skill->SetSubSkill( SK_PPU, atoi( row[c_ppu] ) );
+    Skill->SetSubSkill( SK_APU, atoi( row[c_apu] ) );
+    Skill->SetSubSkill( SK_MST, atoi( row[c_mst] ) );
+    Skill->SetSubSkill( SK_PPW, atoi( row[c_ppw] ) );
+    Skill->SetSubSkill( SK_PSR, atoi( row[c_psr] ) );
+    Skill->SetSubSkill( SK_WPW, atoi( row[c_wpw] ) );
+    // --------------------------------------------
+    // Inventory
+    // ---------------------------------------------
+    mInventory.SetCharId( mID );
+    mInventory.SQLLoad();
+
+    // temp value forcing, not get/saved from DB atm
+    mCombatRank = ( uint8_t )( random() % 127 ); // bad result there on randomness
+    mSynaptic = 0;
+    mIsDead = false;
+
+    mDirectCharID = 0; // until saved/loaded with char
+    mBuddyList = new PBuddyList( mID );
+    if ( !mBuddyList->SQLLoad() )
+    {
+      Console->Print( RED, BLACK, "Char ID %d : Can't load buddy list", mID );
+    }
+    //to add: Chats settings
+
+    mGenrepList = new PGenrepList( mID );
+    if ( !mGenrepList->SQLLoad() )
+    {
+      Console->Print( RED, BLACK, "Char ID %d : Can't load genrep list", mID );
+    }
+
+  }
+  MySQL->FreeGameSQLResult( result );
+
+  // Addition; Set char's online status to ONLINE
+  char sqlqry[50];
+  snprintf(sqlqry, 50, "UPDATE characters SET c_online = 1 WHERE c_id = %d", mID);
+  MySQL->GameQuery(sqlqry);
+
+  return true;
+}
+
+bool PChar::SQLCreate() // Specific method for creation in order to avoid existence check with each save
+{
+  std::string query, queryv;
+
+  query = "INSERT INTO characters (c_id";
+  queryv = ") VALUES (NULL";
+
+  query += ",c_name";
+  queryv = queryv + ",'" + mName + "'";
+
+  query += ",a_id";
+  queryv += Ssprintf( ",'%u'", mAccount );
+  query += ",c_class";
+  queryv += Ssprintf( ",'%u'", mClass );
+  query += ",c_sex";
+  queryv += Ssprintf( ",'%u'", mGender );
+  query += ",c_profession";
+  queryv += Ssprintf( ",'%u'", mProfession );
+  query += ",c_faction";
+  queryv += Ssprintf( ",'%u'", mFaction );
+  query += ",c_head";
+  queryv += Ssprintf( ",'%u'", mRealHead );
+  query += ",c_torso";
+  queryv += Ssprintf( ",'%u'", mRealTorso );
+  query += ",c_legs";
+  queryv += Ssprintf( ",'%u'", mRealLegs );
+  //query += ",c_model";
+  //queryv += Ssprintf(",'%u'", mModel);
+  //query += ",c_type";
+  //queryv += Ssprintf(",'%u'", mType);
+  query += ",c_location";
+  queryv += Ssprintf( ",'%u'", mLocation );
+  query += ",c_cash";
+  queryv += Ssprintf( ",'%u'", mCash );
+  query += ",c_slot";
+  queryv += Ssprintf( ",'%u'", mSlot );
+
+  query = query + queryv + ");";
+
+  if ( MySQL->GameQuery( query.c_str() ) )
+  {
+    Console->Print( RED, BLACK, "PChar::SQLCreate could not add char %s to database", mName.c_str() );
+    Console->Print( "Query was:" );
+    Console->Print( "%s", query.c_str() );
+    MySQL->ShowGameSQLError();
+    return false;
+  }
+  else
+  {
+    mID = MySQL->GetLastGameInsertId();
+//Console->Print(GREEN, BLACK, "New char %s got ID %d", mName.c_str(), mID);
+    mDirtyFlag = true;
+    return true;
+  }
+}
+
+bool PChar::CreateNewChar( uint32_t Account, const std::string &Name, uint32_t Gender, uint32_t Profession, uint32_t Faction,
+                           uint32_t Head, uint32_t Torso, uint32_t Legs, uint8_t NZSNb, const char *NonZeroSubskills, uint32_t Slot )
+{
+  SetName( Name );
+  SetGender( Gender );
+  SetProfession( Profession );
+  SetFaction( Faction );
+  SetRealLook( Head, Torso, Legs );
+  SetBaseSkills();
+  SetBaseSubskills( NZSNb, NonZeroSubskills );
+  SetBaseInventory();
+  SetAccount( Account );
+  SetCharSlot( Slot );
+  mLocation = Config->GetOptionInt( "new_char_location" );
+
+  // This part will have to be rewritten with proper methods
+  mSoullight = 10;
+  mCombatRank = ( uint8_t )( random() % 80 ); // bad result there on randomness
+  mSynaptic = 0;
+  mIsDead = false;
+
+  mDirectCharID = 0; // until saved/loaded with char
+
+  SetDirtyFlag();
+
+  if ( SQLCreate() ) // mID isn't defined before that
+  {
+    mBuddyList = new PBuddyList( mID );
+    mGenrepList = new PGenrepList( mID );
+    mStartApt = mPrimaryApt = Appartements->CreateBaseAppartement( mID, mName, mFaction );
+    mInventory.SetCharId( mID );
+
+    if ( mStartApt && SQLSave() && mInventory.SQLSave() )
+    {
+      return true;
+    }
+    else
+    {
+      Console->Print( YELLOW, BLACK, "New char %s (id %d) : creation aborted", mName.c_str(), mID );
+      if ( mID )
+      {
+        SQLDelete();
+        if ( mStartApt )
+        {
+          Appartements->DeleteCharAppartements( mID );
+        }
+      }
+    }
+  }
+  return false;
+}
+
+bool PChar::SQLSave()
+{
+  std::string query;
+  //std::string ts;
+
+  /* TODO:
+    - Mostly at creation/load :
+              c_apt, (or when first GR to primary apt to avoid creation of unused apt?)
+              (c_slot)
+    - At save/load :
+              SoulLight ???
+              FactionSymp[] ???
+              Chest change: style, brightness, color
+              Legs change: style, brightness, color
+              mHealt, mStamina, mMana (not in DB !!!)
+              How to compute MaxHealth etc. ?
+  */
+  query = "UPDATE characters SET";
+
+  query += Ssprintf( " c_location='%u'", mLocation );
+  query += Ssprintf( ",c_pos_x='%u'", Coords.mX );
+  query += Ssprintf( ",c_pos_y='%u'", Coords.mY );
+  query += Ssprintf( ",c_pos_z='%u'", Coords.mZ );
+  query += Ssprintf( ",c_angle_ud='%u'", Coords.mUD );
+  query += Ssprintf( ",c_angle_lr='%u'", Coords.mLR );
+  query += Ssprintf( ",c_cash='%u'", mCash );
+  query += Ssprintf( ",c_apt='%u'", mPrimaryApt );
+
+  query += Ssprintf( ",c_head='%u'", mRealHead );
+  query += Ssprintf( ",c_torso='%u'", mRealTorso );
+  query += Ssprintf( ",c_legs='%u'", mRealLegs );
+
+  query += Ssprintf( ",c_faction='%u'", mFaction );
+
+  /* This group of fiels shouldn't change in-game
+  query = query + ",c_name='" + mName + "'";
+  query += Ssprintf(",a_id='%u'", mAccount);
+  query += Ssprintf(",c_class='%u'", mClass);
+  query += Ssprintf(",c_sex='%u'", mGender);
+  query += Ssprintf(",c_profession='%u'", mProfession);
+  query += Ssprintf(",c_slot='%u'", mSlot);
+  // query += Ssprintf(",c_model='%u'", mModel);
+  // query += Ssprintf(",c_type='%u'", mType);
+  */
+
+  // ---------------------------------------------
+  // Saving skills --- MAIN Skills with SP and XP
+  // ---------------------------------------------
+  query += Ssprintf( ",c_int_lvl='%u'", Skill->GetMainSkill( MS_INT ) );
+  query += Ssprintf( ",c_con_lvl='%u'", Skill->GetMainSkill( MS_CON ) );
+  query += Ssprintf( ",c_dex_lvl='%u'", Skill->GetMainSkill( MS_DEX ) );
+  query += Ssprintf( ",c_str_lvl='%u'", Skill->GetMainSkill( MS_STR ) );
+  query += Ssprintf( ",c_psi_lvl='%u'", Skill->GetMainSkill( MS_PSI ) );
+  // ---------------------------------------------
+  query += Ssprintf( ",c_int_pts='%u'", Skill->GetSP( MS_INT ) );
+  query += Ssprintf( ",c_con_pts='%u'", Skill->GetSP( MS_CON ) );
+  query += Ssprintf( ",c_dex_pts='%u'", Skill->GetSP( MS_DEX ) );
+  query += Ssprintf( ",c_str_pts='%u'", Skill->GetSP( MS_STR ) );
+  query += Ssprintf( ",c_psi_pts='%u'", Skill->GetSP( MS_PSI ) );
+  // ---------------------------------------------
+  query += Ssprintf( ",c_int_xp='%u'", Skill->GetXP( MS_INT ) );
+  query += Ssprintf( ",c_con_xp='%u'", Skill->GetXP( MS_CON ) );
+  query += Ssprintf( ",c_dex_xp='%u'", Skill->GetXP( MS_DEX ) );
+  query += Ssprintf( ",c_str_xp='%u'", Skill->GetXP( MS_STR ) );
+  query += Ssprintf( ",c_psi_xp='%u'", Skill->GetXP( MS_PSI ) );
+  // ---------------------------------------------
+  // SubSkills
+  // ---------------------------------------------
+  query += Ssprintf( ",c_mc='%u'", Skill->GetSubSkill( SK_MC ) );
+  query += Ssprintf( ",c_hc='%u'", Skill->GetSubSkill( SK_HC ) );
+  query += Ssprintf( ",c_tra='%u'", Skill->GetSubSkill( SK_TRA ) );
+  query += Ssprintf( ",c_for='%u'", Skill->GetSubSkill( SK_FOR ) );
+  query += Ssprintf( ",c_pc='%u'", Skill->GetSubSkill( SK_PC ) );
+  query += Ssprintf( ",c_rc='%u'", Skill->GetSubSkill( SK_RC ) );
+  query += Ssprintf( ",c_tc='%u'", Skill->GetSubSkill( SK_TC ) );
+  query += Ssprintf( ",c_vhc='%u'", Skill->GetSubSkill( SK_VHC ) );
+  query += Ssprintf( ",c_agl='%u'", Skill->GetSubSkill( SK_AGL ) );
+  query += Ssprintf( ",c_rep='%u'", Skill->GetSubSkill( SK_REP ) );
+  query += Ssprintf( ",c_rec='%u'", Skill->GetSubSkill( SK_REC ) );
+  query += Ssprintf( ",c_rcl='%u'", Skill->GetSubSkill( SK_RCL ) );
+  query += Ssprintf( ",c_atl='%u'", Skill->GetSubSkill( SK_ATL ) );
+  query += Ssprintf( ",c_end='%u'", Skill->GetSubSkill( SK_END ) );
+  query += Ssprintf( ",c_fir='%u'", Skill->GetSubSkill( SK_FIR ) );
+  query += Ssprintf( ",c_enr='%u'", Skill->GetSubSkill( SK_ENR ) );
+  query += Ssprintf( ",c_xrr='%u'", Skill->GetSubSkill( SK_XRR ) );
+  query += Ssprintf( ",c_por='%u'", Skill->GetSubSkill( SK_POR ) );
+  query += Ssprintf( ",c_htl='%u'", Skill->GetSubSkill( SK_HLT ) );
+  query += Ssprintf( ",c_hck='%u'", Skill->GetSubSkill( SK_HCK ) );
+  query += Ssprintf( ",c_brt='%u'", Skill->GetSubSkill( SK_BRT ) );
+  query += Ssprintf( ",c_psu='%u'", Skill->GetSubSkill( SK_PSU ) );
+  query += Ssprintf( ",c_wep='%u'", Skill->GetSubSkill( SK_WEP ) );
+  query += Ssprintf( ",c_cst='%u'", Skill->GetSubSkill( SK_CST ) );
+  query += Ssprintf( ",c_res='%u'", Skill->GetSubSkill( SK_RES ) );
+  query += Ssprintf( ",c_imp='%u'", Skill->GetSubSkill( SK_IMP ) );
+  query += Ssprintf( ",c_ppu='%u'", Skill->GetSubSkill( SK_PPU ) );
+  query += Ssprintf( ",c_apu='%u'", Skill->GetSubSkill( SK_APU ) );
+  query += Ssprintf( ",c_mst='%u'", Skill->GetSubSkill( SK_MST ) );
+  query += Ssprintf( ",c_ppw='%u'", Skill->GetSubSkill( SK_PPW ) );
+  query += Ssprintf( ",c_psr='%u'", Skill->GetSubSkill( SK_PSR ) );
+  query += Ssprintf( ",c_wpw='%u'", Skill->GetSubSkill( SK_WPW ) );
+  // ---------------------------------------------
+
+  query += Ssprintf( " WHERE c_id='%u' LIMIT 1;", mID );
+
+  if ( MySQL->GameQuery( query.c_str() ) )
+  {
+    Console->Print( RED, BLACK, "PChar::SQLSave could not save char %s (%u) to database", mName.c_str(), mID );
+    Console->Print( "Query was:" );
+    Console->Print( "%s", query.c_str() );
+    MySQL->ShowGameSQLError();
+    return false;
+  }
+
+  // Chats settings (?), directs
+
+  mDirtyFlag = false;
+  return true;
+}
+
+bool PChar::SQLDelete()
+{
+  return true;
+}
+
+void PChar::SetOnlineStatus( bool IsOnline )
+{
+  // Deactivated, until Maxx added c_isonline row to `characters`
+  //char query[255];
+  int onlinestatus = 0;
+
+  if ( IsOnline )
+  {
+    onlinestatus = 0; // Strange ????
+    mIsOnline = true;
+  }
+  else
+  {
+    onlinestatus = 1; // Strange ????
+    mIsOnline = false;
+  }
+
+//    snprintf(query, 255, "UPDATE charlist SET c_isonline = %d WHERE a_id = %d AND c_id = %d", onlinestatus, mAccount, mID);
+//    if(MySQL->Query(query))
+//    {
+//        Console->Print("Error: Cant set onlinestatus to '%d' for Account: %d, Char: %d", onlinestatus, mAccount, mID);
+//        MySQL->ShowSQLError();
+//        return;
+//    }
+  return;
+}
+
+uint8_t PChar::GetCombatRank()
+{
+    // Override for Special Account Levels
+    PAccount Acc(mAccount);
+    if(Acc.GetLevel() == PAL_ADMIN)
+        return 127;
+    else if(Acc.GetLevel() >= PAL_GM)
+        return 120;
+    else if(Acc.GetLevel() >= PAL_VOLUNTEER)
+        return 50;
+    else
+        return mCombatRank;
+}
+
+
+uint8_t PChar::GetMainRank()
+{
+    // Override for Special Account Levels
+    PAccount Acc(mAccount);
+    if(Acc.GetLevel() == PAL_ADMIN)
+        return 127;
+    else if(Acc.GetLevel() >= PAL_GM)
+        return 120;
+    else if(Acc.GetLevel() >= PAL_VOLUNTEER)
+        return 50;
+    else
+    {
+      uint16_t total;
+      total  = Skill->GetMainSkill( MS_STR ) + Skill->GetMainSkill( MS_DEX );
+      total += Skill->GetMainSkill( MS_CON ) + Skill->GetMainSkill( MS_INT );
+      total += Skill->GetMainSkill( MS_PSI );
+      return (( uint8_t )( total / 5 ) );
+    }
+}
+
+bool PChar::AddGenrep(uint16_t nWorldID, uint16_t nStationID)
+{
+    return mGenrepList->AddGenrep(nWorldID, nStationID );
+}
+
+uint16_t PChar::GetGenrepListDataSize()
+{
+    return mGenrepList->GetListDataSize();
+}
+
+const void *PChar::GetGenrepListData()
+{
+    return mGenrepList->GetListData();
+}
+
+uint8_t PChar::GetGenrepCount()
+{
+    return mGenrepList->Count();
+}
+
+uint32_t PChar::AddCash( uint32_t nAmount )
+{
+    return SetCash(nAmount + mCash);
+}
+
+uint32_t PChar::TakeCash( uint32_t nAmount )
+{
+    if(nAmount > mCash)
+    {
+        //Tries to take away more cash that user has, set to zero
+        return SetCash(0);
+    }
+    else
+    {
+        return SetCash(mCash-nAmount);
+    }
+}
+
+uint32_t PChar::SetCash( uint32_t nCash )
+{
+  //Console->Print("Trying to set cash to nCash: %d", nCash);
+  if (( int )nCash > Config->GetOptionInt( "max_cash" ) )
+  {
+    //Console->Print("Newcash would be more than dynamic maxcash, setting to maxcash");
+    mCash = ( uint32_t )Config->GetOptionInt( "max_cash" );
+  }
+  else if ( nCash > MAXCASH )
+  {
+    //Console->Print("Newcash would be more than hardcoded maxcash, setting to maxcash");
+    mCash = MAXCASH;
+  }
+  else
+  {
+    //Console->Print("Allright, setting to new value");
+    mCash = nCash;
+  }
+  //Console->Print("Returning mCash: %d", mCash);
+  return mCash;
+}
+
+
+bool PChar::SetQuickBeltActiveSlot( uint8_t nSlotID )
+{
+  if (( nSlotID == INV_WORN_QB_HAND ) || ( nSlotID == INV_WORN_QB_NONE ) )
+  {
+    mQuickBeltActiveSlot = nSlotID;
+    return true;
+  }
+  else if ( nSlotID <= ( INV_WORN_QB_END - INV_WORN_QB_START ) )
+  {
+    PContainer* tWorn = mInventory.GetContainer( INV_LOC_WORN );
+
+    if ( ! tWorn->IsSlotFree( nSlotID ) ) // => TODO: MUST ALSO CHECK that item is currently usable and can be held in hand
+    {
+      mQuickBeltActiveSlot = nSlotID;
+      return true;
+    }
+    else
+    {
+      Console->Print( "SetQuickBeltActiveSlot: SlotID %d greater than %d or free (%d)", nSlotID, INV_WORN_QB_END - INV_WORN_QB_START, tWorn->IsSlotFree( nSlotID ) );
+    }
+  }
+  return false;
+}
+
+PSeatType PChar::GetSeatInUse( uint32_t* nObjectId, uint8_t* nSeatId )
+{
+  if ( nObjectId )
+  {
+    *nObjectId = mSeatInUseObjectId;
+  }
+  if ( nSeatId )
+  {
+    *nSeatId = mSeatInUseSeatId;
+  }
+
+  return mSeatInUseType;
+}
+
+void PChar::SetSeatInUse( PSeatType nSeatType, uint32_t nObjectId, uint8_t nSeatId )
+{
+  mSeatInUseType = nSeatType;
+  mSeatInUseObjectId = nObjectId;
+  mSeatInUseSeatId = nSeatId;
+}
+
+PVhcAccessRequestList* PChar::GetVhcAccessRequestList()
+{
+  if( ! mVhcAccessRequestList )
+    mVhcAccessRequestList = new PVhcAccessRequestList();
+
+  return mVhcAccessRequestList;
+}
+
+void PChar::SetLookingAt( uint16_t nLocalCharID )
+{
+  mLookingAt = nLocalCharID;
+  mLookAtTimestamp = std::time( NULL );
+}
+
+uint16_t PChar::GetLookingAt( uint16_t nMaxDelaySec )
+{
+  return ((( mLookAtTimestamp + nMaxDelaySec ) >= std::time( NULL ) ) ? mLookingAt : 0 );
+}
+
+// ===================================
+
+PChars::PChars()
+{
+  mLastID = 0;
+  mLastSave = std::time( NULL );
+
+  mAutoSavePeriod = Config->GetOptionInt( "auto_save_period" );
+  if ( mAutoSavePeriod < 0 )
+  {
+    Console->Print( "%s auto_save_period (%d) must be strict positive.", Console->ColorText( RED, BLACK, "[Error]" ), mAutoSavePeriod );
+    mAutoSavePeriod = 0;
+  }
+  else if ( mAutoSavePeriod > 3600 )
+  {
+    Console->Print( "%s auto_save_period (%d) too high. Forced to 3600 sec.", Console->ColorText( YELLOW, BLACK, "[Warning]" ), mAutoSavePeriod );
+    mAutoSavePeriod = 0;
+  }
+
+  if ( mAutoSavePeriod == 0 )
+  {
+    Console->Print( "%s Auto-save disabled.", Console->ColorText( YELLOW, BLACK, "[Info]" ) );
+  }
+  else if ( mAutoSavePeriod < 60 )
+  {
+    Console->Print( "%s auto_save_period (%d) is low and might lead to high server load.", Console->ColorText( YELLOW, BLACK, "[Warning]" ), mAutoSavePeriod );
+  }
+
+}
+
+PChars::~PChars()
+{
+  for ( CharMap::iterator i = mChars.begin(); i != mChars.end(); i++ )
+    delete i->second;
+}
+
+bool PChars::LoadChar( uint32_t CharID )
+{
+  if ( !CharID )
+    return false;
+
+  PChar *nChar = new PChar();
+  if ( nChar->SQLLoad( CharID ) )
+  {
+    nChar->SetDirtyFlag( false );
+    return AddChar( nChar );
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[ERROR] Could not load char id %d from database", CharID );
+    return false;
+  }
+}
+
+bool PChars::AddChar( PChar* nChar )
+{
+  if ( !nChar )
+    return false;
+
+  mLastID = std::max( mLastID, nChar->GetID() );
+  if ( mChars.insert( std::make_pair( nChar->GetID(), nChar ) ).second )
+  {
+    if ( gDevDebug )
+      Console->Print( "%s Char: %s (id %d) added", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nChar->GetName().c_str() , nChar->GetID() );
+    return true;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[ERROR] Trying to load char twice : %s (id %d)", nChar->GetName().c_str(), nChar->GetID() );
+    return false;
+  }
+}
+
+PChar* PChars::RemoveChar( uint32_t CharID )
+{
+  PChar* Result = NULL;
+
+  CharMap::iterator i = mChars.find( CharID );
+  if ( i != mChars.end() )
+  {
+    Result = i->second;
+    mChars.erase( i );
+    if ( gDevDebug )
+      Console->Print( "%s Char: %s (id %d) removed", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), Result->GetName().c_str() , Result->GetID() );
+  }
+
+  return Result;
+}
+
+void PChars::SQLSave()
+{
+  // saves all dirty-flagged chars
+  int nDirtyChars = 0, nSavedChars = 0;
+  int nDirtyInv = 0, nSavedInv = 0;
+
+  for ( CharMap::const_iterator i = mChars.begin(); i != mChars.end(); i++ )
+  {
+    PChar* Char = i->second;
+    if ( Char->IsDirty() )
+    {
+      ++nDirtyChars;
+      if ( Char->SQLSave() )
+        ++nSavedChars;
+    }
+    if ( Char->GetInventory()->IsDirty() )
+    {
+      ++nDirtyInv;
+      if ( Char->GetInventory()->SQLSave() )
+        ++nSavedInv;
+    }
+  }
+  Console->Print( "%s %i chars saved on %i dirty, %i inventories saved on %i dirty", Console->ColorText( GREEN, BLACK, "[DEBUG]" ), nSavedChars, nDirtyChars, nSavedInv, nDirtyInv );
+  return;
+}
+
+PChar* PChars::GetChar( uint32_t CharID ) const
+{
+  PChar *Result = 0;
+  CharMap::const_iterator i = mChars.find( CharID );
+  if ( i != mChars.end() )
+    Result = i->second;
+
+  return Result;
+}
+
+PChar* PChars::GetChar( const std::string &Name ) const
+{
+  PChar *Result = 0;
+  for ( CharMap::const_iterator i = mChars.begin(); i != mChars.end(); i++ )
+  {
+    if ( !/*std::*/strcasecmp( i->second->GetName().c_str(), Name.c_str() ) )
+    {
+      Result = i->second;
+      break;
+    }
+  }
+  return Result;
+}
+
+bool PChars::CharExist( const std::string &Name ) const
+{
+  char query[256];
+  int EntriesNb;
+  MYSQL_RES *result = 0;
+
+  char escUsername[256];
+  MySQL->EscapeString( Name.c_str(), escUsername, 256 );
+  snprintf( query, 256, "SELECT 1 FROM characters WHERE c_name = '%s' LIMIT 1;", escUsername );
+
+  result = MySQL->GameResQuery( query );
+  if ( result == NULL )
+  {
+    Console->Print( RED, BLACK, "[ERROR] Failed to get CharacterData from SQL" );
+    MySQL->ShowGameSQLError();
+    return true;
+  }
+
+  EntriesNb = mysql_num_rows( result );
+  MySQL->FreeGameSQLResult( result );
+  return( EntriesNb > 0 );
+}
+
+void PChars::Update()
+{
+  std::time_t t = std::time( NULL ); // changed to time() to have real time instead of cpu used time
+
+  if ( mAutoSavePeriod && (( t - mLastSave ) >= mAutoSavePeriod ) )
+  {
+    bool NeedSave = false;
+    for ( CharMap::const_iterator i = mChars.begin(); i != mChars.end(); i++ )
+    {
+      if ( i->second->IsAnyDirty() )
+      {
+        NeedSave = true;
+        break;
+      }
+    }
+
+    if ( NeedSave )
+    {
+      if ( gDevDebug ) Console->Print( "%s Some characters need autosaving...", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+      SQLSave();
+      if ( gDevDebug ) Console->Print( "%s Autosave done.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    }
+    mLastSave = t;
+  }
+}
+
+//MAX_CHARS_PER_ACCOUNT
+int PChars::GetCharProfiles( const uint32_t AccountID, PCharProfile* CharSlotsArray, const uint8_t ArraySize )
+{
+  char query[256];
+  int EntriesNb = 0;
+
+  MYSQL_ROW row = 0;
+  MYSQL_RES *result = 0;
+
+  snprintf( query, 256, "SELECT * FROM characters WHERE a_id = %d ORDER BY c_slot ASC", AccountID );
+
+  result = MySQL->GameResQuery( query );
+  if ( result == NULL )
+  {
+    Console->Print( RED, BLACK, "[ERROR] Failed to load CharacterData from SQL" );
+    MySQL->ShowGameSQLError();
+    return 0;
+  }
+
+  //EntriesNb = mysql_num_rows(result);
+  int SlotID;
+  uint32_t CharID;
+  PChar* tmpChar = new PChar();
+
+  while (( row = mysql_fetch_row( result ) ) )
+  {
+    SlotID = atoi( row[c_slot] );
+    CharID = atoi( row[c_id] );
+    if (( SlotID >= 0 ) && ( SlotID < ArraySize ) )
+    {
+      if ( !CharSlotsArray[SlotID].in_use )
+      {
+        tmpChar->SetID( CharID );
+        tmpChar->SetGender( atoi( row[c_sex] ) );
+        tmpChar->SetProfession( atoi( row[c_profession] ) );
+
+        CharSlotsArray[SlotID].CharID = CharID;
+        CharSlotsArray[SlotID].Type = tmpChar->GetType();
+        CharSlotsArray[SlotID].Location = static_cast<uint32_t>( atoi( row[c_location] ) );
+        CharSlotsArray[SlotID].Head = atoi( row[c_head] );
+        CharSlotsArray[SlotID].Torso = atoi( row[c_torso] );
+        CharSlotsArray[SlotID].Legs = atoi( row[c_legs] );
+        CharSlotsArray[SlotID].Name = row[c_name];
+        CharSlotsArray[SlotID].NameLen = CharSlotsArray[SlotID].Name.length() + 1;
+
+        CharSlotsArray[SlotID].in_use = true;
+        ++EntriesNb;
+      }
+      else
+      {
+        Console->Print( YELLOW, BLACK, "[Warning]Character %d using slot %d already used by char %d - Ignored", \
+                        CharID, SlotID, CharSlotsArray[SlotID].CharID );
+      }
+    }
+    else
+    {
+      Console->Print( YELLOW, BLACK, "[Warning]Character %d using invialid slot %d - Ignored", CharID, SlotID );
+    }
+  }
+
+  delete tmpChar;
+  MySQL->FreeGameSQLResult( result );
+  return EntriesNb;
+}
index b2b3030..bb964b6 100644 (file)
-#pragma once\r
-\r
-#include <chrono>\r
-#include <cstdint>\r
-#include <map>\r
-#include "GameServer/Inventory.hxx" // FIXME: class design fault\r
-\r
-#define MAXCASH 1000000000\r
-\r
-class PGenrepList;\r
-class PSkillHandler;\r
-class PVhcAccessRequestList;\r
-\r
-enum PSeatType {\r
-  seat_none = 0,\r
-  seat_chair,\r
-  seat_subway,\r
-  seat_vhc\r
-};\r
-\r
-class PCharCoordinates {\r
-  public:\r
-    uint16_t mY;     // Y-Position in world // Y increases when going East\r
-    uint16_t mZ;     // Z-Position in world // Z increases when going up\r
-    uint16_t mX;     // X-Position in world // X increases when going South\r
-    uint8_t mUD;     // Up - Mid - Down (d6 - 80 - 2a)\r
-    uint8_t mLR;     // Compass direction (S..E..N..W..S [0-45-90-135-179])\r
-    uint8_t mAct;    // Last user action state\r
-    uint8_t mUnknown;// sometime sent by client with value != 0 (usual case)\r
-    // mAct:\r
-    // 0x00 NC has no focus (player alt+tab'ed out)\r
-    // 0x04 Char on ground/dead   00000100\r
-    // 0x20 Char does nothing     00100000\r
-    // 0x22 kneeing               00100010\r
-    // 0x28 left step             00101000\r
-    // 0x30 right step            00110000\r
-    // 0x40 walking (not running) 01000000 // Seems to mean Running ? - to be verfied, with default walk/run mode !!!\r
-    // 0x60 forward               01100000\r
-    // 0xA0 backward              10100000\r
-    // bits:                      BFWRL.K.\r
-\r
-    uint8_t mJumpingState;\r
-\r
-    //inline PCharCoordinates() { mX = mY = mZ = mUD = mLR = mAct = mUnknown = mJumpingState = 0;}\r
-    void SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD = 0x80, uint8_t nLR = 0 );\r
-    void SetInterpolate( PCharCoordinates& Pos1, PCharCoordinates& Pos2, float nCoef );\r
-\r
-    //Temp\r
-    uint16_t minPos[3];\r
-    uint16_t maxPos[3];\r
-    inline PCharCoordinates() { mX = mY = mZ = mUD = mLR = mAct = mUnknown = mJumpingState = 0; for(int i=0; i<3; ++i) { minPos[i] = 0xffff; maxPos[i] = 0; } }\r
-};\r
-\r
-class PChar\r
-{\r
-  private :\r
-    // static members\r
-    static RegEx* mCharnameRegexFilter;\r
-\r
-    // instance members\r
-    uint32_t mID;\r
-    uint32_t mAccount;\r
-    uint8_t mSlot;\r
-    std::string mName;\r
-    uint32_t mGender;\r
-    uint32_t mClass;\r
-    //uint32_t mType; // Removed that and only keep GetType()\r
-    uint32_t mProfession;\r
-    uint32_t mFaction;\r
-    uint32_t mRealHead;  // Base Skin elements, in complement of (computed) mType\r
-    uint32_t mRealTorso; // " Head shouldn't be changeable, except in case of surgery !!!\r
-    uint32_t mRealLegs;  // "\r
-    uint32_t mSkin;  // Current Skin elements. *** Not saved in DB atm ***\r
-    uint32_t mHead;  // "\r
-    uint32_t mTorso; // "\r
-    uint32_t mLegs;  // "\r
-    uint8_t mHeadColor;  // "\r
-    uint8_t mTorsoColor; // "\r
-    uint8_t mLegsColor;  // "\r
-    uint8_t mHeadDarkness;  // " // 0=Bright, 255=dark\r
-    uint8_t mTorsoDarkness; // "\r
-    uint8_t mLegsDarkness;  // "\r
-    // Skin scale factor setting remain to discover, provided they are somewhere for player chars ...\r
-\r
-    bool mLocationLeased; // temp until char on-demand load/unload\r
-    uint32_t mLocation;\r
-    uint32_t mCash;\r
-    uint32_t mStartApt; // set same as PrimaryApt atm\r
-    uint32_t mPrimaryApt;\r
-\r
-    // not saved in DB atm\r
-    PSeatType mSeatInUseType;\r
-    uint32_t mSeatInUseObjectId;\r
-    uint8_t mSeatInUseSeatId;\r
-    PVhcAccessRequestList* mVhcAccessRequestList;\r
-\r
-    PContainer* mContainerInExclusiveUse;\r
-\r
-    uint16_t mHealth;\r
-    uint16_t mMana;\r
-    uint16_t mStamina;\r
-\r
-    int8_t mSoullight;\r
-    uint8_t mCombatRank; // *** Not got/saved from DB atm ***\r
-    uint8_t mSynaptic; // *** Not got/saved from DB atm ***\r
-    bool mIsDead; // *** Not got/saved from DB atm ***\r
-\r
-    // Only one body effect supported atm. Should be extended later to multiple effects\r
-    uint8_t mBodyEffect; // *** Not got/saved from DB atm ***\r
-    uint8_t mBodyEffectDensity; // *** Not got/saved from DB atm ***\r
-\r
-    uint8_t mSpeedOverride; // a hack to control move speed. Not saved in DB\r
-\r
-    uint32_t mDirectCharID; // for Direct Chat // *** Not got/saved from DB atm ***\r
-    PBuddyList* mBuddyList; // For Buddy list Chat\r
-    uint32_t mActiveChatChannels; // Active chat channels flags // *** Not got/saved from DB atm ***\r
-\r
-    PGenrepList* mGenrepList; // Character's GR list\r
-\r
-    uint8_t mQuickBeltActiveSlot; // QB SlotID of item "in hand", or INV_WORN_QB_HAND or INV_WORN_QB_NONE\r
-\r
-    uint16_t mLookingAt;  // Zone charID of currently targeted player\r
-    std::time_t mLookAtTimestamp; // Lifetimer of lookat var\r
-    uint32_t mLastUsedWorldObjectId; // Last world object clicked on\r
-\r
-    uint8_t mClanLevel; // 1-15\r
-    uint16_t mClanID;\r
-\r
-    bool mIsOnline;\r
-    bool mDirtyFlag;\r
-\r
-    bool mShunned;\r
-    bool mJailed;\r
-\r
-    uint32_t mDialogNPC; // NPCID the player talks to\r
-    uint16_t mCurrentDialogNode; // Node in .lua file we're at right now\r
-\r
-    class PInventory mInventory;\r
-\r
-  protected :\r
-    friend class PChars;\r
-    inline void SetID( uint32_t ID ) { mID = ID; }\r
-    inline void SetAccount( uint32_t Account ) { mAccount = Account; }\r
-    inline void SetCharSlot( uint8_t Slot ) { if ( Slot < 4 ) mSlot = Slot;} // TODO: set max slot according to server config\r
-    inline void SetName( const std::string &Name ) { mName = Name; }\r
-    inline void SetGender( uint32_t Gender ) { mGender = Gender; }\r
-    void SetProfession( uint32_t Profession );\r
-    //inline void SetClass(uint32_t nClass) { mClass = nClass; } // mClass is defined by setting Profession\r
-    //inline void SetType(uint32_t Type) { mType = Type; } // Removed. Type is computed from Gender & Profession (??? is it not Gender + Class ???)\r
-    inline void SetFaction( uint32_t Faction ) { mFaction = Faction; }\r
-    //inline void SetModel(uint32_t Model) { mModel = Model; } // Inhibited for the moment. Base model is deduced from from Gender & Class (Profession)\r
-    void SetRealLook( uint32_t nHead, uint32_t nTorso, uint32_t nLegs );\r
-    void SetBaseSkills();\r
-    void SetBaseSubskills( uint8_t NZSNb, const char* NonZeroSubskills );\r
-    void SetBaseInventory();\r
-\r
-    bool SQLCreate();\r
-\r
-  public :\r
-    PChar();\r
-    ~PChar();\r
-\r
-    static bool SetCharnameRegexFilter( const char* RegexStr );\r
-    static bool IsCharnameWellFormed( const char *Username );\r
-\r
-    PSkillHandler *Skill;\r
-    PCharCoordinates Coords;\r
-\r
-    void SetCurrentLook( uint32_t nSkin, uint32_t nHead = 0, uint32_t nTorso = 0, uint32_t nLegs = 0 );\r
-    void SetCurrentLookFromCharType( uint32_t nType );\r
-    void ResetCurrentLook();\r
-\r
-    void SetCurrentBodyColor( uint8_t nHeadColor, uint8_t nTorsoColor, uint8_t nLegsColor, uint8_t nHeadDarkness = 0, uint8_t nTorsoDarkness = 0, uint8_t nLegsDarkness = 0 );\r
-    inline void SetBodyEffect( uint8_t nEffect, uint8_t nDensity = 0 ) { mBodyEffect = nEffect; mBodyEffectDensity = nDensity; }\r
-    inline void SetSpeedOverride( uint8_t nSpeed = 255 ) { mSpeedOverride = nSpeed; }\r
-\r
-    void SetLookingAt( uint16_t nLocalCharID );\r
-    uint16_t GetLookingAt( uint16_t nMaxDelaySec = 1 );\r
-    inline void SetLastUsedObject ( uint32_t nRawItemId ) { mLastUsedWorldObjectId = nRawItemId; }\r
-    inline uint32_t GetLastUsedObject () const { return mLastUsedWorldObjectId; }\r
-\r
-    inline PInventory* GetInventory() { return &mInventory; }\r
-    inline uint32_t GetID() const { return mID; }\r
-    inline uint32_t GetAccount() const { return mAccount; }\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline uint32_t GetGender() const { return mGender; }\r
-    inline uint32_t GetClass() const { return mClass; }\r
-    inline uint32_t GetType() const { return 2 * mClass + mGender; }\r
-    uint32_t GetSkinFromCharType( uint32_t nType );\r
-    void GetRealLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs );\r
-    void GetCurrentLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs );\r
-    inline void GetBodyEffect( uint8_t &nEffect, uint8_t &nDensity ) { nEffect = mBodyEffect; nDensity = mBodyEffectDensity; }\r
-\r
-    inline uint8_t GetQuickBeltActiveSlot() { return mQuickBeltActiveSlot; }\r
-    bool SetQuickBeltActiveSlot( uint8_t nSlotID );\r
-\r
-    void GetCurrentBodyColor( uint8_t &nHeadColor, uint8_t &nTorsoColor, uint8_t &nLegsColor, uint8_t &nHeadDarkness, uint8_t &nTorsoDarkness, uint8_t &nLegsDarkness );\r
-    inline uint8_t GetSpeedOverride() { return mSpeedOverride; }\r
-    inline uint32_t GetBaseModel();\r
-    inline uint32_t GetProfession() const { return mProfession; }\r
-    inline uint16_t GetMaxHealth() { return mHealth; }\r
-    inline uint16_t GetMaxMana() { return mMana; }\r
-    inline uint16_t GetMaxStamina() { return mStamina; }\r
-    inline uint16_t GetHealth() { return mHealth; }\r
-    inline uint16_t GetMana() { return mMana; }\r
-    inline uint16_t GetStamina() { return mStamina; }\r
-    inline uint32_t GetFaction() const { return mFaction; }\r
-    inline uint32_t GetLocation() const { return mLocation; }\r
-\r
-    inline uint32_t GetCash() const { return mCash; }\r
-    uint32_t SetCash( uint32_t nCash );  // Does return the new cashvalue, NO udpmessage is sent out!!\r
-    uint32_t AddCash( uint32_t nAmount );\r
-    uint32_t TakeCash( uint32_t nAmount );\r
-\r
-    inline uint32_t GetBaseApartment() const { return mPrimaryApt; }\r
-\r
-    inline void SetJail( bool val ) { mJailed = val; };\r
-    inline void SetShun( bool val ) { mShunned = val; };\r
-\r
-    inline bool IsJailed() { return mJailed; };\r
-    inline bool IsShunned() { return mShunned; };\r
-\r
-    inline void SetDialogNPC( uint32_t nNPC ) { mDialogNPC = nNPC; };\r
-    inline uint32_t GetDialogNPC() const { return mDialogNPC; };\r
-\r
-    inline void SetDialogNode( uint16_t nNode ) { mCurrentDialogNode = nNode; };\r
-    inline uint16_t GetDialogNode() const { return mCurrentDialogNode; };\r
-\r
-    inline uint8_t GetClanLevel() const { return mClanLevel; };\r
-    inline uint16_t GetClan() const { return mClanID; };\r
-    void LoadClanLevel();\r
-\r
-    inline int8_t GetSoullight() const { return mSoullight; }\r
-    uint8_t GetMainRank();\r
-    uint8_t GetCombatRank();\r
-    inline uint8_t GetSynaptic() const { return mSynaptic; }\r
-    inline bool IsDead() const { return mIsDead; }\r
-\r
-    inline bool SetDirectChat( uint32_t nBuddyCharID ) { mDirectCharID = nBuddyCharID; return true; }\r
-    inline uint32_t GetDirectChat() { return mDirectCharID; }\r
-    inline void SetActiveChannels( uint32_t nChannels ) { mActiveChatChannels = nChannels; }\r
-    inline uint32_t GetActiveChannels() { return mActiveChatChannels; }\r
-\r
-    inline bool AddBuddy( uint32_t nBuddyCharID ) { return mBuddyList->AddChar( nBuddyCharID ); }\r
-    inline bool RemoveBuddy( uint32_t nBuddyCharID ) { return mBuddyList->RemoveChar( nBuddyCharID ); }\r
-    inline uint16_t GetBuddyListDataSize() { return mBuddyList->GetListDataSize(); }\r
-    inline const void* GetBuddyListData() { return mBuddyList->GetListData(); }\r
-    inline uint8_t GetBuddyCount() { return mBuddyList->Count(); }\r
-    inline bool IsBuddy( uint32_t CharID ) { return mBuddyList->IsInBuddy( CharID ); };\r
-\r
-    bool AddGenrep(uint16_t nWorldID, uint16_t nStationID);\r
-    uint16_t GetGenrepListDataSize();\r
-    const void *GetGenrepListData();\r
-    uint8_t GetGenrepCount();\r
-\r
-    inline bool IsDirty() const { return mDirtyFlag; }\r
-    inline bool IsAnyDirty() const { return mDirtyFlag || mInventory.IsDirty(); }\r
-    inline bool IsOnline() { return mIsOnline; }\r
-    void SetOnlineStatus( bool IsOnline );\r
-\r
-    bool CreateNewChar( uint32_t Account, const std::string &Name, uint32_t Gender, uint32_t Profession, uint32_t Faction,\r
-                        uint32_t Head, uint32_t Torso, uint32_t Legs, uint8_t NZSNb, const char *NonZeroSubskills, uint32_t Slot );\r
-    bool SQLLoad( int CharID );\r
-    bool SQLSave();\r
-    inline bool SQLSaveFull() { return SQLSave() && mInventory.SQLSave(); }\r
-    bool SQLDelete(); // not implemented yet\r
-\r
-    inline void SetLocation( uint32_t Location ) { mLocation = Location; }\r
-    inline void SetDirtyFlag( bool Dirty = true ) { mDirtyFlag = Dirty; }\r
-\r
-    // temp until char on-demand load/unload\r
-    inline void SetLocationLeased( bool nState = true ) { mLocationLeased = nState; }\r
-    inline bool GetLocationLeased() { return mLocationLeased; }\r
-\r
-    PSeatType GetSeatInUse( uint32_t* nObjectId = NULL, uint8_t* nSeatId = NULL );\r
-    void SetSeatInUse( PSeatType nSeatType, uint32_t nObjectId = 0, uint8_t nSeatId = 0 );\r
-\r
-    PVhcAccessRequestList* GetVhcAccessRequestList();\r
-\r
-    inline PContainer* GetContainerInExclusiveUse() { return mContainerInExclusiveUse; }\r
-    inline void SetContainerInExclusiveUse( PContainer* nContainer ) { mContainerInExclusiveUse = nContainer; }\r
-};\r
-\r
-struct PCharProfile\r
-{\r
-  uint32_t CharID;\r
-  uint16_t Type;\r
-  uint16_t Color0;\r
-  uint16_t Unknown1;\r
-  uint8_t Head;\r
-  uint8_t Torso;\r
-  uint8_t Legs;\r
-  uint32_t Location;\r
-  uint8_t NameLen;\r
-  uint8_t Unknown3;\r
-  uint8_t Unknown4;\r
-  uint8_t Unknown5;\r
-  uint8_t Unknown6;\r
-  uint8_t Unknown7;\r
-  uint8_t Unknown8;\r
-  uint8_t Unknown9;\r
-  uint8_t Unknown10;\r
-  uint8_t Unknown11;\r
-  uint8_t Unknown12;\r
-  std::string Name;\r
-  bool in_use;\r
-};\r
-\r
-class PChars\r
-{\r
-  private :\r
-    typedef std::map<uint32_t, PChar*> CharMap;\r
-    CharMap mChars;\r
-    uint32_t mLastID;\r
-\r
-    std::time_t mAutoSavePeriod;\r
-    std::time_t mLastSave;\r
-\r
-  public :\r
-    PChars();\r
-    ~PChars();\r
-\r
-    bool LoadChar( uint32_t CharID );\r
-    bool AddChar( PChar* nChar );\r
-    PChar* RemoveChar( uint32_t CharID );\r
-\r
-    PChar* GetChar( uint32_t CharID ) const;\r
-    PChar* GetChar( const std::string &Name ) const;\r
-    bool CharExist( const std::string &Name ) const;\r
-\r
-    void SQLSave();\r
-    void Update();\r
-\r
-    int GetCharProfiles( const uint32_t AccountID, PCharProfile* CharSlotsArray, const uint8_t ArraySize ); // return effective entries nb\r
-};\r
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#include <map>
+#include "GameServer/Inventory.hxx" // FIXME: class design fault
+
+#define MAXCASH 1000000000
+
+class PGenrepList;
+class PSkillHandler;
+class PVhcAccessRequestList;
+
+enum PSeatType {
+  seat_none = 0,
+  seat_chair,
+  seat_subway,
+  seat_vhc
+};
+
+class PCharCoordinates {
+  public:
+    uint16_t mY;     // Y-Position in world // Y increases when going East
+    uint16_t mZ;     // Z-Position in world // Z increases when going up
+    uint16_t mX;     // X-Position in world // X increases when going South
+    uint8_t mUD;     // Up - Mid - Down (d6 - 80 - 2a)
+    uint8_t mLR;     // Compass direction (S..E..N..W..S [0-45-90-135-179])
+    uint8_t mAct;    // Last user action state
+    uint8_t mUnknown;// sometime sent by client with value != 0 (usual case)
+    // mAct:
+    // 0x00 NC has no focus (player alt+tab'ed out)
+    // 0x04 Char on ground/dead   00000100
+    // 0x20 Char does nothing     00100000
+    // 0x22 kneeing               00100010
+    // 0x28 left step             00101000
+    // 0x30 right step            00110000
+    // 0x40 walking (not running) 01000000 // Seems to mean Running ? - to be verfied, with default walk/run mode !!!
+    // 0x60 forward               01100000
+    // 0xA0 backward              10100000
+    // bits:                      BFWRL.K.
+
+    uint8_t mJumpingState;
+
+    //inline PCharCoordinates() { mX = mY = mZ = mUD = mLR = mAct = mUnknown = mJumpingState = 0;}
+    void SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD = 0x80, uint8_t nLR = 0 );
+    void SetInterpolate( PCharCoordinates& Pos1, PCharCoordinates& Pos2, float nCoef );
+
+    //Temp
+    uint16_t minPos[3];
+    uint16_t maxPos[3];
+    inline PCharCoordinates() { mX = mY = mZ = mUD = mLR = mAct = mUnknown = mJumpingState = 0; for(int i=0; i<3; ++i) { minPos[i] = 0xffff; maxPos[i] = 0; } }
+};
+
+class PChar
+{
+  private :
+    // static members
+    static RegEx* mCharnameRegexFilter;
+
+    // instance members
+    uint32_t mID;
+    uint32_t mAccount;
+    uint8_t mSlot;
+    std::string mName;
+    uint32_t mGender;
+    uint32_t mClass;
+    //uint32_t mType; // Removed that and only keep GetType()
+    uint32_t mProfession;
+    uint32_t mFaction;
+    uint32_t mRealHead;  // Base Skin elements, in complement of (computed) mType
+    uint32_t mRealTorso; // " Head shouldn't be changeable, except in case of surgery !!!
+    uint32_t mRealLegs;  // "
+    uint32_t mSkin;  // Current Skin elements. *** Not saved in DB atm ***
+    uint32_t mHead;  // "
+    uint32_t mTorso; // "
+    uint32_t mLegs;  // "
+    uint8_t mHeadColor;  // "
+    uint8_t mTorsoColor; // "
+    uint8_t mLegsColor;  // "
+    uint8_t mHeadDarkness;  // " // 0=Bright, 255=dark
+    uint8_t mTorsoDarkness; // "
+    uint8_t mLegsDarkness;  // "
+    // Skin scale factor setting remain to discover, provided they are somewhere for player chars ...
+
+    bool mLocationLeased; // temp until char on-demand load/unload
+    uint32_t mLocation;
+    uint32_t mCash;
+    uint32_t mStartApt; // set same as PrimaryApt atm
+    uint32_t mPrimaryApt;
+
+    // not saved in DB atm
+    PSeatType mSeatInUseType;
+    uint32_t mSeatInUseObjectId;
+    uint8_t mSeatInUseSeatId;
+    PVhcAccessRequestList* mVhcAccessRequestList;
+
+    PContainer* mContainerInExclusiveUse;
+
+    uint16_t mHealth;
+    uint16_t mMana;
+    uint16_t mStamina;
+
+    int8_t mSoullight;
+    uint8_t mCombatRank; // *** Not got/saved from DB atm ***
+    uint8_t mSynaptic; // *** Not got/saved from DB atm ***
+    bool mIsDead; // *** Not got/saved from DB atm ***
+
+    // Only one body effect supported atm. Should be extended later to multiple effects
+    uint8_t mBodyEffect; // *** Not got/saved from DB atm ***
+    uint8_t mBodyEffectDensity; // *** Not got/saved from DB atm ***
+
+    uint8_t mSpeedOverride; // a hack to control move speed. Not saved in DB
+
+    uint32_t mDirectCharID; // for Direct Chat // *** Not got/saved from DB atm ***
+    PBuddyList* mBuddyList; // For Buddy list Chat
+    uint32_t mActiveChatChannels; // Active chat channels flags // *** Not got/saved from DB atm ***
+
+    PGenrepList* mGenrepList; // Character's GR list
+
+    uint8_t mQuickBeltActiveSlot; // QB SlotID of item "in hand", or INV_WORN_QB_HAND or INV_WORN_QB_NONE
+
+    uint16_t mLookingAt;  // Zone charID of currently targeted player
+    std::time_t mLookAtTimestamp; // Lifetimer of lookat var
+    uint32_t mLastUsedWorldObjectId; // Last world object clicked on
+
+    uint8_t mClanLevel; // 1-15
+    uint16_t mClanID;
+
+    bool mIsOnline;
+    bool mDirtyFlag;
+
+    bool mShunned;
+    bool mJailed;
+
+    uint32_t mDialogNPC; // NPCID the player talks to
+    uint16_t mCurrentDialogNode; // Node in .lua file we're at right now
+
+    class PInventory mInventory;
+
+  protected :
+    friend class PChars;
+    inline void SetID( uint32_t ID ) { mID = ID; }
+    inline void SetAccount( uint32_t Account ) { mAccount = Account; }
+    inline void SetCharSlot( uint8_t Slot ) { if ( Slot < 4 ) mSlot = Slot;} // TODO: set max slot according to server config
+    inline void SetName( const std::string &Name ) { mName = Name; }
+    inline void SetGender( uint32_t Gender ) { mGender = Gender; }
+    void SetProfession( uint32_t Profession );
+    //inline void SetClass(uint32_t nClass) { mClass = nClass; } // mClass is defined by setting Profession
+    //inline void SetType(uint32_t Type) { mType = Type; } // Removed. Type is computed from Gender & Profession (??? is it not Gender + Class ???)
+    inline void SetFaction( uint32_t Faction ) { mFaction = Faction; }
+    //inline void SetModel(uint32_t Model) { mModel = Model; } // Inhibited for the moment. Base model is deduced from from Gender & Class (Profession)
+    void SetRealLook( uint32_t nHead, uint32_t nTorso, uint32_t nLegs );
+    void SetBaseSkills();
+    void SetBaseSubskills( uint8_t NZSNb, const char* NonZeroSubskills );
+    void SetBaseInventory();
+
+    bool SQLCreate();
+
+  public :
+    PChar();
+    ~PChar();
+
+    static bool SetCharnameRegexFilter( const char* RegexStr );
+    static bool IsCharnameWellFormed( const char *Username );
+
+    PSkillHandler *Skill;
+    PCharCoordinates Coords;
+
+    void SetCurrentLook( uint32_t nSkin, uint32_t nHead = 0, uint32_t nTorso = 0, uint32_t nLegs = 0 );
+    void SetCurrentLookFromCharType( uint32_t nType );
+    void ResetCurrentLook();
+
+    void SetCurrentBodyColor( uint8_t nHeadColor, uint8_t nTorsoColor, uint8_t nLegsColor, uint8_t nHeadDarkness = 0, uint8_t nTorsoDarkness = 0, uint8_t nLegsDarkness = 0 );
+    inline void SetBodyEffect( uint8_t nEffect, uint8_t nDensity = 0 ) { mBodyEffect = nEffect; mBodyEffectDensity = nDensity; }
+    inline void SetSpeedOverride( uint8_t nSpeed = 255 ) { mSpeedOverride = nSpeed; }
+
+    void SetLookingAt( uint16_t nLocalCharID );
+    uint16_t GetLookingAt( uint16_t nMaxDelaySec = 1 );
+    inline void SetLastUsedObject ( uint32_t nRawItemId ) { mLastUsedWorldObjectId = nRawItemId; }
+    inline uint32_t GetLastUsedObject () const { return mLastUsedWorldObjectId; }
+
+    inline PInventory* GetInventory() { return &mInventory; }
+    inline uint32_t GetID() const { return mID; }
+    inline uint32_t GetAccount() const { return mAccount; }
+    inline const std::string &GetName() const { return mName; }
+    inline uint32_t GetGender() const { return mGender; }
+    inline uint32_t GetClass() const { return mClass; }
+    inline uint32_t GetType() const { return 2 * mClass + mGender; }
+    uint32_t GetSkinFromCharType( uint32_t nType );
+    void GetRealLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs );
+    void GetCurrentLook( uint32_t &nSkin, uint32_t &nHead, uint32_t &nTorso, uint32_t &nLegs );
+    inline void GetBodyEffect( uint8_t &nEffect, uint8_t &nDensity ) { nEffect = mBodyEffect; nDensity = mBodyEffectDensity; }
+
+    inline uint8_t GetQuickBeltActiveSlot() { return mQuickBeltActiveSlot; }
+    bool SetQuickBeltActiveSlot( uint8_t nSlotID );
+
+    void GetCurrentBodyColor( uint8_t &nHeadColor, uint8_t &nTorsoColor, uint8_t &nLegsColor, uint8_t &nHeadDarkness, uint8_t &nTorsoDarkness, uint8_t &nLegsDarkness );
+    inline uint8_t GetSpeedOverride() { return mSpeedOverride; }
+    inline uint32_t GetBaseModel();
+    inline uint32_t GetProfession() const { return mProfession; }
+    inline uint16_t GetMaxHealth() { return mHealth; }
+    inline uint16_t GetMaxMana() { return mMana; }
+    inline uint16_t GetMaxStamina() { return mStamina; }
+    inline uint16_t GetHealth() { return mHealth; }
+    inline uint16_t GetMana() { return mMana; }
+    inline uint16_t GetStamina() { return mStamina; }
+    inline uint32_t GetFaction() const { return mFaction; }
+    inline uint32_t GetLocation() const { return mLocation; }
+
+    inline uint32_t GetCash() const { return mCash; }
+    uint32_t SetCash( uint32_t nCash );  // Does return the new cashvalue, NO udpmessage is sent out!!
+    uint32_t AddCash( uint32_t nAmount );
+    uint32_t TakeCash( uint32_t nAmount );
+
+    inline uint32_t GetBaseApartment() const { return mPrimaryApt; }
+
+    inline void SetJail( bool val ) { mJailed = val; };
+    inline void SetShun( bool val ) { mShunned = val; };
+
+    inline bool IsJailed() { return mJailed; };
+    inline bool IsShunned() { return mShunned; };
+
+    inline void SetDialogNPC( uint32_t nNPC ) { mDialogNPC = nNPC; };
+    inline uint32_t GetDialogNPC() const { return mDialogNPC; };
+
+    inline void SetDialogNode( uint16_t nNode ) { mCurrentDialogNode = nNode; };
+    inline uint16_t GetDialogNode() const { return mCurrentDialogNode; };
+
+    inline uint8_t GetClanLevel() const { return mClanLevel; };
+    inline uint16_t GetClan() const { return mClanID; };
+    void LoadClanLevel();
+
+    inline int8_t GetSoullight() const { return mSoullight; }
+    uint8_t GetMainRank();
+    uint8_t GetCombatRank();
+    inline uint8_t GetSynaptic() const { return mSynaptic; }
+    inline bool IsDead() const { return mIsDead; }
+
+    inline bool SetDirectChat( uint32_t nBuddyCharID ) { mDirectCharID = nBuddyCharID; return true; }
+    inline uint32_t GetDirectChat() { return mDirectCharID; }
+    inline void SetActiveChannels( uint32_t nChannels ) { mActiveChatChannels = nChannels; }
+    inline uint32_t GetActiveChannels() { return mActiveChatChannels; }
+
+    inline bool AddBuddy( uint32_t nBuddyCharID ) { return mBuddyList->AddChar( nBuddyCharID ); }
+    inline bool RemoveBuddy( uint32_t nBuddyCharID ) { return mBuddyList->RemoveChar( nBuddyCharID ); }
+    inline uint16_t GetBuddyListDataSize() { return mBuddyList->GetListDataSize(); }
+    inline const void* GetBuddyListData() { return mBuddyList->GetListData(); }
+    inline uint8_t GetBuddyCount() { return mBuddyList->Count(); }
+    inline bool IsBuddy( uint32_t CharID ) { return mBuddyList->IsInBuddy( CharID ); };
+
+    bool AddGenrep(uint16_t nWorldID, uint16_t nStationID);
+    uint16_t GetGenrepListDataSize();
+    const void *GetGenrepListData();
+    uint8_t GetGenrepCount();
+
+    inline bool IsDirty() const { return mDirtyFlag; }
+    inline bool IsAnyDirty() const { return mDirtyFlag || mInventory.IsDirty(); }
+    inline bool IsOnline() { return mIsOnline; }
+    void SetOnlineStatus( bool IsOnline );
+
+    bool CreateNewChar( uint32_t Account, const std::string &Name, uint32_t Gender, uint32_t Profession, uint32_t Faction,
+                        uint32_t Head, uint32_t Torso, uint32_t Legs, uint8_t NZSNb, const char *NonZeroSubskills, uint32_t Slot );
+    bool SQLLoad( int CharID );
+    bool SQLSave();
+    inline bool SQLSaveFull() { return SQLSave() && mInventory.SQLSave(); }
+    bool SQLDelete(); // not implemented yet
+
+    inline void SetLocation( uint32_t Location ) { mLocation = Location; }
+    inline void SetDirtyFlag( bool Dirty = true ) { mDirtyFlag = Dirty; }
+
+    // temp until char on-demand load/unload
+    inline void SetLocationLeased( bool nState = true ) { mLocationLeased = nState; }
+    inline bool GetLocationLeased() { return mLocationLeased; }
+
+    PSeatType GetSeatInUse( uint32_t* nObjectId = NULL, uint8_t* nSeatId = NULL );
+    void SetSeatInUse( PSeatType nSeatType, uint32_t nObjectId = 0, uint8_t nSeatId = 0 );
+
+    PVhcAccessRequestList* GetVhcAccessRequestList();
+
+    inline PContainer* GetContainerInExclusiveUse() { return mContainerInExclusiveUse; }
+    inline void SetContainerInExclusiveUse( PContainer* nContainer ) { mContainerInExclusiveUse = nContainer; }
+};
+
+struct PCharProfile
+{
+  uint32_t CharID;
+  uint16_t Type;
+  uint16_t Color0;
+  uint16_t Unknown1;
+  uint8_t Head;
+  uint8_t Torso;
+  uint8_t Legs;
+  uint32_t Location;
+  uint8_t NameLen;
+  uint8_t Unknown3;
+  uint8_t Unknown4;
+  uint8_t Unknown5;
+  uint8_t Unknown6;
+  uint8_t Unknown7;
+  uint8_t Unknown8;
+  uint8_t Unknown9;
+  uint8_t Unknown10;
+  uint8_t Unknown11;
+  uint8_t Unknown12;
+  std::string Name;
+  bool in_use;
+};
+
+class PChars
+{
+  private :
+    typedef std::map<uint32_t, PChar*> CharMap;
+    CharMap mChars;
+    uint32_t mLastID;
+
+    std::time_t mAutoSavePeriod;
+    std::time_t mLastSave;
+
+  public :
+    PChars();
+    ~PChars();
+
+    bool LoadChar( uint32_t CharID );
+    bool AddChar( PChar* nChar );
+    PChar* RemoveChar( uint32_t CharID );
+
+    PChar* GetChar( uint32_t CharID ) const;
+    PChar* GetChar( const std::string &Name ) const;
+    bool CharExist( const std::string &Name ) const;
+
+    void SQLSave();
+    void Update();
+
+    int GetCharProfiles( const uint32_t AccountID, PCharProfile* CharSlotsArray, const uint8_t ArraySize ); // return effective entries nb
+};
index 9be8592..dfdd1d9 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-//  TODO:- Add "hooks" to process chatevents everywhere in the source <-- kind of done. you can use the global PChat Instance.\r
-//         Check:\r
-//              Chat->send(PClient* receiver, const uint8_t* Channel, const char* AuthorNickName, char* text, bool debugOut=false);\r
-//         Example:\r
-//              Chat->send(receiverClient, CHAT_DIRECT, Chars->GetChar(authorClient->GetCharID())->GetName().c_str(), text);\r
-\r
-PChat::PChat()\r
-{\r
-}\r
-\r
-PChat::~PChat()\r
-{\r
-}\r
-\r
-/*\r
-DONE    void sendBuddy(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendLocal(PClient* author, char* text, bool debugOut=false);\r
-NEED CLANDATA    void sendClan(PClient* author, char* text, bool debugOut=false);\r
-NEED TEAMDATA    void sendTeam(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendDirect(PClient* author, PClient* receiver, char* text, bool debugOut=false);\r
-DONE    void sendZone(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendFrak(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTradeCS(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTradeMB(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTradeNC(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTradeTH(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTradeWL(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendOOC(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendHelp(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendClanSearch(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendServicesCS(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendServicesMB(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendServicesNC(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendServicesTH(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendServicesWL(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTeam10(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTeam30(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTeam50(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendTeam70(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendAdmin(PClient* author, char* text, bool debugOut=false);\r
-DONE    void sendGM(PClient* author, char* text, bool debugOut=false);\r
-*/\r
-\r
-\r
-void PChat::sendBuddy(PClient* author, const char* text, bool debugOut)\r
-{\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-    // send the message to all Buddys in list\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second && authorChar->IsBuddy(it->second->GetCharID()) == true)\r
-        {\r
-            PClient* receiver = it->second;\r
-            //Console->Print("DEBUG: Buddychat - Sending msg to %s", Chars->GetChar(receiver->GetCharID())->GetName().c_str());\r
-            send(receiver, CHAT_BUDDY, authorChar->GetName().c_str(), text, debugOut);\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendConnectedList(PClient* receiver, bool debugOut)\r
-{\r
-    const char* text = "Connected Players are:]";\r
-    send(receiver, CHAT_DIRECT, "[System", text, debugOut);\r
-\r
-    int counter = 1;\r
-\r
-    // send the list of currently connected players to receiver\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-          char counterText[5];\r
-          snprintf(counterText, 5, "%d", counter);\r
-\r
-        PChar* receiverChar = Chars->GetChar(it->second->GetCharID());\r
-        send(receiver, CHAT_DIRECT, (receiverChar ? receiverChar->GetName().c_str() : "*"), counterText, debugOut);\r
-\r
-        counter++;\r
-    }\r
-}\r
-\r
-\r
-void PChat::sendFrak(PClient* author, const char* text, bool debugOut)\r
-{\r
-    // send the message to all clients that have same FactionID\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-    uint32_t FID = authorChar->GetFaction(); // get LocationID of author\r
-\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            PClient* receiver = it->second;\r
-            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());\r
-            if(receiverChar && (receiverChar->GetFaction() == FID))\r
-            {\r
-                if(chanEnabled(receiver, C_FRAK) == true)\r
-                    send(receiver, CHAT_FRAK, authorChar->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendZone(PClient* author, const char* text, bool debugOut)\r
-{\r
-    // send the message to all clients that have same ZoneID\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-    uint32_t ZID = authorChar->GetLocation(); // get LocationID of author\r
-\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            PClient* receiver = it->second;\r
-            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());\r
-            if(receiverChar && (receiverChar->GetLocation() == ZID))\r
-            {\r
-                if(chanEnabled(receiver, C_ZONE) == true)\r
-                    send(receiver, CHAT_ZONE, authorChar->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendLocal(PClient* author, const char* text, bool debugOut)\r
-{\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-    uint32_t ZID = authorChar->GetLocation(); // get LocationID of author\r
-\r
-    // send the message to all clients that are in Area (Radius = X (needs to be defined somewhere!))\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            PClient* receiver = it->second;\r
-            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());\r
-            if(receiverChar && (receiverChar->GetLocation() == ZID))\r
-            {\r
-                uint16_t distance = DistanceApprox((authorChar->Coords).mX, (authorChar->Coords).mY, (authorChar->Coords).mZ, (receiverChar->Coords).mX, (receiverChar->Coords).mY, (receiverChar->Coords).mZ);\r
-                if(distance < LOCALCHAT_MAXDISTANCE)\r
-                {\r
-                    //sendLocalchat(receiver, author, text, debugOut); // Doesnt work!\r
-                    send(receiver, CHAT_LOCAL, authorChar->GetName().c_str(), text, debugOut);\r
-                }\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendGM(PClient* author, const char* text, bool debugOut)\r
-{\r
-    if(author->GetAccountLevel() >= PAL_GM) // Only send GM> chat when user is an Gamemaster or higher\r
-    {\r
-        // send the message to all GameMasters.\r
-        for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-        {\r
-            if(author != it->second) // if its not the client, that send the message to the server\r
-            {\r
-                if(it->second) // only send if the client is existing!\r
-                {\r
-                    PClient* receiver = it->second;\r
-                    if(receiver->GetAccountLevel() >= PAL_GM) // Only send GM chat if RECEIVER is GM or higher\r
-                        send(receiver, CHAT_GM, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-                }\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendGMAdmin(PClient* author, const char* text, bool debugOut)\r
-{\r
-    if(author->GetAccountLevel() >= PAL_GM) // Only send GM> chat when user is an Gamemaster or higher\r
-    {\r
-        // send the message to ALL users online\r
-        for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-        {\r
-            if(author != it->second) // if its not the client, that send the message to the server\r
-            {\r
-                if(it->second) // only send if the client is existing!\r
-                {\r
-                    PClient* receiver = it->second;\r
-                    send(receiver, CHAT_GMADMIN, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-                }\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendAdmin(PClient* author, const char* text, bool debugOut)\r
-{\r
-    if(author->GetAccountLevel() >= PAL_ADMIN) // Only send ADMIN> chat when user is an serveradmin\r
-    {\r
-        // send the message to ALL users online\r
-        for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-        {\r
-            if(author != it->second) // if its not the client, that send the message to the server\r
-            {\r
-                if(it->second) // only send if the client is existing!\r
-                {\r
-                    PClient* receiver = it->second;\r
-                    send(receiver, CHAT_ADMIN, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-                }\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendBroadcast(const char* text, bool debugOut)\r
-{\r
-    // send the message to ALL users online\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(it->second) // only send if the client is existing!\r
-        {\r
-            PClient* receiver = it->second;\r
-            send(receiver, CHAT_ADMIN, "Server", text, debugOut);\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendOOCBroadcast(const char* text, bool debugOut)\r
-{\r
-    // send the message to ALL users online\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(it->second) // only send if the client is existing!\r
-        {\r
-            PClient* receiver = it->second;\r
-            if(chanEnabled(receiver, C_OOC) == true)\r
-                send(receiver, CHAT_OOC, "Server", text, debugOut);\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendClan(PClient* author, const char* text, bool debugOut)\r
-{\r
-    /**\r
-        NOT ABLE TO IMPLEMENT THIS CHATTYPE YET, ITS SUPERGLOBAL TILL THEN\r
-    **/\r
-    // send the message to all clients that have same ClanID\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-\r
-//    int ClanID = authorChar->getClanID(); // get clanID of author\r
-\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second)\r
-        {\r
-            PClient* receiver = it->second;\r
-            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());\r
-            if(receiverChar /*&& (receiverChar->getClanID() == ClanID)*/)\r
-            {\r
-                send(receiver, CHAT_CLAN, authorChar->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-\r
-}\r
-\r
-void PChat::sendTeam(PClient* author, const char* text, bool debugOut)\r
-{\r
-    /**\r
-        NOT ABLE TO IMPLEMENT THIS CHATTYPE YET, ITS SUPERGLOBAL TILL THEN\r
-    **/\r
-    // send the message to all clients that have same TeamID\r
-\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-\r
-    //int TeamID = authorChar->getTeamID(); // get TeamID of author\r
-\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second)\r
-        {\r
-            PClient* receiver = it->second;\r
-            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());\r
-            if(receiverChar /*&& (receiverChar->getTeamID() == TeamID)*/)\r
-            {\r
-                send(receiver, CHAT_TEAM, authorChar->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendPlayerDirect(PClient* author, const char* text, uint32_t destination, bool debugOut)\r
-{\r
-    bool tmpTargetOnline = false;\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        PClient* receiver = it->second;\r
-        PChar* receiverChar = Chars->GetChar(receiver->GetCharID());\r
-        if(receiverChar && (receiver->GetCharID() == destination))       \r
-        {\r
-            tmpTargetOnline = true;\r
-            sendDirect(author, receiver, text, debugOut);\r
-        }\r
-    }\r
-    if(tmpTargetOnline == false)\r
-    {\r
-        ConnectionTCP *Socket = author->getTCPConn();\r
-        uint8_t DirectTargetNotOnline[] = {0xFE, 0x07, 0x00, 0x83, 0x18, 0x01, 0x81, 0x54, 0x00, 0x00};\r
-\r
-        Socket->write(DirectTargetNotOnline, sizeof(DirectTargetNotOnline));\r
-        Socket->flushSendBuffer();\r
-    }\r
-\r
-    if(debugOut == true)\r
-    {\r
-        if(tmpTargetOnline == false)\r
-            Console->Print("[DEBUG] Requested target CharID %d is not online", destination);\r
-        else\r
-            Console->Print("[DEBUG] CharID %d found and message transmitted!", destination);\r
-    }\r
-}\r
-\r
-void PChat::sendDirect(PClient* author, PClient* receiver, const char* text, bool debugOut)\r
-{\r
-    PChar* authorChar = Chars->GetChar(author->GetCharID());\r
-\r
-    char *DChatPacket;\r
-    unsigned int packetsize = 0, c;\r
-    int LenText, LenNick, fpp, d, e, loopout;\r
-\r
-    ConnectionTCP *Socket = receiver->getTCPConn();\r
-\r
-    uint8_t BasicDirectPacket[] = {0xFE, 0x20, 0x00, 0x83, 0x17, 0xB7, 0x5F, 0x00, 0x00, 0x0C, 0x04, 0x00};\r
-\r
-    LenText = LenNick = fpp = 0;\r
-\r
-    do {\r
-      LenText++;\r
-    } while(text[LenText] != '\0');\r
-\r
-    do {\r
-      LenNick++;\r
-    } while(authorChar->GetName().c_str()[LenNick] != '\0');\r
-\r
-    loopout = 0;\r
-\r
-    packetsize = sizeof(BasicDirectPacket) + LenText + LenNick;\r
-\r
-    if(debugOut == true) {\r
-       Console->Print("Sizeof(TextToSend): %d || Sizeof(Nick): %d", LenText, LenNick);\r
-       Console->Print("Whole size: %d", packetsize);\r
-    }\r
-\r
-    DChatPacket = new char [packetsize];\r
-\r
-    // Copy basic packet into final packet\r
-    for(c=0;c<sizeof(BasicDirectPacket);c++) {\r
-       DChatPacket[fpp] = BasicDirectPacket[c];\r
-       fpp++;\r
-    }\r
-\r
-    // Copy Nickname into final packet\r
-    for(d=0;d<LenNick;d++) {\r
-       DChatPacket[fpp] = authorChar->GetName().c_str()[d];\r
-       fpp++;\r
-    }\r
-\r
-    // Copy Text into final packet\r
-    for(e=0;e<LenText;e++) {\r
-       DChatPacket[fpp] = text[e];\r
-       fpp++;\r
-    }\r
-\r
-    // Change Lenght bytes in final packet\r
-    DChatPacket[1] = packetsize - 3;\r
-    DChatPacket[9] = LenNick;\r
-\r
-    if(debugOut == true) {\r
-        unsigned int debugout;\r
-        for(debugout=0;debugout<packetsize;debugout++) {\r
-           Console->Print("Byte %d: %#x", debugout, DChatPacket[debugout]);\r
-        }\r
-    }\r
-\r
-    // Sending direct chat packet and removing dynamic array\r
-    Socket->write(DChatPacket, packetsize);\r
-    Socket->flushSendBuffer();\r
-    delete[] DChatPacket;\r
-}\r
-\r
-void PChat::sendLocalchat(PClient* receiver, PClient* author, const char* text, bool debugOut)\r
-{\r
-    return; // IncreaseUDP could cause OOO here. Since this function is doing nothing, we disabled it\r
-    char *LocalChatPacket;\r
-    int overallsize = 0, LenText = 0;\r
-    uint8_t BasicLocal[] = { 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1B };\r
-\r
-    // Get size of Text to send\r
-    do {\r
-      LenText++;\r
-    } while(text[LenText] != '\0');\r
-\r
-    // Calculate packetsize\r
-    overallsize = sizeof(BasicLocal) + LenText + 1;\r
-\r
-    if(debugOut == true)\r
-       Console->Print("Whole size: %d", overallsize);\r
-\r
-    LocalChatPacket = new char [overallsize];\r
-\r
-    // Copy basic packet into final packet\r
-    int fpp = 0;\r
-    for(unsigned int c = 0; c < sizeof(BasicLocal); c++) {\r
-       LocalChatPacket[fpp] = BasicLocal[c];\r
-       fpp++;\r
-    }\r
-\r
-    // Copy Text into final packet\r
-    for(int e = 0; e < LenText; e++) {\r
-       LocalChatPacket[fpp] = text[e];\r
-       fpp++;\r
-    }\r
-\r
-    // Terminate string\r
-    LocalChatPacket[fpp] = 0x00;\r
-\r
-    // Add UdpID, SessionID, lenght and local charid\r
-    receiver->IncreaseUDP_ID();\r
-    *(uint16_t*)&LocalChatPacket[1] = receiver->GetUDP_ID();     // UDP\r
-    *(uint16_t*)&LocalChatPacket[3] = receiver->GetSessionID();  // Session\r
-    *(uint8_t*)&LocalChatPacket[5] = overallsize - 6;            // Packetlen\r
-    *(uint16_t*)&LocalChatPacket[7] = receiver->GetUDP_ID();     // 2nd UDP\r
-    *(uint16_t*)&LocalChatPacket[10] = author->GetLocalID();     // Local ID\r
-\r
-    // Sending local chat packet and removing dynamic array\r
-    ConnectionUDP *Socket = receiver->getUDPConn();\r
-    Socket->write(LocalChatPacket, overallsize);\r
-    Socket->flushSendBuffer();\r
-    delete[] LocalChatPacket;\r
-}\r
-\r
-void PChat::sendTradeCS(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TRADECS) == true)\r
-                    send(receiver, CHAT_TRADECS, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTradeMB(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TRADEMB) == true)\r
-                    send(receiver, CHAT_TRADEMB, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTradeNC(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TRADENC) == true)\r
-                    send(receiver, CHAT_TRADENC, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTradeTH(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TRADETH) == true)\r
-                    send(receiver, CHAT_TRADETH, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTradeWL(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TRADEWL) == true)\r
-                    send(receiver, CHAT_TRADEWL, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendOOC(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_OOC) == true)\r
-                    send(receiver, CHAT_OOC, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendHelp(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_HELP) == true)\r
-                    send(receiver, CHAT_HELP, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendClanSearch(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_CLANSEARCH) == true)\r
-                    send(receiver, CHAT_CLANSEARCH, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendServicesCS(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_SERVICECS) == true)\r
-                    send(receiver, CHAT_SERVICECS, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendServicesMB(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_SERVICEMB) == true)\r
-                    send(receiver, CHAT_SERVICESMB, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendServicesNC(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_SERVICENC) == true)\r
-                    send(receiver, CHAT_SERVICESNC, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendServicesTH(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_SERVICETH) == true)\r
-                    send(receiver, CHAT_SERVICESTH, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendServicesWL(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_SERVICEWL) == true)\r
-                    send(receiver, CHAT_SERVICESWL, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTeam10(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TEAM10) == true)\r
-                    send(receiver, CHAT_TEAM10, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTeam30(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TEAM30) == true)\r
-                    send(receiver, CHAT_TEAM30, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTeam50(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TEAM50) == true)\r
-                    send(receiver, CHAT_TEAM50, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PChat::sendTeam70(PClient* author, const char* text, bool debugOut)\r
-{\r
-    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)\r
-    {\r
-        if(author != it->second) // if its not the client, that send the message to the server\r
-        {\r
-            if(it->second) // only send if the client is existing!\r
-            {\r
-                PClient* receiver = it->second;\r
-                if(chanEnabled(receiver, C_TEAM70) == true)\r
-                    send(receiver, CHAT_TEAM70, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-bool PChat::chanEnabled(PClient* Client, uint32_t channel)\r
-{\r
-    // Check if player has target channel enabled or disabled\r
-    PChar* TargetChar = Chars->GetChar(Client->GetCharID());\r
-    if(!TargetChar)\r
-      return false;\r
-      \r
-    uint32_t actChans = TargetChar->GetActiveChannels();\r
-    uint32_t check = actChans & channel;\r
-\r
-    if(check == channel)\r
-        return true;\r
-    else\r
-        return false;\r
-}\r
-\r
-bool PChat::send(PClient* receiver, const uint8_t* Channel, const char* AuthorNickName, const char* text, bool debugOut)\r
-{\r
-    char *ChatPacket;\r
-    unsigned int packetsize = 0, c;\r
-    int LenText, LenNick, fpp, d, e, loopout;\r
-    uint8_t TargetChannel[2];\r
-\r
-//Console->Print("1: %#x", Channel[0]);\r
-//Console->Print("2: %#x", CHAT_BUDDY[0]);\r
-\r
-\r
-      if(cmpr(Channel, CHAT_BUDDY) == true) {\r
-           TargetChannel[0] = CHAT_BUDDY[0];\r
-           TargetChannel[1] = CHAT_BUDDY[1];\r
-      } else if(cmpr(Channel, CHAT_LOCAL) == true) {\r
-           TargetChannel[0] = CHAT_LOCAL[0];\r
-           TargetChannel[1] = CHAT_LOCAL[1];\r
-      } else if(cmpr(Channel, CHAT_CLAN) == true) {\r
-           TargetChannel[0] = CHAT_CLAN[0];\r
-           TargetChannel[1] = CHAT_CLAN[1];\r
-      } else if(cmpr(Channel, CHAT_TEAM) == true) {\r
-           TargetChannel[0] = CHAT_TEAM[0];\r
-           TargetChannel[1] = CHAT_TEAM[1];\r
-      } else if(cmpr(Channel, CHAT_DIRECT) == true) {\r
-           TargetChannel[0] = CHAT_DIRECT[0];\r
-           TargetChannel[1] = CHAT_DIRECT[1];\r
-      } else if(cmpr(Channel, CHAT_ZONE) == true) {\r
-           TargetChannel[0] = CHAT_ZONE[0];\r
-           TargetChannel[1] = CHAT_ZONE[1];\r
-      } else if(cmpr(Channel, CHAT_FRAK) == true) {\r
-           TargetChannel[0] = CHAT_FRAK[0];\r
-           TargetChannel[1] = CHAT_FRAK[1];\r
-      } else if(cmpr(Channel, CHAT_TRADECS) == true) {\r
-           TargetChannel[0] = CHAT_TRADECS[0];\r
-           TargetChannel[1] = CHAT_TRADECS[1];\r
-      } else if(cmpr(Channel, CHAT_TRADEMB) == true) {\r
-           TargetChannel[0] = CHAT_TRADEMB[0];\r
-           TargetChannel[1] = CHAT_TRADEMB[1];\r
-      } else if(cmpr(Channel, CHAT_TRADENC) == true) {\r
-           TargetChannel[0] = CHAT_TRADENC[0];\r
-           TargetChannel[1] = CHAT_TRADENC[1];\r
-      } else if(cmpr(Channel, CHAT_TRADETH) == true) {\r
-           TargetChannel[0] = CHAT_TRADETH[0];\r
-           TargetChannel[1] = CHAT_TRADETH[1];\r
-      } else if(cmpr(Channel, CHAT_TRADEWL) == true) {\r
-           TargetChannel[0] = CHAT_TRADEWL[0];\r
-           TargetChannel[1] = CHAT_TRADEWL[1];\r
-      } else if(cmpr(Channel, CHAT_OOC) == true) {\r
-           TargetChannel[0] = CHAT_OOC[0];\r
-           TargetChannel[1] = CHAT_OOC[1];\r
-      } else if(cmpr(Channel, CHAT_HELP) == true) {\r
-           TargetChannel[0] = CHAT_HELP[0];\r
-           TargetChannel[1] = CHAT_HELP[1];\r
-      } else if(cmpr(Channel, CHAT_CLANSEARCH) == true) {\r
-           TargetChannel[0] = CHAT_CLANSEARCH[0];\r
-           TargetChannel[1] = CHAT_CLANSEARCH[1];\r
-      } else if(cmpr(Channel, CHAT_SERVICECS) == true) {\r
-           TargetChannel[0] = CHAT_SERVICECS[0];\r
-           TargetChannel[1] = CHAT_SERVICECS[1];\r
-      } else if(cmpr(Channel, CHAT_SERVICESMB) == true) {\r
-           TargetChannel[0] = CHAT_SERVICESMB[0];\r
-           TargetChannel[1] = CHAT_SERVICESMB[1];\r
-      } else if(cmpr(Channel, CHAT_SERVICESNC) == true) {\r
-           TargetChannel[0] = CHAT_SERVICESNC[0];\r
-           TargetChannel[1] = CHAT_SERVICESNC[1];\r
-      } else if(cmpr(Channel, CHAT_SERVICESTH) == true) {\r
-           TargetChannel[0] = CHAT_SERVICESTH[0];\r
-           TargetChannel[1] = CHAT_SERVICESTH[1];\r
-      } else if(cmpr(Channel, CHAT_SERVICESWL) == true) {\r
-           TargetChannel[0] = CHAT_SERVICESWL[0];\r
-           TargetChannel[1] = CHAT_SERVICESWL[1];\r
-      } else if(cmpr(Channel, CHAT_TEAM10) == true) {\r
-           TargetChannel[0] = CHAT_TEAM10[0];\r
-           TargetChannel[1] = CHAT_TEAM10[1];\r
-      } else if(cmpr(Channel, CHAT_TEAM30) == true) {\r
-           TargetChannel[0] = CHAT_TEAM30[0];\r
-           TargetChannel[1] = CHAT_TEAM30[1];\r
-      } else if(cmpr(Channel, CHAT_TEAM50) == true) {\r
-           TargetChannel[0] = CHAT_TEAM50[0];\r
-           TargetChannel[1] = CHAT_TEAM50[1];\r
-      } else if(cmpr(Channel, CHAT_TEAM70) == true) {\r
-           TargetChannel[0] = CHAT_TEAM70[0];\r
-           TargetChannel[1] = CHAT_TEAM70[1];\r
-      } else if(cmpr(Channel, CHAT_ADMIN) == true) {\r
-           TargetChannel[0] = CHAT_ADMIN[0];\r
-           TargetChannel[1] = CHAT_ADMIN[1];\r
-      } else if(cmpr(Channel, CHAT_GMADMIN) == true) {\r
-           TargetChannel[0] = CHAT_GMADMIN[0];\r
-           TargetChannel[1] = CHAT_GMADMIN[1];\r
-      } else if(cmpr(Channel, CHAT_GM) == true) {\r
-           TargetChannel[0] = CHAT_GM[0];\r
-           TargetChannel[1] = CHAT_GM[1];\r
-      } else {\r
-         Console->Print("SendChat error: Channel %#x unknown", Channel);\r
-         return false;\r
-      }\r
-\r
-    ConnectionTCP *Socket = receiver->getTCPConn();\r
-\r
-    uint8_t BasicChatPacket[] = {0xFE, 0x15, 0x00, 0x83, 0x17, 0x90, 0x03, 0x00, 0x00, 0x07, 0x05, 0x0F};\r
-\r
-    LenText = LenNick = fpp = 0;\r
-\r
-    do {\r
-      LenText++;\r
-    } while(text[LenText] != '\0');\r
-\r
-    do {\r
-      LenNick++;\r
-    } while(AuthorNickName[LenNick] != '\0');\r
-\r
-    if(LenText == 0 || LenNick == 0) {\r
-       Console->Print("Error in SendChat, nickname or text is missing");\r
-       return false;\r
-    }\r
-\r
-    loopout = 0;\r
-\r
-    packetsize = sizeof(BasicChatPacket) + LenText + LenNick;\r
-\r
-    if(debugOut == true) {\r
-       Console->Print("Sizeof(TextToSend): %d || Sizeof(Nick): %d", LenText, LenNick);\r
-       Console->Print("Whole size: %d", packetsize);\r
-    }\r
-\r
-    ChatPacket = new char [packetsize];\r
-\r
-    // Copy basic packet into final packet\r
-    for(c=0;c<sizeof(BasicChatPacket);c++) {\r
-       ChatPacket[fpp] = BasicChatPacket[c];\r
-       fpp++;\r
-    }\r
-\r
-    // Copy Nickname into final packet\r
-    for(d=0;d<LenNick;d++) {\r
-       ChatPacket[fpp] = AuthorNickName[d];\r
-       fpp++;\r
-    }\r
-\r
-    // Copy Text into final packet\r
-    for(e=0;e<LenText;e++) {\r
-       ChatPacket[fpp] = text[e];\r
-       fpp++;\r
-    }\r
-\r
-    // Change Lenght bytes in final packet\r
-    ChatPacket[1] = packetsize - 3;\r
-    ChatPacket[9] = LenNick;\r
-    ChatPacket[10] = TargetChannel[0];\r
-    ChatPacket[11] = TargetChannel[1];\r
-\r
-    if(debugOut == true) {\r
-        unsigned int debugout;\r
-        for(debugout=0;debugout<packetsize;debugout++) {\r
-           Console->Print("Byte %d: %#x", debugout, ChatPacket[debugout]);\r
-        }\r
-    }\r
-\r
-    // Sending direct chat packet and removing dynamic array\r
-    Socket->write(ChatPacket, packetsize);\r
-    Socket->flushSendBuffer();\r
-    delete[] ChatPacket;\r
-\r
-    return true;\r
-}\r
-\r
-\r
-\r
-bool PChat::HandleGameChat(PClient *Client, const uint8_t *Packet)\r
-{\r
-    // if player is shunned, ignore all incomming chat and game commands.\r
-    // ServerAdmins are not affected by any shuns. (Should never happen anyways...)\r
-    if((Client->GetChar()->IsShunned() == true) && (Client->GetAccountLevel() < PAL_ADMIN)) return true;\r
-\r
-    int i, j, k;\r
-\r
-     uint8_t chattype = *(uint8_t*)&Packet[7];\r
-// -----------------------------------------------\r
-    if(chattype == 0x1B) {\r
-      // Local chat\r
-      i = 8;\r
-      j = 0;\r
-\r
-      char ChatText[255];\r
-\r
-      do {\r
-         ChatText[j] = Packet[i];\r
-         i++;\r
-         j++;\r
-      } while (ChatText[j-1] != 0x00);\r
-\r
-      ChatText[j] = '\0';\r
-      if(ChatText[0] == '@' && sizeof(ChatText) > 2) {\r
-            GameCommands->HandleGameCommand(ChatText, Client);\r
-      } else {\r
-          // We know its working, so we dont need console output anymore\r
-            //Console->Print("Local Chat: %s", ChatText);\r
-            //Console->Print("Client CharName is: %s", Chars->GetChar(Client->GetCharID())->GetName().c_str());\r
-            sendLocal(Client, ChatText, false);\r
-      }\r
-\r
-// -----------------------------------------------\r
-   } else if (chattype == 0x3B) {\r
-      // Non-Local chat\r
-      i = 13;\r
-      j = 0;\r
-      k = 0;\r
-\r
-      char ChatText[255];\r
-\r
-      do {\r
-         ChatText[j] = Packet[i];\r
-         i++;\r
-         j++;\r
-      } while (ChatText[j-1] != 0x00);\r
-\r
-\r
-      ChatText[j] = '\0';\r
-      if(ChatText[0] == '@' && sizeof(ChatText) > 2) {\r
-            GameCommands->HandleGameCommand(ChatText, Client);\r
-      } else {\r
-        //      Console->Print("CHATLINE: %s HEX: %#X", ChatText, Packet[i-1]);\r
-        char Channel[4];\r
-\r
-        for(k = 0; k <= 3; k ++) {\r
-           Channel[k] = Packet[k+8];\r
-        }\r
-  //    Console->Print("Channel no %#x %#x %#x %#x", Channel[0], Channel[1], Channel[2], Channel[3]);\r
-\r
-        // First, check if packet is a direct-chat-packet\r
-        if(*(uint8_t*)&Packet[8] == 0x04) {\r
-             //Console->Print("Direct Chat: %s", ChatText);\r
-             sendPlayerDirect(Client, ChatText, *(uint32_t*)&Packet[9], false);\r
-             //sendDirect(Client, ChatText, false);\r
-             // "DIRECT> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_BUDDY) {\r
-             //Console->Print("Buddy Chat: %s", ChatText);\r
-             sendBuddy(Client, ChatText, false);\r
-             // "BUDDY> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CLAN) {\r
-             //Console->Print("Clan Chat: %s", ChatText);\r
-             sendClan(Client, ChatText, false);\r
-             // "CLAN> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_TEAM) {\r
-             //Console->Print("Team Chat: %s", ChatText);\r
-             sendTeam(Client, ChatText, false);\r
-             // "TEAM> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_ZONE) {\r
-             //Console->Print("Custom - Zone Chat: %s", ChatText);\r
-             sendZone(Client, ChatText, false);\r
-             // "ZONE> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_FRAKTION) {\r
-             //Console->Print("Custom - Fraktion Chat: %s", ChatText);\r
-             sendFrak(Client, ChatText, false);\r
-             // "FRACTION> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_CANYON) {\r
-             //Console->Print("Custom - Trade_Canyon Chat: %s", ChatText);\r
-             sendTradeCS(Client, ChatText, false);\r
-             // "TRADE - CS> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_MB) {\r
-             //Console->Print("Custom - Trade_MB Chat: %s", ChatText);\r
-             sendTradeMB(Client, ChatText, false);\r
-             // "TRADE - MB> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_NC) {\r
-             //Console->Print("Custom - Trade_NC Chat: %s", ChatText);\r
-             sendTradeNC(Client, ChatText, false);\r
-             // "TRADE - NC> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_TH) {\r
-             //Console->Print("Custom - Trade_TH Chat: %s", ChatText);\r
-             sendTradeTH(Client, ChatText, false);\r
-             // "TRADE - TH> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_WASTE) {\r
-             //Console->Print("Custom - Trade_Waste Chat: %s", ChatText);\r
-             sendTradeWL(Client, ChatText, false);\r
-             // "TRADE - WL> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_OOC) {\r
-             //Console->Print("Custom - OOC Chat: %s", ChatText);\r
-             sendOOC(Client, ChatText, false);\r
-             // "OOC> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_PLAYERHELP) {\r
-             //Console->Print("Custom - PlayerToPlayerhelp Chat: %s", ChatText);\r
-             sendHelp(Client, ChatText, false);\r
-             // "HELP> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_CLANSEARCH) {\r
-             //Console->Print("Custom - Clansearch Chat: %s", ChatText);\r
-             sendClanSearch(Client, ChatText, false);\r
-             // "CLANSEARCH> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_CANYON) {\r
-             //Console->Print("Custom - Services_Canyon Chat: %s", ChatText);\r
-             sendServicesCS(Client, ChatText, false);\r
-             // "SKILL - CS> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_MB) {\r
-             //Console->Print("Custom - Services_MB Chat: %s", ChatText);\r
-             sendServicesMB(Client, ChatText, false);\r
-             // "SKILL - MB> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_NC) {\r
-             //Console->Print("Custom - Services_NC Chat: %s", ChatText);\r
-             sendServicesNC(Client, ChatText, false);\r
-             // "SKILL - NC> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_TH) {\r
-             //Console->Print("Custom - Services_TH Chat: %s", ChatText);\r
-             sendServicesTH(Client, ChatText, false);\r
-             // "SKILL - TH> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_WASTE) {\r
-             //Console->Print("Custom - Services_Waste Chat: %s", ChatText);\r
-             sendServicesWL(Client, ChatText, false);\r
-             // "SKILL - WL> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_10) {\r
-             //Console->Print("Custom - Team10 Chat: %s", ChatText);\r
-             sendTeam10(Client, ChatText, false);\r
-             // "TEAMSEARCH 10> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_30) {\r
-             //Console->Print("Custom - Team30 Chat: %s", ChatText);\r
-             sendTeam30(Client, ChatText, false);\r
-             // "EAMSEARCH 30> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_50) {\r
-             //Console->Print("Custom - Team50 Chat: %s", ChatText);\r
-             sendTeam50(Client, ChatText, false);\r
-             // "EAMSEARCH 50> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_70) {\r
-             //Console->Print("Custom - Team70 Chat: %s", ChatText);\r
-             sendTeam70(Client, ChatText, false);\r
-             // "EAMSEARCH 70> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_ADMIN) {\r
-             //Console->Print("Admin Chat: %s", ChatText);\r
-             sendAdmin(Client, ChatText, false);\r
-             // "ADMIN> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_GMADMIN) {\r
-             //Console->Print("Admin Chat: %s", ChatText);\r
-             sendGMAdmin(Client, ChatText, false);\r
-             // "ADMIN> %s: %s", PlayerName, ChatText\r
-        }\r
-        else if(*(uint32_t*)Channel == CHANNEL_GMCHAT) {\r
-             //Console->Print("GameMaster Chat: %s", ChatText);\r
-             sendGM(Client, ChatText, false);\r
-             // "GM> %s: %s", PlayerName, ChatText\r
-        }\r
-        else {\r
-             Console->Print("Unknown Chat-Channel: %#x", *(uint32_t*)Channel);\r
-        };\r
-  }\r
-}\r
-return (true);\r
-}\r
-\r
-bool PChat::cmpr(const uint8_t *Array1, const uint8_t *Array2) {\r
-   if(Array1[0] == Array2[0] && Array1[1] == Array2[1]) {\r
-       return true;\r
-   } else {\r
-       return false;\r
-   }\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+//  TODO:- Add "hooks" to process chatevents everywhere in the source <-- kind of done. you can use the global PChat Instance.
+//         Check:
+//              Chat->send(PClient* receiver, const uint8_t* Channel, const char* AuthorNickName, char* text, bool debugOut=false);
+//         Example:
+//              Chat->send(receiverClient, CHAT_DIRECT, Chars->GetChar(authorClient->GetCharID())->GetName().c_str(), text);
+
+PChat::PChat()
+{
+}
+
+PChat::~PChat()
+{
+}
+
+/*
+DONE    void sendBuddy(PClient* author, char* text, bool debugOut=false);
+DONE    void sendLocal(PClient* author, char* text, bool debugOut=false);
+NEED CLANDATA    void sendClan(PClient* author, char* text, bool debugOut=false);
+NEED TEAMDATA    void sendTeam(PClient* author, char* text, bool debugOut=false);
+DONE    void sendDirect(PClient* author, PClient* receiver, char* text, bool debugOut=false);
+DONE    void sendZone(PClient* author, char* text, bool debugOut=false);
+DONE    void sendFrak(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTradeCS(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTradeMB(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTradeNC(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTradeTH(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTradeWL(PClient* author, char* text, bool debugOut=false);
+DONE    void sendOOC(PClient* author, char* text, bool debugOut=false);
+DONE    void sendHelp(PClient* author, char* text, bool debugOut=false);
+DONE    void sendClanSearch(PClient* author, char* text, bool debugOut=false);
+DONE    void sendServicesCS(PClient* author, char* text, bool debugOut=false);
+DONE    void sendServicesMB(PClient* author, char* text, bool debugOut=false);
+DONE    void sendServicesNC(PClient* author, char* text, bool debugOut=false);
+DONE    void sendServicesTH(PClient* author, char* text, bool debugOut=false);
+DONE    void sendServicesWL(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTeam10(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTeam30(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTeam50(PClient* author, char* text, bool debugOut=false);
+DONE    void sendTeam70(PClient* author, char* text, bool debugOut=false);
+DONE    void sendAdmin(PClient* author, char* text, bool debugOut=false);
+DONE    void sendGM(PClient* author, char* text, bool debugOut=false);
+*/
+
+
+void PChat::sendBuddy(PClient* author, const char* text, bool debugOut)
+{
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+    // send the message to all Buddys in list
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second && authorChar->IsBuddy(it->second->GetCharID()) == true)
+        {
+            PClient* receiver = it->second;
+            //Console->Print("DEBUG: Buddychat - Sending msg to %s", Chars->GetChar(receiver->GetCharID())->GetName().c_str());
+            send(receiver, CHAT_BUDDY, authorChar->GetName().c_str(), text, debugOut);
+        }
+    }
+}
+
+void PChat::sendConnectedList(PClient* receiver, bool debugOut)
+{
+    const char* text = "Connected Players are:]";
+    send(receiver, CHAT_DIRECT, "[System", text, debugOut);
+
+    int counter = 1;
+
+    // send the list of currently connected players to receiver
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+          char counterText[5];
+          snprintf(counterText, 5, "%d", counter);
+
+        PChar* receiverChar = Chars->GetChar(it->second->GetCharID());
+        send(receiver, CHAT_DIRECT, (receiverChar ? receiverChar->GetName().c_str() : "*"), counterText, debugOut);
+
+        counter++;
+    }
+}
+
+
+void PChat::sendFrak(PClient* author, const char* text, bool debugOut)
+{
+    // send the message to all clients that have same FactionID
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+    uint32_t FID = authorChar->GetFaction(); // get LocationID of author
+
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            PClient* receiver = it->second;
+            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());
+            if(receiverChar && (receiverChar->GetFaction() == FID))
+            {
+                if(chanEnabled(receiver, C_FRAK) == true)
+                    send(receiver, CHAT_FRAK, authorChar->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendZone(PClient* author, const char* text, bool debugOut)
+{
+    // send the message to all clients that have same ZoneID
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+    uint32_t ZID = authorChar->GetLocation(); // get LocationID of author
+
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            PClient* receiver = it->second;
+            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());
+            if(receiverChar && (receiverChar->GetLocation() == ZID))
+            {
+                if(chanEnabled(receiver, C_ZONE) == true)
+                    send(receiver, CHAT_ZONE, authorChar->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendLocal(PClient* author, const char* text, bool debugOut)
+{
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+    uint32_t ZID = authorChar->GetLocation(); // get LocationID of author
+
+    // send the message to all clients that are in Area (Radius = X (needs to be defined somewhere!))
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            PClient* receiver = it->second;
+            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());
+            if(receiverChar && (receiverChar->GetLocation() == ZID))
+            {
+                uint16_t distance = DistanceApprox((authorChar->Coords).mX, (authorChar->Coords).mY, (authorChar->Coords).mZ, (receiverChar->Coords).mX, (receiverChar->Coords).mY, (receiverChar->Coords).mZ);
+                if(distance < LOCALCHAT_MAXDISTANCE)
+                {
+                    //sendLocalchat(receiver, author, text, debugOut); // Doesnt work!
+                    send(receiver, CHAT_LOCAL, authorChar->GetName().c_str(), text, debugOut);
+                }
+            }
+        }
+    }
+}
+
+void PChat::sendGM(PClient* author, const char* text, bool debugOut)
+{
+    if(author->GetAccountLevel() >= PAL_GM) // Only send GM> chat when user is an Gamemaster or higher
+    {
+        // send the message to all GameMasters.
+        for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+        {
+            if(author != it->second) // if its not the client, that send the message to the server
+            {
+                if(it->second) // only send if the client is existing!
+                {
+                    PClient* receiver = it->second;
+                    if(receiver->GetAccountLevel() >= PAL_GM) // Only send GM chat if RECEIVER is GM or higher
+                        send(receiver, CHAT_GM, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+                }
+            }
+        }
+    }
+}
+
+void PChat::sendGMAdmin(PClient* author, const char* text, bool debugOut)
+{
+    if(author->GetAccountLevel() >= PAL_GM) // Only send GM> chat when user is an Gamemaster or higher
+    {
+        // send the message to ALL users online
+        for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+        {
+            if(author != it->second) // if its not the client, that send the message to the server
+            {
+                if(it->second) // only send if the client is existing!
+                {
+                    PClient* receiver = it->second;
+                    send(receiver, CHAT_GMADMIN, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+                }
+            }
+        }
+    }
+}
+
+void PChat::sendAdmin(PClient* author, const char* text, bool debugOut)
+{
+    if(author->GetAccountLevel() >= PAL_ADMIN) // Only send ADMIN> chat when user is an serveradmin
+    {
+        // send the message to ALL users online
+        for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+        {
+            if(author != it->second) // if its not the client, that send the message to the server
+            {
+                if(it->second) // only send if the client is existing!
+                {
+                    PClient* receiver = it->second;
+                    send(receiver, CHAT_ADMIN, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+                }
+            }
+        }
+    }
+}
+
+void PChat::sendBroadcast(const char* text, bool debugOut)
+{
+    // send the message to ALL users online
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(it->second) // only send if the client is existing!
+        {
+            PClient* receiver = it->second;
+            send(receiver, CHAT_ADMIN, "Server", text, debugOut);
+        }
+    }
+}
+
+void PChat::sendOOCBroadcast(const char* text, bool debugOut)
+{
+    // send the message to ALL users online
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(it->second) // only send if the client is existing!
+        {
+            PClient* receiver = it->second;
+            if(chanEnabled(receiver, C_OOC) == true)
+                send(receiver, CHAT_OOC, "Server", text, debugOut);
+        }
+    }
+}
+
+void PChat::sendClan(PClient* author, const char* text, bool debugOut)
+{
+    /**
+        NOT ABLE TO IMPLEMENT THIS CHATTYPE YET, ITS SUPERGLOBAL TILL THEN
+    **/
+    // send the message to all clients that have same ClanID
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+
+//    int ClanID = authorChar->getClanID(); // get clanID of author
+
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second)
+        {
+            PClient* receiver = it->second;
+            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());
+            if(receiverChar /*&& (receiverChar->getClanID() == ClanID)*/)
+            {
+                send(receiver, CHAT_CLAN, authorChar->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+
+}
+
+void PChat::sendTeam(PClient* author, const char* text, bool debugOut)
+{
+    /**
+        NOT ABLE TO IMPLEMENT THIS CHATTYPE YET, ITS SUPERGLOBAL TILL THEN
+    **/
+    // send the message to all clients that have same TeamID
+
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+
+    //int TeamID = authorChar->getTeamID(); // get TeamID of author
+
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second)
+        {
+            PClient* receiver = it->second;
+            PChar* receiverChar = Chars->GetChar(receiver->GetCharID());
+            if(receiverChar /*&& (receiverChar->getTeamID() == TeamID)*/)
+            {
+                send(receiver, CHAT_TEAM, authorChar->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendPlayerDirect(PClient* author, const char* text, uint32_t destination, bool debugOut)
+{
+    bool tmpTargetOnline = false;
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        PClient* receiver = it->second;
+        PChar* receiverChar = Chars->GetChar(receiver->GetCharID());
+        if(receiverChar && (receiver->GetCharID() == destination))       
+        {
+            tmpTargetOnline = true;
+            sendDirect(author, receiver, text, debugOut);
+        }
+    }
+    if(tmpTargetOnline == false)
+    {
+        ConnectionTCP *Socket = author->getTCPConn();
+        uint8_t DirectTargetNotOnline[] = {0xFE, 0x07, 0x00, 0x83, 0x18, 0x01, 0x81, 0x54, 0x00, 0x00};
+
+        Socket->write(DirectTargetNotOnline, sizeof(DirectTargetNotOnline));
+        Socket->flushSendBuffer();
+    }
+
+    if(debugOut == true)
+    {
+        if(tmpTargetOnline == false)
+            Console->Print("[DEBUG] Requested target CharID %d is not online", destination);
+        else
+            Console->Print("[DEBUG] CharID %d found and message transmitted!", destination);
+    }
+}
+
+void PChat::sendDirect(PClient* author, PClient* receiver, const char* text, bool debugOut)
+{
+    PChar* authorChar = Chars->GetChar(author->GetCharID());
+
+    char *DChatPacket;
+    unsigned int packetsize = 0, c;
+    int LenText, LenNick, fpp, d, e, loopout;
+
+    ConnectionTCP *Socket = receiver->getTCPConn();
+
+    uint8_t BasicDirectPacket[] = {0xFE, 0x20, 0x00, 0x83, 0x17, 0xB7, 0x5F, 0x00, 0x00, 0x0C, 0x04, 0x00};
+
+    LenText = LenNick = fpp = 0;
+
+    do {
+      LenText++;
+    } while(text[LenText] != '\0');
+
+    do {
+      LenNick++;
+    } while(authorChar->GetName().c_str()[LenNick] != '\0');
+
+    loopout = 0;
+
+    packetsize = sizeof(BasicDirectPacket) + LenText + LenNick;
+
+    if(debugOut == true) {
+       Console->Print("Sizeof(TextToSend): %d || Sizeof(Nick): %d", LenText, LenNick);
+       Console->Print("Whole size: %d", packetsize);
+    }
+
+    DChatPacket = new char [packetsize];
+
+    // Copy basic packet into final packet
+    for(c=0;c<sizeof(BasicDirectPacket);c++) {
+       DChatPacket[fpp] = BasicDirectPacket[c];
+       fpp++;
+    }
+
+    // Copy Nickname into final packet
+    for(d=0;d<LenNick;d++) {
+       DChatPacket[fpp] = authorChar->GetName().c_str()[d];
+       fpp++;
+    }
+
+    // Copy Text into final packet
+    for(e=0;e<LenText;e++) {
+       DChatPacket[fpp] = text[e];
+       fpp++;
+    }
+
+    // Change Lenght bytes in final packet
+    DChatPacket[1] = packetsize - 3;
+    DChatPacket[9] = LenNick;
+
+    if(debugOut == true) {
+        unsigned int debugout;
+        for(debugout=0;debugout<packetsize;debugout++) {
+           Console->Print("Byte %d: %#x", debugout, DChatPacket[debugout]);
+        }
+    }
+
+    // Sending direct chat packet and removing dynamic array
+    Socket->write(DChatPacket, packetsize);
+    Socket->flushSendBuffer();
+    delete[] DChatPacket;
+}
+
+void PChat::sendLocalchat(PClient* receiver, PClient* author, const char* text, bool debugOut)
+{
+    return; // IncreaseUDP could cause OOO here. Since this function is doing nothing, we disabled it
+    char *LocalChatPacket;
+    int overallsize = 0, LenText = 0;
+    uint8_t BasicLocal[] = { 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1B };
+
+    // Get size of Text to send
+    do {
+      LenText++;
+    } while(text[LenText] != '\0');
+
+    // Calculate packetsize
+    overallsize = sizeof(BasicLocal) + LenText + 1;
+
+    if(debugOut == true)
+       Console->Print("Whole size: %d", overallsize);
+
+    LocalChatPacket = new char [overallsize];
+
+    // Copy basic packet into final packet
+    int fpp = 0;
+    for(unsigned int c = 0; c < sizeof(BasicLocal); c++) {
+       LocalChatPacket[fpp] = BasicLocal[c];
+       fpp++;
+    }
+
+    // Copy Text into final packet
+    for(int e = 0; e < LenText; e++) {
+       LocalChatPacket[fpp] = text[e];
+       fpp++;
+    }
+
+    // Terminate string
+    LocalChatPacket[fpp] = 0x00;
+
+    // Add UdpID, SessionID, lenght and local charid
+    receiver->IncreaseUDP_ID();
+    *(uint16_t*)&LocalChatPacket[1] = receiver->GetUDP_ID();     // UDP
+    *(uint16_t*)&LocalChatPacket[3] = receiver->GetSessionID();  // Session
+    *(uint8_t*)&LocalChatPacket[5] = overallsize - 6;            // Packetlen
+    *(uint16_t*)&LocalChatPacket[7] = receiver->GetUDP_ID();     // 2nd UDP
+    *(uint16_t*)&LocalChatPacket[10] = author->GetLocalID();     // Local ID
+
+    // Sending local chat packet and removing dynamic array
+    ConnectionUDP *Socket = receiver->getUDPConn();
+    Socket->write(LocalChatPacket, overallsize);
+    Socket->flushSendBuffer();
+    delete[] LocalChatPacket;
+}
+
+void PChat::sendTradeCS(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TRADECS) == true)
+                    send(receiver, CHAT_TRADECS, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTradeMB(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TRADEMB) == true)
+                    send(receiver, CHAT_TRADEMB, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTradeNC(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TRADENC) == true)
+                    send(receiver, CHAT_TRADENC, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTradeTH(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TRADETH) == true)
+                    send(receiver, CHAT_TRADETH, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTradeWL(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TRADEWL) == true)
+                    send(receiver, CHAT_TRADEWL, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendOOC(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_OOC) == true)
+                    send(receiver, CHAT_OOC, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendHelp(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_HELP) == true)
+                    send(receiver, CHAT_HELP, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendClanSearch(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_CLANSEARCH) == true)
+                    send(receiver, CHAT_CLANSEARCH, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendServicesCS(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_SERVICECS) == true)
+                    send(receiver, CHAT_SERVICECS, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendServicesMB(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_SERVICEMB) == true)
+                    send(receiver, CHAT_SERVICESMB, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendServicesNC(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_SERVICENC) == true)
+                    send(receiver, CHAT_SERVICESNC, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendServicesTH(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_SERVICETH) == true)
+                    send(receiver, CHAT_SERVICESTH, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendServicesWL(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_SERVICEWL) == true)
+                    send(receiver, CHAT_SERVICESWL, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTeam10(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TEAM10) == true)
+                    send(receiver, CHAT_TEAM10, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTeam30(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TEAM30) == true)
+                    send(receiver, CHAT_TEAM30, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTeam50(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TEAM50) == true)
+                    send(receiver, CHAT_TEAM50, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+void PChat::sendTeam70(PClient* author, const char* text, bool debugOut)
+{
+    for(PClientMap::iterator it=ClientManager->getClientListBegin(); it!=ClientManager->getClientListEnd(); it++)
+    {
+        if(author != it->second) // if its not the client, that send the message to the server
+        {
+            if(it->second) // only send if the client is existing!
+            {
+                PClient* receiver = it->second;
+                if(chanEnabled(receiver, C_TEAM70) == true)
+                    send(receiver, CHAT_TEAM70, Chars->GetChar(author->GetCharID())->GetName().c_str(), text, debugOut);
+            }
+        }
+    }
+}
+
+bool PChat::chanEnabled(PClient* Client, uint32_t channel)
+{
+    // Check if player has target channel enabled or disabled
+    PChar* TargetChar = Chars->GetChar(Client->GetCharID());
+    if(!TargetChar)
+      return false;
+      
+    uint32_t actChans = TargetChar->GetActiveChannels();
+    uint32_t check = actChans & channel;
+
+    if(check == channel)
+        return true;
+    else
+        return false;
+}
+
+bool PChat::send(PClient* receiver, const uint8_t* Channel, const char* AuthorNickName, const char* text, bool debugOut)
+{
+    char *ChatPacket;
+    unsigned int packetsize = 0, c;
+    int LenText, LenNick, fpp, d, e, loopout;
+    uint8_t TargetChannel[2];
+
+//Console->Print("1: %#x", Channel[0]);
+//Console->Print("2: %#x", CHAT_BUDDY[0]);
+
+
+      if(cmpr(Channel, CHAT_BUDDY) == true) {
+           TargetChannel[0] = CHAT_BUDDY[0];
+           TargetChannel[1] = CHAT_BUDDY[1];
+      } else if(cmpr(Channel, CHAT_LOCAL) == true) {
+           TargetChannel[0] = CHAT_LOCAL[0];
+           TargetChannel[1] = CHAT_LOCAL[1];
+      } else if(cmpr(Channel, CHAT_CLAN) == true) {
+           TargetChannel[0] = CHAT_CLAN[0];
+           TargetChannel[1] = CHAT_CLAN[1];
+      } else if(cmpr(Channel, CHAT_TEAM) == true) {
+           TargetChannel[0] = CHAT_TEAM[0];
+           TargetChannel[1] = CHAT_TEAM[1];
+      } else if(cmpr(Channel, CHAT_DIRECT) == true) {
+           TargetChannel[0] = CHAT_DIRECT[0];
+           TargetChannel[1] = CHAT_DIRECT[1];
+      } else if(cmpr(Channel, CHAT_ZONE) == true) {
+           TargetChannel[0] = CHAT_ZONE[0];
+           TargetChannel[1] = CHAT_ZONE[1];
+      } else if(cmpr(Channel, CHAT_FRAK) == true) {
+           TargetChannel[0] = CHAT_FRAK[0];
+           TargetChannel[1] = CHAT_FRAK[1];
+      } else if(cmpr(Channel, CHAT_TRADECS) == true) {
+           TargetChannel[0] = CHAT_TRADECS[0];
+           TargetChannel[1] = CHAT_TRADECS[1];
+      } else if(cmpr(Channel, CHAT_TRADEMB) == true) {
+           TargetChannel[0] = CHAT_TRADEMB[0];
+           TargetChannel[1] = CHAT_TRADEMB[1];
+      } else if(cmpr(Channel, CHAT_TRADENC) == true) {
+           TargetChannel[0] = CHAT_TRADENC[0];
+           TargetChannel[1] = CHAT_TRADENC[1];
+      } else if(cmpr(Channel, CHAT_TRADETH) == true) {
+           TargetChannel[0] = CHAT_TRADETH[0];
+           TargetChannel[1] = CHAT_TRADETH[1];
+      } else if(cmpr(Channel, CHAT_TRADEWL) == true) {
+           TargetChannel[0] = CHAT_TRADEWL[0];
+           TargetChannel[1] = CHAT_TRADEWL[1];
+      } else if(cmpr(Channel, CHAT_OOC) == true) {
+           TargetChannel[0] = CHAT_OOC[0];
+           TargetChannel[1] = CHAT_OOC[1];
+      } else if(cmpr(Channel, CHAT_HELP) == true) {
+           TargetChannel[0] = CHAT_HELP[0];
+           TargetChannel[1] = CHAT_HELP[1];
+      } else if(cmpr(Channel, CHAT_CLANSEARCH) == true) {
+           TargetChannel[0] = CHAT_CLANSEARCH[0];
+           TargetChannel[1] = CHAT_CLANSEARCH[1];
+      } else if(cmpr(Channel, CHAT_SERVICECS) == true) {
+           TargetChannel[0] = CHAT_SERVICECS[0];
+           TargetChannel[1] = CHAT_SERVICECS[1];
+      } else if(cmpr(Channel, CHAT_SERVICESMB) == true) {
+           TargetChannel[0] = CHAT_SERVICESMB[0];
+           TargetChannel[1] = CHAT_SERVICESMB[1];
+      } else if(cmpr(Channel, CHAT_SERVICESNC) == true) {
+           TargetChannel[0] = CHAT_SERVICESNC[0];
+           TargetChannel[1] = CHAT_SERVICESNC[1];
+      } else if(cmpr(Channel, CHAT_SERVICESTH) == true) {
+           TargetChannel[0] = CHAT_SERVICESTH[0];
+           TargetChannel[1] = CHAT_SERVICESTH[1];
+      } else if(cmpr(Channel, CHAT_SERVICESWL) == true) {
+           TargetChannel[0] = CHAT_SERVICESWL[0];
+           TargetChannel[1] = CHAT_SERVICESWL[1];
+      } else if(cmpr(Channel, CHAT_TEAM10) == true) {
+           TargetChannel[0] = CHAT_TEAM10[0];
+           TargetChannel[1] = CHAT_TEAM10[1];
+      } else if(cmpr(Channel, CHAT_TEAM30) == true) {
+           TargetChannel[0] = CHAT_TEAM30[0];
+           TargetChannel[1] = CHAT_TEAM30[1];
+      } else if(cmpr(Channel, CHAT_TEAM50) == true) {
+           TargetChannel[0] = CHAT_TEAM50[0];
+           TargetChannel[1] = CHAT_TEAM50[1];
+      } else if(cmpr(Channel, CHAT_TEAM70) == true) {
+           TargetChannel[0] = CHAT_TEAM70[0];
+           TargetChannel[1] = CHAT_TEAM70[1];
+      } else if(cmpr(Channel, CHAT_ADMIN) == true) {
+           TargetChannel[0] = CHAT_ADMIN[0];
+           TargetChannel[1] = CHAT_ADMIN[1];
+      } else if(cmpr(Channel, CHAT_GMADMIN) == true) {
+           TargetChannel[0] = CHAT_GMADMIN[0];
+           TargetChannel[1] = CHAT_GMADMIN[1];
+      } else if(cmpr(Channel, CHAT_GM) == true) {
+           TargetChannel[0] = CHAT_GM[0];
+           TargetChannel[1] = CHAT_GM[1];
+      } else {
+         Console->Print("SendChat error: Channel %#x unknown", Channel);
+         return false;
+      }
+
+    ConnectionTCP *Socket = receiver->getTCPConn();
+
+    uint8_t BasicChatPacket[] = {0xFE, 0x15, 0x00, 0x83, 0x17, 0x90, 0x03, 0x00, 0x00, 0x07, 0x05, 0x0F};
+
+    LenText = LenNick = fpp = 0;
+
+    do {
+      LenText++;
+    } while(text[LenText] != '\0');
+
+    do {
+      LenNick++;
+    } while(AuthorNickName[LenNick] != '\0');
+
+    if(LenText == 0 || LenNick == 0) {
+       Console->Print("Error in SendChat, nickname or text is missing");
+       return false;
+    }
+
+    loopout = 0;
+
+    packetsize = sizeof(BasicChatPacket) + LenText + LenNick;
+
+    if(debugOut == true) {
+       Console->Print("Sizeof(TextToSend): %d || Sizeof(Nick): %d", LenText, LenNick);
+       Console->Print("Whole size: %d", packetsize);
+    }
+
+    ChatPacket = new char [packetsize];
+
+    // Copy basic packet into final packet
+    for(c=0;c<sizeof(BasicChatPacket);c++) {
+       ChatPacket[fpp] = BasicChatPacket[c];
+       fpp++;
+    }
+
+    // Copy Nickname into final packet
+    for(d=0;d<LenNick;d++) {
+       ChatPacket[fpp] = AuthorNickName[d];
+       fpp++;
+    }
+
+    // Copy Text into final packet
+    for(e=0;e<LenText;e++) {
+       ChatPacket[fpp] = text[e];
+       fpp++;
+    }
+
+    // Change Lenght bytes in final packet
+    ChatPacket[1] = packetsize - 3;
+    ChatPacket[9] = LenNick;
+    ChatPacket[10] = TargetChannel[0];
+    ChatPacket[11] = TargetChannel[1];
+
+    if(debugOut == true) {
+        unsigned int debugout;
+        for(debugout=0;debugout<packetsize;debugout++) {
+           Console->Print("Byte %d: %#x", debugout, ChatPacket[debugout]);
+        }
+    }
+
+    // Sending direct chat packet and removing dynamic array
+    Socket->write(ChatPacket, packetsize);
+    Socket->flushSendBuffer();
+    delete[] ChatPacket;
+
+    return true;
+}
+
+
+
+bool PChat::HandleGameChat(PClient *Client, const uint8_t *Packet)
+{
+    // if player is shunned, ignore all incomming chat and game commands.
+    // ServerAdmins are not affected by any shuns. (Should never happen anyways...)
+    if((Client->GetChar()->IsShunned() == true) && (Client->GetAccountLevel() < PAL_ADMIN)) return true;
+
+    int i, j, k;
+
+     uint8_t chattype = *(uint8_t*)&Packet[7];
+// -----------------------------------------------
+    if(chattype == 0x1B) {
+      // Local chat
+      i = 8;
+      j = 0;
+
+      char ChatText[255];
+
+      do {
+         ChatText[j] = Packet[i];
+         i++;
+         j++;
+      } while (ChatText[j-1] != 0x00);
+
+      ChatText[j] = '\0';
+      if(ChatText[0] == '@' && sizeof(ChatText) > 2) {
+            GameCommands->HandleGameCommand(ChatText, Client);
+      } else {
+          // We know its working, so we dont need console output anymore
+            //Console->Print("Local Chat: %s", ChatText);
+            //Console->Print("Client CharName is: %s", Chars->GetChar(Client->GetCharID())->GetName().c_str());
+            sendLocal(Client, ChatText, false);
+      }
+
+// -----------------------------------------------
+   } else if (chattype == 0x3B) {
+      // Non-Local chat
+      i = 13;
+      j = 0;
+      k = 0;
+
+      char ChatText[255];
+
+      do {
+         ChatText[j] = Packet[i];
+         i++;
+         j++;
+      } while (ChatText[j-1] != 0x00);
+
+
+      ChatText[j] = '\0';
+      if(ChatText[0] == '@' && sizeof(ChatText) > 2) {
+            GameCommands->HandleGameCommand(ChatText, Client);
+      } else {
+        //      Console->Print("CHATLINE: %s HEX: %#X", ChatText, Packet[i-1]);
+        char Channel[4];
+
+        for(k = 0; k <= 3; k ++) {
+           Channel[k] = Packet[k+8];
+        }
+  //    Console->Print("Channel no %#x %#x %#x %#x", Channel[0], Channel[1], Channel[2], Channel[3]);
+
+        // First, check if packet is a direct-chat-packet
+        if(*(uint8_t*)&Packet[8] == 0x04) {
+             //Console->Print("Direct Chat: %s", ChatText);
+             sendPlayerDirect(Client, ChatText, *(uint32_t*)&Packet[9], false);
+             //sendDirect(Client, ChatText, false);
+             // "DIRECT> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_BUDDY) {
+             //Console->Print("Buddy Chat: %s", ChatText);
+             sendBuddy(Client, ChatText, false);
+             // "BUDDY> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CLAN) {
+             //Console->Print("Clan Chat: %s", ChatText);
+             sendClan(Client, ChatText, false);
+             // "CLAN> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_TEAM) {
+             //Console->Print("Team Chat: %s", ChatText);
+             sendTeam(Client, ChatText, false);
+             // "TEAM> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_ZONE) {
+             //Console->Print("Custom - Zone Chat: %s", ChatText);
+             sendZone(Client, ChatText, false);
+             // "ZONE> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_FRAKTION) {
+             //Console->Print("Custom - Fraktion Chat: %s", ChatText);
+             sendFrak(Client, ChatText, false);
+             // "FRACTION> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_CANYON) {
+             //Console->Print("Custom - Trade_Canyon Chat: %s", ChatText);
+             sendTradeCS(Client, ChatText, false);
+             // "TRADE - CS> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_MB) {
+             //Console->Print("Custom - Trade_MB Chat: %s", ChatText);
+             sendTradeMB(Client, ChatText, false);
+             // "TRADE - MB> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_NC) {
+             //Console->Print("Custom - Trade_NC Chat: %s", ChatText);
+             sendTradeNC(Client, ChatText, false);
+             // "TRADE - NC> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_TH) {
+             //Console->Print("Custom - Trade_TH Chat: %s", ChatText);
+             sendTradeTH(Client, ChatText, false);
+             // "TRADE - TH> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TRADE_WASTE) {
+             //Console->Print("Custom - Trade_Waste Chat: %s", ChatText);
+             sendTradeWL(Client, ChatText, false);
+             // "TRADE - WL> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_OOC) {
+             //Console->Print("Custom - OOC Chat: %s", ChatText);
+             sendOOC(Client, ChatText, false);
+             // "OOC> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_PLAYERHELP) {
+             //Console->Print("Custom - PlayerToPlayerhelp Chat: %s", ChatText);
+             sendHelp(Client, ChatText, false);
+             // "HELP> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_CLANSEARCH) {
+             //Console->Print("Custom - Clansearch Chat: %s", ChatText);
+             sendClanSearch(Client, ChatText, false);
+             // "CLANSEARCH> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_CANYON) {
+             //Console->Print("Custom - Services_Canyon Chat: %s", ChatText);
+             sendServicesCS(Client, ChatText, false);
+             // "SKILL - CS> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_MB) {
+             //Console->Print("Custom - Services_MB Chat: %s", ChatText);
+             sendServicesMB(Client, ChatText, false);
+             // "SKILL - MB> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_NC) {
+             //Console->Print("Custom - Services_NC Chat: %s", ChatText);
+             sendServicesNC(Client, ChatText, false);
+             // "SKILL - NC> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_TH) {
+             //Console->Print("Custom - Services_TH Chat: %s", ChatText);
+             sendServicesTH(Client, ChatText, false);
+             // "SKILL - TH> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_SERVICES_WASTE) {
+             //Console->Print("Custom - Services_Waste Chat: %s", ChatText);
+             sendServicesWL(Client, ChatText, false);
+             // "SKILL - WL> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_10) {
+             //Console->Print("Custom - Team10 Chat: %s", ChatText);
+             sendTeam10(Client, ChatText, false);
+             // "TEAMSEARCH 10> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_30) {
+             //Console->Print("Custom - Team30 Chat: %s", ChatText);
+             sendTeam30(Client, ChatText, false);
+             // "EAMSEARCH 30> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_50) {
+             //Console->Print("Custom - Team50 Chat: %s", ChatText);
+             sendTeam50(Client, ChatText, false);
+             // "EAMSEARCH 50> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_CUS_TEAM_70) {
+             //Console->Print("Custom - Team70 Chat: %s", ChatText);
+             sendTeam70(Client, ChatText, false);
+             // "EAMSEARCH 70> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_ADMIN) {
+             //Console->Print("Admin Chat: %s", ChatText);
+             sendAdmin(Client, ChatText, false);
+             // "ADMIN> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_GMADMIN) {
+             //Console->Print("Admin Chat: %s", ChatText);
+             sendGMAdmin(Client, ChatText, false);
+             // "ADMIN> %s: %s", PlayerName, ChatText
+        }
+        else if(*(uint32_t*)Channel == CHANNEL_GMCHAT) {
+             //Console->Print("GameMaster Chat: %s", ChatText);
+             sendGM(Client, ChatText, false);
+             // "GM> %s: %s", PlayerName, ChatText
+        }
+        else {
+             Console->Print("Unknown Chat-Channel: %#x", *(uint32_t*)Channel);
+        };
+  }
+}
+return (true);
+}
+
+bool PChat::cmpr(const uint8_t *Array1, const uint8_t *Array2) {
+   if(Array1[0] == Array2[0] && Array1[1] == Array2[1]) {
+       return true;
+   } else {
+       return false;
+   }
+}
index 7d20a6e..c499f98 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-#define LOCALCHAT_MAXDISTANCE 1433\r
-\r
-class PClient;\r
-\r
-class PChat {\r
-public:\r
-    PChat();\r
-    ~PChat();\r
-\r
-    // INCOMING CHAT\r
-    bool HandleGameChat(PClient *Client, const uint8_t *Packet);\r
-    bool cmpr(const uint8_t *Array1, const uint8_t *Array2);\r
-\r
-    // this function is called by the other more specific functions and simply sends the data to the receiver-client\r
-    bool send(PClient* receiver, const uint8_t* Channel, const char* AuthorNickName, const char* text, bool debugOut=false);\r
-\r
-    // this is for debugging and sends the current connected playerlist to the receiver-client\r
-    void sendConnectedList(PClient* receiver, bool debugOut=false);\r
-\r
-    // specific channel functions:\r
-    void sendBuddy(PClient* author, const char* text, bool debugOut=false);\r
-    void sendLocal(PClient* author, const char* text, bool debugOut=false);\r
-    void sendClan(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTeam(PClient* author, const char* text, bool debugOut=false);\r
-    void sendDirect(PClient* author, PClient* receiver, const char* text, bool debugOut=false);\r
-    void sendZone(PClient* author, const char* text, bool debugOut=false);\r
-    void sendFrak(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTradeCS(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTradeMB(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTradeNC(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTradeTH(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTradeWL(PClient* author, const char* text, bool debugOut=false);\r
-    void sendOOC(PClient* author, const char* text, bool debugOut=false);\r
-    void sendHelp(PClient* author, const char* text, bool debugOut=false);\r
-    void sendClanSearch(PClient* author, const char* text, bool debugOut=false);\r
-    void sendServicesCS(PClient* author, const char* text, bool debugOut=false);\r
-    void sendServicesMB(PClient* author, const char* text, bool debugOut=false);\r
-    void sendServicesNC(PClient* author, const char* text, bool debugOut=false);\r
-    void sendServicesTH(PClient* author, const char* text, bool debugOut=false);\r
-    void sendServicesWL(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTeam10(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTeam30(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTeam50(PClient* author, const char* text, bool debugOut=false);\r
-    void sendTeam70(PClient* author, const char* text, bool debugOut=false);\r
-    void sendAdmin(PClient* author, const char* text, bool debugOut=false);\r
-    void sendGM(PClient* author, const char* text, bool debugOut=false);\r
-    void sendGMAdmin(PClient* author, const char* text, bool debugOut=false);\r
-\r
-    void sendBroadcast(const char* text, bool debugOut=false);\r
-    void sendOOCBroadcast(const char* text, bool debugOut=false);\r
-    void sendPlayerDirect(PClient* author, const char* text, uint32_t destination, bool debugOut=false);\r
-    void sendLocalchat(PClient* receiver, PClient* author, const char* text, bool debugOut=false);\r
-    bool chanEnabled(PClient* Client, uint32_t channel);\r
-};\r
-\r
-/** A WARNING: DO >N O T< (!!!) CHANGE >ANY< OF THE FOLLOWING VARIABLES UNLESS YOU KNOW EXACT WHAT YOU'RE DOING! **/\r
-/** You can easily mess up the entire chat subsystem. If you're unsure, ask Namikon first! **/\r
-/*\r
-####################\r
-   CHANNEL-CODES:\r
-     (INCOMING)\r
-####################\r
-*/\r
-static const uint32_t CHANNEL_BUDDY = 0x00000000;                // Buddy\r
-static const uint32_t CHANNEL_CLAN = 0x00000002;                 // Clan\r
-static const uint32_t CHANNEL_TEAM = 0x00000003;                 // Team\r
-static const uint32_t CHANNEL_DIRECT = 0xFFFFFFFF;               // Direct UNKNOWN YET\r
-static const uint32_t CHANNEL_CUS_ZONE = 0x00000105;             // Custom -> Zone\r
-static const uint32_t CHANNEL_CUS_FRAKTION = 0x00000205;         // Custom -> Fraktion\r
-static const uint32_t CHANNEL_CUS_TRADE_CANYON = 0x00002005;     // Custom -> Trade Canyon\r
-static const uint32_t CHANNEL_CUS_TRADE_MB = 0x00000805;         // Custom -> Trade MB\r
-static const uint32_t CHANNEL_CUS_TRADE_NC = 0x00000405;         // Custom -> Trade NC\r
-static const uint32_t CHANNEL_CUS_TRADE_TH = 0x00001005;         // Custom -> Trade TH\r
-static const uint32_t CHANNEL_CUS_TRADE_WASTE = 0x00004005;      // Custom -> Trade Wastelands\r
-static const uint32_t CHANNEL_CUS_OOC = 0x04000005;              // Custom -> OOC\r
-static const uint32_t CHANNEL_CUS_PLAYERHELP = 0x02000005;       // Custom -> Player 2 Player help\r
-static const uint32_t CHANNEL_CUS_CLANSEARCH = 0x01000005;       // Custom -> Searching Clan\r
-static const uint32_t CHANNEL_CUS_SERVICES_CANYON = 0x00040005;  // Custom -> Runner Services Canyon\r
-static const uint32_t CHANNEL_CUS_SERVICES_MB = 0x00010005;      // Custom -> Runner Services MB\r
-static const uint32_t CHANNEL_CUS_SERVICES_NC = 0x00008005;      // Custom -> Runner Services NC\r
-static const uint32_t CHANNEL_CUS_SERVICES_TH = 0x00020005;      // Custom -> Runner Services TH\r
-static const uint32_t CHANNEL_CUS_SERVICES_WASTE = 0x00080005;   // Custom -> Runner Services Wastelands\r
-static const uint32_t CHANNEL_CUS_TEAM_10 = 0x00100005;          // Custom -> Searching Team ~10\r
-static const uint32_t CHANNEL_CUS_TEAM_30 = 0x00200005;          // Custom -> Searching Team ~30\r
-static const uint32_t CHANNEL_CUS_TEAM_50 = 0x00400005;          // Custom -> Searching Team ~50\r
-static const uint32_t CHANNEL_CUS_TEAM_70 = 0x00800005;          // Custom -> Searching Team ~70\r
-static const uint32_t CHANNEL_ADMIN = 0x000000FF;                // Admin chat\r
-static const uint32_t CHANNEL_GMADMIN = 0x000000FE;                // Admin chat\r
-static const uint32_t CHANNEL_GMCHAT = 0x000000FD;               // GameMaster chat\r
-/*\r
-####################\r
-   CHANNEL-CODES:\r
-     (OUTGOING)\r
-####################\r
-*/\r
-static const uint8_t CHAT_BUDDY[] = {0x00, 0x10};\r
-static const uint8_t CHAT_LOCAL[] =  {0x01, 0x10};\r
-static const uint8_t CHAT_CLAN[] = {0x02, 0x10};\r
-static const uint8_t CHAT_TEAM[] = {0x03, 0x10};\r
-static const uint8_t CHAT_DIRECT[] = {0x04, 0x10};\r
-static const uint8_t CHAT_ZONE[] = {0x05, 0x00};\r
-static const uint8_t CHAT_FRAK[] = {0x05, 0x01};\r
-static const uint8_t CHAT_TRADECS[] = {0x05, 0x05};\r
-static const uint8_t CHAT_TRADEMB[] = {0x05, 0x03};\r
-static const uint8_t CHAT_TRADENC[] = {0x05, 0x02};\r
-static const uint8_t CHAT_TRADETH[] = {0x05, 0x04};\r
-static const uint8_t CHAT_TRADEWL[] = {0x05, 0x06};\r
-static const uint8_t CHAT_OOC[] = {0x05, 0x12};\r
-static const uint8_t CHAT_HELP[] = {0x05, 0x11};\r
-static const uint8_t CHAT_CLANSEARCH[] = {0x05, 0x10};\r
-static const uint8_t CHAT_SERVICECS[] =  {0x05, 0x0A};\r
-static const uint8_t CHAT_SERVICESMB[] = {0x05, 0x08};\r
-static const uint8_t CHAT_SERVICESNC[] = {0x05, 0x07};\r
-static const uint8_t CHAT_SERVICESTH[] = {0x05, 0x09};\r
-static const uint8_t CHAT_SERVICESWL[] = {0x05, 0x0B};\r
-static const uint8_t CHAT_TEAM10[] = {0x05, 0x0C};\r
-static const uint8_t CHAT_TEAM30[] = {0x05, 0x0D};\r
-static const uint8_t CHAT_TEAM50[] = {0x05, 0x0E};\r
-static const uint8_t CHAT_TEAM70[] = {0x05, 0x0F};\r
-static const uint8_t CHAT_ADMIN[] = {0xFF, 0x10};\r
-static const uint8_t CHAT_GMADMIN[] = {0xFE, 0x10};\r
-static const uint8_t CHAT_GM[] = {0xFD, 0x10};\r
-\r
-/*\r
-####################\r
-   CHANNEL-CODES:\r
-(EN/DISABLE-ABLE CHANNELS)\r
-####################\r
-*/\r
-static const uint32_t C_ZONE = 1;\r
-static const uint32_t C_FRAK = 2;\r
-static const uint32_t C_TRADENC = 4;\r
-static const uint32_t C_TRADEMB = 8;\r
-static const uint32_t C_TRADETH = 16;\r
-static const uint32_t C_TRADECS = 32;\r
-static const uint32_t C_TRADEWL = 64;\r
-static const uint32_t C_SERVICENC = 128;\r
-static const uint32_t C_SERVICEMB = 256;\r
-static const uint32_t C_SERVICETH = 512;\r
-static const uint32_t C_SERVICECS = 1024;\r
-static const uint32_t C_SERVICEWL = 2048;\r
-static const uint32_t C_TEAM10 = 4096;\r
-static const uint32_t C_TEAM30 = 8192;\r
-static const uint32_t C_TEAM50 = 16384;\r
-static const uint32_t C_TEAM70 = 32768;\r
-static const uint32_t C_CLANSEARCH = 65536;\r
-static const uint32_t C_HELP = 131072;\r
-static const uint32_t C_OOC = 262144;\r
+#pragma once
+
+#include <cstdint>
+
+#define LOCALCHAT_MAXDISTANCE 1433
+
+class PClient;
+
+class PChat {
+public:
+    PChat();
+    ~PChat();
+
+    // INCOMING CHAT
+    bool HandleGameChat(PClient *Client, const uint8_t *Packet);
+    bool cmpr(const uint8_t *Array1, const uint8_t *Array2);
+
+    // this function is called by the other more specific functions and simply sends the data to the receiver-client
+    bool send(PClient* receiver, const uint8_t* Channel, const char* AuthorNickName, const char* text, bool debugOut=false);
+
+    // this is for debugging and sends the current connected playerlist to the receiver-client
+    void sendConnectedList(PClient* receiver, bool debugOut=false);
+
+    // specific channel functions:
+    void sendBuddy(PClient* author, const char* text, bool debugOut=false);
+    void sendLocal(PClient* author, const char* text, bool debugOut=false);
+    void sendClan(PClient* author, const char* text, bool debugOut=false);
+    void sendTeam(PClient* author, const char* text, bool debugOut=false);
+    void sendDirect(PClient* author, PClient* receiver, const char* text, bool debugOut=false);
+    void sendZone(PClient* author, const char* text, bool debugOut=false);
+    void sendFrak(PClient* author, const char* text, bool debugOut=false);
+    void sendTradeCS(PClient* author, const char* text, bool debugOut=false);
+    void sendTradeMB(PClient* author, const char* text, bool debugOut=false);
+    void sendTradeNC(PClient* author, const char* text, bool debugOut=false);
+    void sendTradeTH(PClient* author, const char* text, bool debugOut=false);
+    void sendTradeWL(PClient* author, const char* text, bool debugOut=false);
+    void sendOOC(PClient* author, const char* text, bool debugOut=false);
+    void sendHelp(PClient* author, const char* text, bool debugOut=false);
+    void sendClanSearch(PClient* author, const char* text, bool debugOut=false);
+    void sendServicesCS(PClient* author, const char* text, bool debugOut=false);
+    void sendServicesMB(PClient* author, const char* text, bool debugOut=false);
+    void sendServicesNC(PClient* author, const char* text, bool debugOut=false);
+    void sendServicesTH(PClient* author, const char* text, bool debugOut=false);
+    void sendServicesWL(PClient* author, const char* text, bool debugOut=false);
+    void sendTeam10(PClient* author, const char* text, bool debugOut=false);
+    void sendTeam30(PClient* author, const char* text, bool debugOut=false);
+    void sendTeam50(PClient* author, const char* text, bool debugOut=false);
+    void sendTeam70(PClient* author, const char* text, bool debugOut=false);
+    void sendAdmin(PClient* author, const char* text, bool debugOut=false);
+    void sendGM(PClient* author, const char* text, bool debugOut=false);
+    void sendGMAdmin(PClient* author, const char* text, bool debugOut=false);
+
+    void sendBroadcast(const char* text, bool debugOut=false);
+    void sendOOCBroadcast(const char* text, bool debugOut=false);
+    void sendPlayerDirect(PClient* author, const char* text, uint32_t destination, bool debugOut=false);
+    void sendLocalchat(PClient* receiver, PClient* author, const char* text, bool debugOut=false);
+    bool chanEnabled(PClient* Client, uint32_t channel);
+};
+
+/** A WARNING: DO >N O T< (!!!) CHANGE >ANY< OF THE FOLLOWING VARIABLES UNLESS YOU KNOW EXACT WHAT YOU'RE DOING! **/
+/** You can easily mess up the entire chat subsystem. If you're unsure, ask Namikon first! **/
+/*
+####################
+   CHANNEL-CODES:
+     (INCOMING)
+####################
+*/
+static const uint32_t CHANNEL_BUDDY = 0x00000000;                // Buddy
+static const uint32_t CHANNEL_CLAN = 0x00000002;                 // Clan
+static const uint32_t CHANNEL_TEAM = 0x00000003;                 // Team
+static const uint32_t CHANNEL_DIRECT = 0xFFFFFFFF;               // Direct UNKNOWN YET
+static const uint32_t CHANNEL_CUS_ZONE = 0x00000105;             // Custom -> Zone
+static const uint32_t CHANNEL_CUS_FRAKTION = 0x00000205;         // Custom -> Fraktion
+static const uint32_t CHANNEL_CUS_TRADE_CANYON = 0x00002005;     // Custom -> Trade Canyon
+static const uint32_t CHANNEL_CUS_TRADE_MB = 0x00000805;         // Custom -> Trade MB
+static const uint32_t CHANNEL_CUS_TRADE_NC = 0x00000405;         // Custom -> Trade NC
+static const uint32_t CHANNEL_CUS_TRADE_TH = 0x00001005;         // Custom -> Trade TH
+static const uint32_t CHANNEL_CUS_TRADE_WASTE = 0x00004005;      // Custom -> Trade Wastelands
+static const uint32_t CHANNEL_CUS_OOC = 0x04000005;              // Custom -> OOC
+static const uint32_t CHANNEL_CUS_PLAYERHELP = 0x02000005;       // Custom -> Player 2 Player help
+static const uint32_t CHANNEL_CUS_CLANSEARCH = 0x01000005;       // Custom -> Searching Clan
+static const uint32_t CHANNEL_CUS_SERVICES_CANYON = 0x00040005;  // Custom -> Runner Services Canyon
+static const uint32_t CHANNEL_CUS_SERVICES_MB = 0x00010005;      // Custom -> Runner Services MB
+static const uint32_t CHANNEL_CUS_SERVICES_NC = 0x00008005;      // Custom -> Runner Services NC
+static const uint32_t CHANNEL_CUS_SERVICES_TH = 0x00020005;      // Custom -> Runner Services TH
+static const uint32_t CHANNEL_CUS_SERVICES_WASTE = 0x00080005;   // Custom -> Runner Services Wastelands
+static const uint32_t CHANNEL_CUS_TEAM_10 = 0x00100005;          // Custom -> Searching Team ~10
+static const uint32_t CHANNEL_CUS_TEAM_30 = 0x00200005;          // Custom -> Searching Team ~30
+static const uint32_t CHANNEL_CUS_TEAM_50 = 0x00400005;          // Custom -> Searching Team ~50
+static const uint32_t CHANNEL_CUS_TEAM_70 = 0x00800005;          // Custom -> Searching Team ~70
+static const uint32_t CHANNEL_ADMIN = 0x000000FF;                // Admin chat
+static const uint32_t CHANNEL_GMADMIN = 0x000000FE;                // Admin chat
+static const uint32_t CHANNEL_GMCHAT = 0x000000FD;               // GameMaster chat
+/*
+####################
+   CHANNEL-CODES:
+     (OUTGOING)
+####################
+*/
+static const uint8_t CHAT_BUDDY[] = {0x00, 0x10};
+static const uint8_t CHAT_LOCAL[] =  {0x01, 0x10};
+static const uint8_t CHAT_CLAN[] = {0x02, 0x10};
+static const uint8_t CHAT_TEAM[] = {0x03, 0x10};
+static const uint8_t CHAT_DIRECT[] = {0x04, 0x10};
+static const uint8_t CHAT_ZONE[] = {0x05, 0x00};
+static const uint8_t CHAT_FRAK[] = {0x05, 0x01};
+static const uint8_t CHAT_TRADECS[] = {0x05, 0x05};
+static const uint8_t CHAT_TRADEMB[] = {0x05, 0x03};
+static const uint8_t CHAT_TRADENC[] = {0x05, 0x02};
+static const uint8_t CHAT_TRADETH[] = {0x05, 0x04};
+static const uint8_t CHAT_TRADEWL[] = {0x05, 0x06};
+static const uint8_t CHAT_OOC[] = {0x05, 0x12};
+static const uint8_t CHAT_HELP[] = {0x05, 0x11};
+static const uint8_t CHAT_CLANSEARCH[] = {0x05, 0x10};
+static const uint8_t CHAT_SERVICECS[] =  {0x05, 0x0A};
+static const uint8_t CHAT_SERVICESMB[] = {0x05, 0x08};
+static const uint8_t CHAT_SERVICESNC[] = {0x05, 0x07};
+static const uint8_t CHAT_SERVICESTH[] = {0x05, 0x09};
+static const uint8_t CHAT_SERVICESWL[] = {0x05, 0x0B};
+static const uint8_t CHAT_TEAM10[] = {0x05, 0x0C};
+static const uint8_t CHAT_TEAM30[] = {0x05, 0x0D};
+static const uint8_t CHAT_TEAM50[] = {0x05, 0x0E};
+static const uint8_t CHAT_TEAM70[] = {0x05, 0x0F};
+static const uint8_t CHAT_ADMIN[] = {0xFF, 0x10};
+static const uint8_t CHAT_GMADMIN[] = {0xFE, 0x10};
+static const uint8_t CHAT_GM[] = {0xFD, 0x10};
+
+/*
+####################
+   CHANNEL-CODES:
+(EN/DISABLE-ABLE CHANNELS)
+####################
+*/
+static const uint32_t C_ZONE = 1;
+static const uint32_t C_FRAK = 2;
+static const uint32_t C_TRADENC = 4;
+static const uint32_t C_TRADEMB = 8;
+static const uint32_t C_TRADETH = 16;
+static const uint32_t C_TRADECS = 32;
+static const uint32_t C_TRADEWL = 64;
+static const uint32_t C_SERVICENC = 128;
+static const uint32_t C_SERVICEMB = 256;
+static const uint32_t C_SERVICETH = 512;
+static const uint32_t C_SERVICECS = 1024;
+static const uint32_t C_SERVICEWL = 2048;
+static const uint32_t C_TEAM10 = 4096;
+static const uint32_t C_TEAM30 = 8192;
+static const uint32_t C_TEAM50 = 16384;
+static const uint32_t C_TEAM70 = 32768;
+static const uint32_t C_CLANSEARCH = 65536;
+static const uint32_t C_HELP = 131072;
+static const uint32_t C_OOC = 262144;
index 7011b38..c3e0508 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PClient::PClient( int Index )\r
-{\r
-  mAccountID = 0;\r
-  mAccountLevel = 0;\r
-  mIndex = Index;\r
-  mCharID = 0;\r
-  mConnection = PCC_NONE;\r
-  mRemotePort = 0;\r
-  m_TCPConnection = NULL;\r
-  m_UDPConnection = NULL;\r
-\r
-  for ( int i = 0; i < DEBUG_MODES ; i++ )\r
-    mDebugMode[i] = false;\r
-\r
-  //********\r
-  mAwaitingWarpto = false;\r
-  mTargetX = 0;\r
-  mTargetY = 0;\r
-  mTargetZ = 0;\r
-  //********\r
-  mActorRemoveMode = false;\r
-  mAcceptNPCUpdates = false;\r
-\r
-  testval8 = 0;\r
-}\r
-\r
-PClient::~PClient()\r
-{\r
-  if ( m_TCPConnection )\r
-  {\r
-    delete m_TCPConnection;\r
-    m_TCPConnection = NULL;\r
-  }\r
-  if ( m_UDPConnection )\r
-  {\r
-    delete m_UDPConnection;\r
-    m_UDPConnection = NULL;\r
-  }\r
-}\r
-/// ******************************************************\r
-\r
-bool PClient::GetDebugMode(PDebugMode nDebugID)\r
-{\r
-    return mDebugMode[nDebugID];\r
-}\r
-\r
-bool PClient::IsAcceptingNPCUpdates()\r
-{\r
-    return mAcceptNPCUpdates;\r
-}\r
-\r
-void PClient::SetAcceptNPCUpdates(bool nVal)\r
-{\r
-    mAcceptNPCUpdates = nVal;\r
-}\r
-\r
-bool PClient::IsZoning()\r
-{\r
-    return mZoning;\r
-}\r
-\r
-void PClient::SetZoning(bool nVal)\r
-{\r
-    mZoning = nVal;\r
-    if (!nVal)\r
-        mVhcZoning = false;\r
-}\r
-\r
-bool PClient::IsVhcZoning()\r
-{\r
-    return mVhcZoning;\r
-}\r
-\r
-void PClient::SetVhcZoning(bool nVal)\r
-{\r
-    mVhcZoning = nVal;\r
-}\r
-\r
-uint32_t PClient::GetIndex() const\r
-{\r
-    return mIndex;\r
-}\r
-\r
-uint32_t PClient::GetID() const\r
-{\r
-    return mIndex;\r
-}\r
-\r
-uint32_t PClient::GetLocalID() const\r
-{\r
-    return mIndex + 1;\r
-}\r
-\r
-uint32_t PClient::GetCharID() const\r
-{\r
-    return mCharID;\r
-}\r
-\r
-int PClient::GetRemoteUDPPort() const\r
-{\r
-    return mRemotePort;\r
-}\r
-\r
-bool PClient::IsInRemoveActorMode()\r
-{\r
-    return mActorRemoveMode;\r
-}\r
-\r
-void PClient::SetRemoveActorMode(bool nNewValue)\r
-{\r
-    mActorRemoveMode = nNewValue;\r
-}\r
-\r
-void PClient::SetRemoteUDPPort(int port)\r
-{\r
-    mRemotePort = port;\r
-}\r
-\r
-void PClient::SetCharID(int id)\r
-{\r
-    mCharID = id;\r
-}\r
-\r
-uint16_t PClient::GetUDP_ID()\r
-{\r
-  if ( m_UDPConnection )\r
-    return m_UDPConnection->GetUDP_ID();\r
-  else\r
-    Console->Print( "%s Unable to get UDP_ID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-  return 0;\r
-}\r
-\r
-void PClient::SetUDP_ID( int id )\r
-{\r
-  if ( m_UDPConnection )\r
-    m_UDPConnection->SetUDP_ID( id );\r
-  else\r
-    Console->Print( "%s Unable to set UDP_ID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-}\r
-\r
-void PClient::IncreaseUDP_ID()\r
-{\r
-  if ( m_UDPConnection )\r
-    m_UDPConnection->IncreaseUDP_ID();\r
-  else\r
-    Console->Print( "%s Unable to increase UDP_ID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-}\r
-\r
-uint16_t PClient::GetSessionID()\r
-{\r
-  if ( m_UDPConnection )\r
-    return m_UDPConnection->GetSessionID();\r
-  else\r
-    Console->Print( "%s Unable to get UDP SessionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-  return 0;\r
-}\r
-\r
-uint16_t PClient::GetTransactionID()\r
-{\r
-  if ( m_UDPConnection )\r
-    return m_UDPConnection->GetTransactionID();\r
-  else\r
-    Console->Print( "%s Unable to get UDP TransactionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-  return 0;\r
-}\r
-\r
-void PClient::ResetTransactionID()\r
-{\r
-  if ( m_UDPConnection )\r
-    m_UDPConnection->ResetTransactionID();\r
-  else\r
-    Console->Print( "%s Unable to reset UDP TransactionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-}\r
-\r
-void PClient::IncreaseTransactionID( uint8_t nInc )\r
-{\r
-  if ( m_UDPConnection )\r
-    m_UDPConnection->IncreaseTransactionID( nInc );\r
-  else\r
-    Console->Print( "%s Unable to increase UDP TransactionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-}\r
-\r
-void PClient::FillInUDP_ID( PMessage* nMessage )\r
-{\r
-  uint16_t CurrPos;\r
-\r
-  if (( nMessage->GetSize() > 9 ) && ( nMessage->U8Data( 0x00 ) == 0x13 ) )\r
-  {\r
-    CurrPos = 5;\r
-    while ( CurrPos < nMessage->GetSize() ) // do UDP_ID mgt for each 0x03 subtype subpacket\r
-    {\r
-      if ( nMessage->U8Data( CurrPos + 1 ) == 0x03 )\r
-      {\r
-        IncreaseUDP_ID();\r
-        nMessage->U16Data( CurrPos + 2 ) = GetUDP_ID();\r
-      }\r
-      CurrPos = CurrPos + nMessage->U8Data( CurrPos ) + 1;\r
-    }\r
-  }\r
-  nMessage->U16Data( 0x01 ) = GetUDP_ID();\r
-  nMessage->U16Data( 0x03 ) = GetSessionID();\r
-}\r
-\r
-void PClient::setTCPConnection(ConnectionTCP *conn)\r
-{\r
-    m_TCPConnection = conn;\r
-    m_UDPConnection = nullptr;\r
-    mConnection = PCC_GAME;\r
-}\r
-\r
-void PClient::setUDPConnection(ConnectionUDP *conn)\r
-{\r
-    m_UDPConnection = conn;\r
-}\r
-\r
-ConnectionTCP *PClient::getTCPConn()\r
-{\r
-    return m_TCPConnection;\r
-}\r
-\r
-ConnectionUDP *PClient::getUDPConn()\r
-{\r
-    return m_UDPConnection;\r
-}\r
-\r
-void PClient::SendTCPMessage(PMessage *nMessage)\r
-{\r
-    if (m_TCPConnection)\r
-        m_TCPConnection->SendMessage(nMessage);\r
-    else\r
-        delete nMessage;\r
-}\r
-\r
-void PClient::FragmentAndSendUDPMessage( PMessage* nMessage, uint8_t nType )\r
-{\r
-  PMessage* ChunkBuffer;\r
-  PMessage* ChunkMsg;\r
-  const uint16_t ChunkSize = 220;\r
-  uint16_t StartIncUDPIDOnChunk = 0;\r
-  uint16_t IncludedHeaderSize = 0;\r
-  bool ReplaceFirstByte = false;\r
-  uint8_t ReplaceFirstByteValue = 0;\r
-  uint16_t MultiTriggeringSize = 0;\r
-\r
-  switch ( nType )\r
-  {\r
-    case 0x68: // Terminal ReceiveDB\r
-    {\r
-        ReplaceFirstByte = true;\r
-        ReplaceFirstByteValue = 0x21;\r
-        MultiTriggeringSize = 220;\r
-        IncludedHeaderSize = 9;\r
-        StartIncUDPIDOnChunk = 1;\r
-        break;\r
-    }\r
-    case 0x04:\r
-    {\r
-      Console->Print( RED, BLACK, "[Error] PClient::FragmentAndSendUDPMessage: Message type 0x%02x not managed yet", nType );\r
-      break;\r
-    }\r
-    case 0x05: //CharOpenContainerMsg with header & UDP_ID incremented\r
-    {\r
-      StartIncUDPIDOnChunk = 1;\r
-      IncludedHeaderSize = 9;\r
-      ReplaceFirstByte = true;\r
-      ReplaceFirstByteValue = 0x15;\r
-      MultiTriggeringSize = 230;\r
-      break;\r
-    }\r
-    case 0x06: // For sending Custom LUA Scripts to client\r
-    {\r
-        break;\r
-    }\r
-    case 0x19: //BaselineMsg (with no header)\r
-    {\r
-      break;\r
-    }\r
-    case 0xac: //BuildTraderItemListMsg with header & UDP_ID incremented\r
-    {\r
-      StartIncUDPIDOnChunk = 1;\r
-      IncludedHeaderSize = 9;\r
-      ReplaceFirstByte = true;\r
-      ReplaceFirstByteValue = 0x15;\r
-      MultiTriggeringSize = 230;\r
-      break;\r
-    }\r
-    default:\r
-    {\r
-      Console->Print( RED, BLACK, "[Error] PClient::FragmentAndSendUDPMessage: Message type 0x%02x not managed", nType );\r
-      break;\r
-    }\r
-  }\r
-\r
-  if ( nMessage->GetSize() >= MultiTriggeringSize )\r
-  {\r
-    if ( gDevDebug )\r
-      Console->Print( YELLOW, BLACK, "[Debug] Fragmenting message type 0x%02x", nType );\r
-    if ( ReplaceFirstByte )\r
-    {\r
-      nMessage->U8Data( IncludedHeaderSize ) = ReplaceFirstByteValue;\r
-    }\r
-\r
-    uint16_t ChunksNum = ( nMessage->GetSize() - IncludedHeaderSize + ChunkSize - 1 ) / ChunkSize;\r
-\r
-    for ( uint16_t ChunkID = 0; ChunkID < ChunksNum; ChunkID++ )\r
-    {\r
-      ChunkBuffer = nMessage->GetChunk( IncludedHeaderSize, ChunkSize, ChunkID );\r
-      if ( ChunkBuffer == NULL )\r
-      {\r
-        Console->Print( RED, BLACK, "[Error] PClient::FragmentAndSendUDPMessage: Bad chunk number: %d for size %d", ChunksNum, nMessage->GetSize() );\r
-        break;\r
-      }\r
-\r
-      ChunkMsg = new PMessage( ChunkSize + 15 );\r
-      if ( ChunkID >= StartIncUDPIDOnChunk )\r
-      {\r
-        IncreaseUDP_ID();\r
-      }\r
-\r
-      *ChunkMsg << ( uint8_t )0x13;\r
-      *ChunkMsg << ( uint16_t )GetUDP_ID();\r
-      *ChunkMsg << ( uint16_t )GetSessionID();\r
-      *ChunkMsg << ( uint8_t )( 9 + ChunkBuffer->GetSize() );\r
-      *ChunkMsg << ( uint8_t )0x03;\r
-      *ChunkMsg << ( uint16_t )GetUDP_ID();\r
-      *ChunkMsg << ( uint8_t )0x07; // Fragmented\r
-      *ChunkMsg << ( uint16_t )ChunkID;\r
-      *ChunkMsg << ( uint16_t )ChunksNum;\r
-      *ChunkMsg << ( uint8_t )nType;\r
-      *ChunkMsg << *ChunkBuffer;\r
-\r
-      delete ChunkBuffer;\r
-      //Console->Print(YELLOW, BLACK, "[Debug] Sending Fragment %d/%d", ChunkID+1, ChunksNum);\r
-      //ChunkMsg->Dump();\r
-      SendUDPMessage( ChunkMsg );\r
-    }\r
-    delete nMessage;\r
-  }\r
-  else\r
-  {\r
-    //Console->Print(YELLOW, BLACK, "[Debug] Sending message WITHOUT Fragmenting");\r
-    SendUDPMessage( nMessage );\r
-  }\r
-}\r
-\r
-void PClient::SendUDPMessage(PMessage *nMessage, bool nVIP)\r
-{\r
-    if (m_UDPConnection)\r
-        m_UDPConnection->SendMessage(nMessage, nVIP);\r
-    else\r
-        delete nMessage;\r
-}\r
-\r
-void PClient::SetDebugMode( PDebugMode nDebugID, bool nVal )\r
-{\r
-  if ( nDebugID == DBG_ALL )\r
-  {\r
-    for ( int i = 0; i < DEBUG_MODES ; i++ )\r
-      mDebugMode[i] = nVal;\r
-  }\r
-  else\r
-    mDebugMode[nDebugID] = nVal;\r
-}\r
-\r
-bool PClient::ChangeCharLocation( uint32_t nLocation, bool DoForce )\r
-{\r
-  if ( gDevDebug )\r
-    Console->Print( "%s PClient::ChangeCharLocation", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-  if ( Worlds->IsValidWorld( nLocation ) )\r
-  {\r
-    mAcceptNPCUpdates = false; // Zone changed, reject NPC updates till initial NPC spawn\r
-    PChar* tChar = GetChar();\r
-    uint32_t CurrentLocation = tChar->GetLocation();\r
-    if (( CurrentLocation == nLocation ) && !DoForce )\r
-      return true;\r
-\r
-    // DoForce is used in GM teleport and jail/unjail command to free player from jail\r
-    if (( tChar->IsJailed() == true ) && !DoForce )\r
-    {\r
-      if ( CurrentLocation != 550 && CurrentLocation != 551 ) // If player managed to "get out of jail" somehow, replace him there\r
-      {\r
-        // Do nothing here. This doesnt work as long as we are able to warp the player around just by\r
-        // sending some packets out. Enable/modify this if fixed\r
-        //tChar->SetLocation(550);\r
-      }\r
-      // Player still in 550 or 551 and trying to warp out (by death for example) just\r
-      // return true and let him respawn at 550 entrypoint 0\r
-      //return true;\r
-    }\r
-\r
-    PWorld* nWorld;\r
-    if (( nWorld = Worlds->LeaseWorld( nLocation ) ) )\r
-    {\r
-      if ( tChar->GetLocationLeased() )\r
-      {\r
-        // TAke care of sitting chars\r
-        uint32_t ChairObjectId;\r
-        uint8_t tSeatId;\r
-        PSeatType tSeatType;\r
-        if (( tSeatType = tChar->GetSeatInUse( &ChairObjectId, &tSeatId ) ) )\r
-        {\r
-          bool vhcZoning = false;\r
-          PSpawnedVehicle* tVhc = 0;\r
-          if ( (tSeatType == seat_vhc) && IsVhcZoning() ) // If seat is vhc,\r
-          { // Do  additionnal check\r
-            if (( tVhc = nWorld->GetSpawnedVehicles()->GetVehicle( ChairObjectId ) ) )\r
-            {\r
-              if ( tVhc->GetSeatUser( tSeatId ) == tChar->GetID() )\r
-              {\r
-                vhcZoning = true;\r
-              }\r
-            }\r
-          }\r
-\r
-          if ( ! vhcZoning )\r
-          {\r
-            PUdpCharExitChair::DoLeaveChair( tChar, this, tVhc, true );\r
-          }\r
-          /*{\r
-            Worlds->GetWorld( CurrentLocation )->CharLeaveChair( GetLocalID(), ChairObjectId );\r
-            tChar->SetSeatInUse( seat_none );\r
-          }*/\r
-        }\r
-        this->InitWarpCircle();\r
-        this->InitCharVanish();\r
-        Worlds->ReleaseWorld( CurrentLocation );\r
-      }\r
-      tChar->SetLocation( nLocation );\r
-      tChar->SetLocationLeased();\r
-\r
-      return true;\r
-    }\r
-  }\r
-  else if ( nLocation != 1 ) // try to fall back if bad location\r
-  {\r
-    Console->Print( YELLOW, BLACK, "[Warning] Client %d want to zone to invalid world %d. Falling back to world 1", mIndex, nLocation );\r
-    return ChangeCharLocation( 1, DoForce );\r
-  }\r
-\r
-  return false;\r
-}\r
-\r
-int PClient::GetConnection() const\r
-{\r
-    return mConnection;\r
-}\r
-\r
-const char *PClient::GetAddress() const\r
-{\r
-    return m_TCPConnection->getRemoteAddress();\r
-}\r
-\r
-uint32_t PClient::GetAccountID() const\r
-{\r
-    return mAccountID;\r
-}\r
-\r
-int PClient::GetAccountLevel() const\r
-{\r
-    return mAccountLevel;\r
-}\r
-\r
-void PClient::GameDisconnect()\r
-{\r
-  mAccountID = 0;\r
-\r
-  if ( m_TCPConnection )\r
-  {\r
-    delete m_TCPConnection;\r
-    m_TCPConnection = NULL;\r
-  }\r
-\r
-  if ( m_UDPConnection )\r
-  {\r
-    delete m_UDPConnection;\r
-    m_UDPConnection = NULL;\r
-  }\r
-\r
-  /**** Will be better to put that char-saving-at-disconnect in Char destructor, when only used Chars will be loaded ****/\r
-  PChar *tChar = GetChar();\r
-  if ( tChar )\r
-  {\r
-    SetZoning();\r
-    if ( tChar->GetLocationLeased() )\r
-    {\r
-      if ( tChar->GetSeatInUse() )\r
-      {\r
-        //if(gDevDebug)\r
-          Console->Print( "%s Trying to get leaving char out of her seat", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-        PUdpCharExitChair::DoLeaveChair( tChar, this, NULL, true );\r
-      }\r
-      /* // replaced by the lines above\r
-      PSeatType cSeatType;\r
-      uint32_t cSeatObjectId;\r
-      uint8_t cSeatId;\r
-      PWorld* cWorld;\r
-\r
-      cWorld = Worlds->GetWorld(tChar->GetLocation());\r
-      cSeatType = tChar->GetSeatInUse(&cSeatObjectId, &cSeatId);\r
-      if(cSeatType)\r
-      {\r
-        if(cSeatType == seat_chair)\r
-        {\r
-          cWorld->CharLeaveChair(GetLocalID(), cSeatObjectId);\r
-          tChar->SetSeatInUse(seat_none);\r
-        }\r
-        else if(cSeatType == seat_subway)\r
-        {\r
-          Subway->UnsetSeatUser(cSeatObjectId, cSeatId, GetLocalID());\r
-          tChar->SetSeatInUse(seat_none);\r
-        }\r
-        else if(cSeatType == seat_vhc)\r
-        {\r
-          cWorld->GetSpawnedVehicles()->GetVehicle(cSeatObjectId)->UnsetSeatUser(cSeatId, GetLocalID());\r
-          tChar->SetSeatInUse(seat_none);\r
-        }\r
-        else\r
-        {\r
-          Console->Print(RED, BLACK, "[Notice] PClient::GameDisconnect : Leaving seat of unkown type %d", cSeatType);\r
-        }\r
-      }\r
-      */\r
-    }\r
-\r
-    if ( tChar->IsDirty() )\r
-    {\r
-      bool res = tChar->SQLSave();\r
-      if ( res )\r
-        Console->Print( "%s GameDisconnect: Char %i (Client %i) saved before disconnect.", Console->ColorText( GREEN, BLACK, "[DEBUG]" ),  tChar->GetID(), mIndex );\r
-      else\r
-        Console->Print( RED, BLACK, "[DEBUG] GameDisconnect: Char %i (Client %i) saving before disconnect and FAILED.", tChar->GetID(), mIndex );\r
-    }\r
-    else\r
-    {\r
-      Console->Print( "%s GameDisconnect: Char %i (Client %i) no save needed.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), tChar->GetID(), mIndex );\r
-      if ( !tChar->IsOnline() )\r
-        Console->Print( "%s GameDisconnect: Char %i (Client %i) wasn't marked as ingame anyway...", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), tChar->GetID(), mIndex );\r
-    }\r
-\r
-    if ( tChar->GetLocationLeased() )\r
-    {\r
-      if ( gDevDebug )\r
-        Console->Print( "%s Sending char leaving effect", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-      InitWarpCircle();\r
-      InitCharVanish();\r
-\r
-      Worlds->ReleaseWorld( tChar->GetLocation() );\r
-      tChar->SetLocationLeased( false );\r
-    }\r
-\r
-    Chars->RemoveChar( mCharID );\r
-    delete tChar;\r
-    mCharID = 0;\r
-  }\r
-  else\r
-  {\r
-    //Console->Print(YELLOW, BLACK, "GameDisconnect: Client %i had no char online.", mIndex);\r
-  }\r
-  /**********************************/\r
-\r
-  //mConnection &= ~PCC_GAME;\r
-  mConnection = PCC_NONE;\r
-}\r
-\r
-void PClient::RefreshAccountInfo( PAccount *Account )\r
-{\r
-  mAccountID = Account->GetID();\r
-  mAccountLevel = Account->GetLevel();\r
-}\r
-\r
-void PClient::LoggedIn(PAccount *Account)\r
-{\r
-    RefreshAccountInfo(Account);\r
-}\r
-\r
-void PClient::Update()\r
-{\r
-  if ( m_TCPConnection )\r
-  {\r
-    if ( m_TCPConnection->timeOut() )\r
-    {\r
-      Console->Print( "%s GameSocket: Client %i: timeout", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), mIndex );\r
-      GameServer->ClientDisconnected( this );\r
-    }\r
-    else\r
-    {\r
-      if ( !m_TCPConnection->update() )\r
-      {\r
-        GameServer->ClientDisconnected( this );\r
-      }\r
-    }\r
-  }\r
-\r
-  if ( m_UDPConnection )\r
-  {\r
-    if ( m_UDPConnection->timeOut() )\r
-    {\r
-      Console->Print( "%s Game UDP: Client %i: timeout", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), mIndex );\r
-      GameServer->UDPStreamClosed( this );\r
-    }\r
-    else\r
-    {\r
-      if ( !m_UDPConnection->update() )\r
-      {\r
-        GameServer->UDPStreamClosed( this );\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-PChar* PClient::GetChar() const\r
-{\r
-  if ( mCharID )\r
-  {\r
-    return Chars->GetChar( mCharID );\r
-  }\r
-  else\r
-  {\r
-    return NULL;\r
-  }\r
-}\r
-\r
-int PClient::getZoneID() const\r
-{\r
-    return m_ZoneID;\r
-}\r
-\r
-void PClient::SetAwaitingWarpto(bool yesno, uint16_t NewX, uint16_t NewY, uint16_t NewZ)\r
-{\r
-    mAwaitingWarpto = yesno;\r
-    mTargetX = NewX;\r
-    mTargetY = NewY;\r
-    mTargetZ = NewZ;\r
-}\r
-\r
-bool PClient::GetCharAwaitingWarpto( uint16_t* PosX, uint16_t* PosY, uint16_t* PosZ )\r
-{\r
-  if ( PosX )\r
-    *PosX = mTargetX;\r
-  if ( PosY )\r
-    *PosY = mTargetY;\r
-  if ( PosZ )\r
-    *PosZ = mTargetZ;\r
-\r
-  return mAwaitingWarpto;\r
-  /*\r
-    if(mAwaitingWarpto == true)\r
-    {\r
-\r
-        // Position update doesnt work. Uncomment&Change function if ever required again\r
-        mAwaitingWarpto = false;\r
-            (GetChar()->Coords).mX = mTargetX;\r
-            (GetChar()->Coords).mY = mTargetY;\r
-            (GetChar()->Coords).mZ = mTargetZ;\r
-        return true;\r
-  //        PMessage* tmpMsg_posupdate;\r
-  //\r
-  //        tmpMsg_posupdate = MsgBuilder->BuildCharPosMoveMsg(this, mTargetX, mTargetY, mTargetZ);\r
-  //        ClientManager->UDPBroadcast(tmpMsg_posupdate, this);\r
-  //        tmpMsg_posupdate = NULL;\r
-    }\r
-    return false;\r
-  */\r
-}\r
-\r
-void PClient::InitWarpCircle()\r
-{\r
-  PMessage* tmpMsg_circle = MsgBuilder->BuildCharShowGlowCircleMsg( this );\r
-  ClientManager->UDPBroadcast( tmpMsg_circle, this, 1000, true ); // send only in a 1000 radius\r
-}\r
-\r
-void PClient::InitCharVanish()\r
-{\r
-  PMessage* tmpMsg_vanish = MsgBuilder->BuildRemoveWorldObjectMsg( GetLocalID() );\r
-  ClientManager->UDPBroadcast( tmpMsg_vanish, this, 0, true );\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PClient::PClient( int Index )
+{
+  mAccountID = 0;
+  mAccountLevel = 0;
+  mIndex = Index;
+  mCharID = 0;
+  mConnection = PCC_NONE;
+  mRemotePort = 0;
+  m_TCPConnection = NULL;
+  m_UDPConnection = NULL;
+
+  for ( int i = 0; i < DEBUG_MODES ; i++ )
+    mDebugMode[i] = false;
+
+  //********
+  mAwaitingWarpto = false;
+  mTargetX = 0;
+  mTargetY = 0;
+  mTargetZ = 0;
+  //********
+  mActorRemoveMode = false;
+  mAcceptNPCUpdates = false;
+
+  testval8 = 0;
+}
+
+PClient::~PClient()
+{
+  if ( m_TCPConnection )
+  {
+    delete m_TCPConnection;
+    m_TCPConnection = NULL;
+  }
+  if ( m_UDPConnection )
+  {
+    delete m_UDPConnection;
+    m_UDPConnection = NULL;
+  }
+}
+/// ******************************************************
+
+bool PClient::GetDebugMode(PDebugMode nDebugID)
+{
+    return mDebugMode[nDebugID];
+}
+
+bool PClient::IsAcceptingNPCUpdates()
+{
+    return mAcceptNPCUpdates;
+}
+
+void PClient::SetAcceptNPCUpdates(bool nVal)
+{
+    mAcceptNPCUpdates = nVal;
+}
+
+bool PClient::IsZoning()
+{
+    return mZoning;
+}
+
+void PClient::SetZoning(bool nVal)
+{
+    mZoning = nVal;
+    if (!nVal)
+        mVhcZoning = false;
+}
+
+bool PClient::IsVhcZoning()
+{
+    return mVhcZoning;
+}
+
+void PClient::SetVhcZoning(bool nVal)
+{
+    mVhcZoning = nVal;
+}
+
+uint32_t PClient::GetIndex() const
+{
+    return mIndex;
+}
+
+uint32_t PClient::GetID() const
+{
+    return mIndex;
+}
+
+uint32_t PClient::GetLocalID() const
+{
+    return mIndex + 1;
+}
+
+uint32_t PClient::GetCharID() const
+{
+    return mCharID;
+}
+
+int PClient::GetRemoteUDPPort() const
+{
+    return mRemotePort;
+}
+
+bool PClient::IsInRemoveActorMode()
+{
+    return mActorRemoveMode;
+}
+
+void PClient::SetRemoveActorMode(bool nNewValue)
+{
+    mActorRemoveMode = nNewValue;
+}
+
+void PClient::SetRemoteUDPPort(int port)
+{
+    mRemotePort = port;
+}
+
+void PClient::SetCharID(int id)
+{
+    mCharID = id;
+}
+
+uint16_t PClient::GetUDP_ID()
+{
+  if ( m_UDPConnection )
+    return m_UDPConnection->GetUDP_ID();
+  else
+    Console->Print( "%s Unable to get UDP_ID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+  return 0;
+}
+
+void PClient::SetUDP_ID( int id )
+{
+  if ( m_UDPConnection )
+    m_UDPConnection->SetUDP_ID( id );
+  else
+    Console->Print( "%s Unable to set UDP_ID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+}
+
+void PClient::IncreaseUDP_ID()
+{
+  if ( m_UDPConnection )
+    m_UDPConnection->IncreaseUDP_ID();
+  else
+    Console->Print( "%s Unable to increase UDP_ID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+}
+
+uint16_t PClient::GetSessionID()
+{
+  if ( m_UDPConnection )
+    return m_UDPConnection->GetSessionID();
+  else
+    Console->Print( "%s Unable to get UDP SessionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+  return 0;
+}
+
+uint16_t PClient::GetTransactionID()
+{
+  if ( m_UDPConnection )
+    return m_UDPConnection->GetTransactionID();
+  else
+    Console->Print( "%s Unable to get UDP TransactionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+  return 0;
+}
+
+void PClient::ResetTransactionID()
+{
+  if ( m_UDPConnection )
+    m_UDPConnection->ResetTransactionID();
+  else
+    Console->Print( "%s Unable to reset UDP TransactionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+}
+
+void PClient::IncreaseTransactionID( uint8_t nInc )
+{
+  if ( m_UDPConnection )
+    m_UDPConnection->IncreaseTransactionID( nInc );
+  else
+    Console->Print( "%s Unable to increase UDP TransactionID, UDP ConnectionClass is not yet initialized!", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+}
+
+void PClient::FillInUDP_ID( PMessage* nMessage )
+{
+  uint16_t CurrPos;
+
+  if (( nMessage->GetSize() > 9 ) && ( nMessage->U8Data( 0x00 ) == 0x13 ) )
+  {
+    CurrPos = 5;
+    while ( CurrPos < nMessage->GetSize() ) // do UDP_ID mgt for each 0x03 subtype subpacket
+    {
+      if ( nMessage->U8Data( CurrPos + 1 ) == 0x03 )
+      {
+        IncreaseUDP_ID();
+        nMessage->U16Data( CurrPos + 2 ) = GetUDP_ID();
+      }
+      CurrPos = CurrPos + nMessage->U8Data( CurrPos ) + 1;
+    }
+  }
+  nMessage->U16Data( 0x01 ) = GetUDP_ID();
+  nMessage->U16Data( 0x03 ) = GetSessionID();
+}
+
+void PClient::setTCPConnection(ConnectionTCP *conn)
+{
+    m_TCPConnection = conn;
+    m_UDPConnection = nullptr;
+    mConnection = PCC_GAME;
+}
+
+void PClient::setUDPConnection(ConnectionUDP *conn)
+{
+    m_UDPConnection = conn;
+}
+
+ConnectionTCP *PClient::getTCPConn()
+{
+    return m_TCPConnection;
+}
+
+ConnectionUDP *PClient::getUDPConn()
+{
+    return m_UDPConnection;
+}
+
+void PClient::SendTCPMessage(PMessage *nMessage)
+{
+    if (m_TCPConnection)
+        m_TCPConnection->SendMessage(nMessage);
+    else
+        delete nMessage;
+}
+
+void PClient::FragmentAndSendUDPMessage( PMessage* nMessage, uint8_t nType )
+{
+  PMessage* ChunkBuffer;
+  PMessage* ChunkMsg;
+  const uint16_t ChunkSize = 220;
+  uint16_t StartIncUDPIDOnChunk = 0;
+  uint16_t IncludedHeaderSize = 0;
+  bool ReplaceFirstByte = false;
+  uint8_t ReplaceFirstByteValue = 0;
+  uint16_t MultiTriggeringSize = 0;
+
+  switch ( nType )
+  {
+    case 0x68: // Terminal ReceiveDB
+    {
+        ReplaceFirstByte = true;
+        ReplaceFirstByteValue = 0x21;
+        MultiTriggeringSize = 220;
+        IncludedHeaderSize = 9;
+        StartIncUDPIDOnChunk = 1;
+        break;
+    }
+    case 0x04:
+    {
+      Console->Print( RED, BLACK, "[Error] PClient::FragmentAndSendUDPMessage: Message type 0x%02x not managed yet", nType );
+      break;
+    }
+    case 0x05: //CharOpenContainerMsg with header & UDP_ID incremented
+    {
+      StartIncUDPIDOnChunk = 1;
+      IncludedHeaderSize = 9;
+      ReplaceFirstByte = true;
+      ReplaceFirstByteValue = 0x15;
+      MultiTriggeringSize = 230;
+      break;
+    }
+    case 0x06: // For sending Custom LUA Scripts to client
+    {
+        break;
+    }
+    case 0x19: //BaselineMsg (with no header)
+    {
+      break;
+    }
+    case 0xac: //BuildTraderItemListMsg with header & UDP_ID incremented
+    {
+      StartIncUDPIDOnChunk = 1;
+      IncludedHeaderSize = 9;
+      ReplaceFirstByte = true;
+      ReplaceFirstByteValue = 0x15;
+      MultiTriggeringSize = 230;
+      break;
+    }
+    default:
+    {
+      Console->Print( RED, BLACK, "[Error] PClient::FragmentAndSendUDPMessage: Message type 0x%02x not managed", nType );
+      break;
+    }
+  }
+
+  if ( nMessage->GetSize() >= MultiTriggeringSize )
+  {
+    if ( gDevDebug )
+      Console->Print( YELLOW, BLACK, "[Debug] Fragmenting message type 0x%02x", nType );
+    if ( ReplaceFirstByte )
+    {
+      nMessage->U8Data( IncludedHeaderSize ) = ReplaceFirstByteValue;
+    }
+
+    uint16_t ChunksNum = ( nMessage->GetSize() - IncludedHeaderSize + ChunkSize - 1 ) / ChunkSize;
+
+    for ( uint16_t ChunkID = 0; ChunkID < ChunksNum; ChunkID++ )
+    {
+      ChunkBuffer = nMessage->GetChunk( IncludedHeaderSize, ChunkSize, ChunkID );
+      if ( ChunkBuffer == NULL )
+      {
+        Console->Print( RED, BLACK, "[Error] PClient::FragmentAndSendUDPMessage: Bad chunk number: %d for size %d", ChunksNum, nMessage->GetSize() );
+        break;
+      }
+
+      ChunkMsg = new PMessage( ChunkSize + 15 );
+      if ( ChunkID >= StartIncUDPIDOnChunk )
+      {
+        IncreaseUDP_ID();
+      }
+
+      *ChunkMsg << ( uint8_t )0x13;
+      *ChunkMsg << ( uint16_t )GetUDP_ID();
+      *ChunkMsg << ( uint16_t )GetSessionID();
+      *ChunkMsg << ( uint8_t )( 9 + ChunkBuffer->GetSize() );
+      *ChunkMsg << ( uint8_t )0x03;
+      *ChunkMsg << ( uint16_t )GetUDP_ID();
+      *ChunkMsg << ( uint8_t )0x07; // Fragmented
+      *ChunkMsg << ( uint16_t )ChunkID;
+      *ChunkMsg << ( uint16_t )ChunksNum;
+      *ChunkMsg << ( uint8_t )nType;
+      *ChunkMsg << *ChunkBuffer;
+
+      delete ChunkBuffer;
+      //Console->Print(YELLOW, BLACK, "[Debug] Sending Fragment %d/%d", ChunkID+1, ChunksNum);
+      //ChunkMsg->Dump();
+      SendUDPMessage( ChunkMsg );
+    }
+    delete nMessage;
+  }
+  else
+  {
+    //Console->Print(YELLOW, BLACK, "[Debug] Sending message WITHOUT Fragmenting");
+    SendUDPMessage( nMessage );
+  }
+}
+
+void PClient::SendUDPMessage(PMessage *nMessage, bool nVIP)
+{
+    if (m_UDPConnection)
+        m_UDPConnection->SendMessage(nMessage, nVIP);
+    else
+        delete nMessage;
+}
+
+void PClient::SetDebugMode( PDebugMode nDebugID, bool nVal )
+{
+  if ( nDebugID == DBG_ALL )
+  {
+    for ( int i = 0; i < DEBUG_MODES ; i++ )
+      mDebugMode[i] = nVal;
+  }
+  else
+    mDebugMode[nDebugID] = nVal;
+}
+
+bool PClient::ChangeCharLocation( uint32_t nLocation, bool DoForce )
+{
+  if ( gDevDebug )
+    Console->Print( "%s PClient::ChangeCharLocation", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+  if ( Worlds->IsValidWorld( nLocation ) )
+  {
+    mAcceptNPCUpdates = false; // Zone changed, reject NPC updates till initial NPC spawn
+    PChar* tChar = GetChar();
+    uint32_t CurrentLocation = tChar->GetLocation();
+    if (( CurrentLocation == nLocation ) && !DoForce )
+      return true;
+
+    // DoForce is used in GM teleport and jail/unjail command to free player from jail
+    if (( tChar->IsJailed() == true ) && !DoForce )
+    {
+      if ( CurrentLocation != 550 && CurrentLocation != 551 ) // If player managed to "get out of jail" somehow, replace him there
+      {
+        // Do nothing here. This doesnt work as long as we are able to warp the player around just by
+        // sending some packets out. Enable/modify this if fixed
+        //tChar->SetLocation(550);
+      }
+      // Player still in 550 or 551 and trying to warp out (by death for example) just
+      // return true and let him respawn at 550 entrypoint 0
+      //return true;
+    }
+
+    PWorld* nWorld;
+    if (( nWorld = Worlds->LeaseWorld( nLocation ) ) )
+    {
+      if ( tChar->GetLocationLeased() )
+      {
+        // TAke care of sitting chars
+        uint32_t ChairObjectId;
+        uint8_t tSeatId;
+        PSeatType tSeatType;
+        if (( tSeatType = tChar->GetSeatInUse( &ChairObjectId, &tSeatId ) ) )
+        {
+          bool vhcZoning = false;
+          PSpawnedVehicle* tVhc = 0;
+          if ( (tSeatType == seat_vhc) && IsVhcZoning() ) // If seat is vhc,
+          { // Do  additionnal check
+            if (( tVhc = nWorld->GetSpawnedVehicles()->GetVehicle( ChairObjectId ) ) )
+            {
+              if ( tVhc->GetSeatUser( tSeatId ) == tChar->GetID() )
+              {
+                vhcZoning = true;
+              }
+            }
+          }
+
+          if ( ! vhcZoning )
+          {
+            PUdpCharExitChair::DoLeaveChair( tChar, this, tVhc, true );
+          }
+          /*{
+            Worlds->GetWorld( CurrentLocation )->CharLeaveChair( GetLocalID(), ChairObjectId );
+            tChar->SetSeatInUse( seat_none );
+          }*/
+        }
+        this->InitWarpCircle();
+        this->InitCharVanish();
+        Worlds->ReleaseWorld( CurrentLocation );
+      }
+      tChar->SetLocation( nLocation );
+      tChar->SetLocationLeased();
+
+      return true;
+    }
+  }
+  else if ( nLocation != 1 ) // try to fall back if bad location
+  {
+    Console->Print( YELLOW, BLACK, "[Warning] Client %d want to zone to invalid world %d. Falling back to world 1", mIndex, nLocation );
+    return ChangeCharLocation( 1, DoForce );
+  }
+
+  return false;
+}
+
+int PClient::GetConnection() const
+{
+    return mConnection;
+}
+
+const char *PClient::GetAddress() const
+{
+    return m_TCPConnection->getRemoteAddress();
+}
+
+uint32_t PClient::GetAccountID() const
+{
+    return mAccountID;
+}
+
+int PClient::GetAccountLevel() const
+{
+    return mAccountLevel;
+}
+
+void PClient::GameDisconnect()
+{
+  mAccountID = 0;
+
+  if ( m_TCPConnection )
+  {
+    delete m_TCPConnection;
+    m_TCPConnection = NULL;
+  }
+
+  if ( m_UDPConnection )
+  {
+    delete m_UDPConnection;
+    m_UDPConnection = NULL;
+  }
+
+  /**** Will be better to put that char-saving-at-disconnect in Char destructor, when only used Chars will be loaded ****/
+  PChar *tChar = GetChar();
+  if ( tChar )
+  {
+    SetZoning();
+    if ( tChar->GetLocationLeased() )
+    {
+      if ( tChar->GetSeatInUse() )
+      {
+        //if(gDevDebug)
+          Console->Print( "%s Trying to get leaving char out of her seat", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+        PUdpCharExitChair::DoLeaveChair( tChar, this, NULL, true );
+      }
+      /* // replaced by the lines above
+      PSeatType cSeatType;
+      uint32_t cSeatObjectId;
+      uint8_t cSeatId;
+      PWorld* cWorld;
+
+      cWorld = Worlds->GetWorld(tChar->GetLocation());
+      cSeatType = tChar->GetSeatInUse(&cSeatObjectId, &cSeatId);
+      if(cSeatType)
+      {
+        if(cSeatType == seat_chair)
+        {
+          cWorld->CharLeaveChair(GetLocalID(), cSeatObjectId);
+          tChar->SetSeatInUse(seat_none);
+        }
+        else if(cSeatType == seat_subway)
+        {
+          Subway->UnsetSeatUser(cSeatObjectId, cSeatId, GetLocalID());
+          tChar->SetSeatInUse(seat_none);
+        }
+        else if(cSeatType == seat_vhc)
+        {
+          cWorld->GetSpawnedVehicles()->GetVehicle(cSeatObjectId)->UnsetSeatUser(cSeatId, GetLocalID());
+          tChar->SetSeatInUse(seat_none);
+        }
+        else
+        {
+          Console->Print(RED, BLACK, "[Notice] PClient::GameDisconnect : Leaving seat of unkown type %d", cSeatType);
+        }
+      }
+      */
+    }
+
+    if ( tChar->IsDirty() )
+    {
+      bool res = tChar->SQLSave();
+      if ( res )
+        Console->Print( "%s GameDisconnect: Char %i (Client %i) saved before disconnect.", Console->ColorText( GREEN, BLACK, "[DEBUG]" ),  tChar->GetID(), mIndex );
+      else
+        Console->Print( RED, BLACK, "[DEBUG] GameDisconnect: Char %i (Client %i) saving before disconnect and FAILED.", tChar->GetID(), mIndex );
+    }
+    else
+    {
+      Console->Print( "%s GameDisconnect: Char %i (Client %i) no save needed.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), tChar->GetID(), mIndex );
+      if ( !tChar->IsOnline() )
+        Console->Print( "%s GameDisconnect: Char %i (Client %i) wasn't marked as ingame anyway...", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), tChar->GetID(), mIndex );
+    }
+
+    if ( tChar->GetLocationLeased() )
+    {
+      if ( gDevDebug )
+        Console->Print( "%s Sending char leaving effect", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+      InitWarpCircle();
+      InitCharVanish();
+
+      Worlds->ReleaseWorld( tChar->GetLocation() );
+      tChar->SetLocationLeased( false );
+    }
+
+    Chars->RemoveChar( mCharID );
+    delete tChar;
+    mCharID = 0;
+  }
+  else
+  {
+    //Console->Print(YELLOW, BLACK, "GameDisconnect: Client %i had no char online.", mIndex);
+  }
+  /**********************************/
+
+  //mConnection &= ~PCC_GAME;
+  mConnection = PCC_NONE;
+}
+
+void PClient::RefreshAccountInfo( PAccount *Account )
+{
+  mAccountID = Account->GetID();
+  mAccountLevel = Account->GetLevel();
+}
+
+void PClient::LoggedIn(PAccount *Account)
+{
+    RefreshAccountInfo(Account);
+}
+
+void PClient::Update()
+{
+  if ( m_TCPConnection )
+  {
+    if ( m_TCPConnection->timeOut() )
+    {
+      Console->Print( "%s GameSocket: Client %i: timeout", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), mIndex );
+      GameServer->ClientDisconnected( this );
+    }
+    else
+    {
+      if ( !m_TCPConnection->update() )
+      {
+        GameServer->ClientDisconnected( this );
+      }
+    }
+  }
+
+  if ( m_UDPConnection )
+  {
+    if ( m_UDPConnection->timeOut() )
+    {
+      Console->Print( "%s Game UDP: Client %i: timeout", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), mIndex );
+      GameServer->UDPStreamClosed( this );
+    }
+    else
+    {
+      if ( !m_UDPConnection->update() )
+      {
+        GameServer->UDPStreamClosed( this );
+      }
+    }
+  }
+}
+
+PChar* PClient::GetChar() const
+{
+  if ( mCharID )
+  {
+    return Chars->GetChar( mCharID );
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+int PClient::getZoneID() const
+{
+    return m_ZoneID;
+}
+
+void PClient::SetAwaitingWarpto(bool yesno, uint16_t NewX, uint16_t NewY, uint16_t NewZ)
+{
+    mAwaitingWarpto = yesno;
+    mTargetX = NewX;
+    mTargetY = NewY;
+    mTargetZ = NewZ;
+}
+
+bool PClient::GetCharAwaitingWarpto( uint16_t* PosX, uint16_t* PosY, uint16_t* PosZ )
+{
+  if ( PosX )
+    *PosX = mTargetX;
+  if ( PosY )
+    *PosY = mTargetY;
+  if ( PosZ )
+    *PosZ = mTargetZ;
+
+  return mAwaitingWarpto;
+  /*
+    if(mAwaitingWarpto == true)
+    {
+
+        // Position update doesnt work. Uncomment&Change function if ever required again
+        mAwaitingWarpto = false;
+            (GetChar()->Coords).mX = mTargetX;
+            (GetChar()->Coords).mY = mTargetY;
+            (GetChar()->Coords).mZ = mTargetZ;
+        return true;
+  //        PMessage* tmpMsg_posupdate;
+  //
+  //        tmpMsg_posupdate = MsgBuilder->BuildCharPosMoveMsg(this, mTargetX, mTargetY, mTargetZ);
+  //        ClientManager->UDPBroadcast(tmpMsg_posupdate, this);
+  //        tmpMsg_posupdate = NULL;
+    }
+    return false;
+  */
+}
+
+void PClient::InitWarpCircle()
+{
+  PMessage* tmpMsg_circle = MsgBuilder->BuildCharShowGlowCircleMsg( this );
+  ClientManager->UDPBroadcast( tmpMsg_circle, this, 1000, true ); // send only in a 1000 radius
+}
+
+void PClient::InitCharVanish()
+{
+  PMessage* tmpMsg_vanish = MsgBuilder->BuildRemoveWorldObjectMsg( GetLocalID() );
+  ClientManager->UDPBroadcast( tmpMsg_vanish, this, 0, true );
+}
index 3dbcf57..e56d96e 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class ConnectionTCP;\r
-class ConnectionUDP;\r
-class PMessage;\r
-\r
-//  TODO: - check that SetUDP_ID, and the mSessionID(UDP_ID_HIGH) real use,\r
-//          and if UDP_ID and mSessionID must be synced (like in NeoX) or not\r
-\r
-enum PClientConnection\r
-{\r
-  PCC_NONE = 0,\r
-  PCC_GAME = 1\r
-};\r
-\r
-// AccountLevel handling is part of accounts.cpp\r
-/*\r
-enum PClientLevel\r
-{\r
- PCL_BANNED = -1,\r
- PCL_UNREGPLAYER = 0,\r
- PCL_REGPLAYER = 1,\r
- PCL_VOLUNTEER = 30,\r
- PCL_GM = 50,\r
- PCL_ADMIN = 100\r
-};\r
-*/\r
-#define DEBUG_MODES 3\r
-enum PDebugMode\r
-{\r
-  DBG_LOCATION = 0,\r
-  DBG_ITEMID = 1,\r
-  DBG_SUBWAY = 2,\r
-  DBG_ALL = DEBUG_MODES // must always be last, with DEBUG_MODES updated as needed\r
-};\r
-\r
-\r
-class PClient\r
-{\r
-  private :\r
-    ConnectionTCP* m_TCPConnection;\r
-    ConnectionUDP* m_UDPConnection;\r
-\r
-    uint32_t mAccountID;\r
-    int mAccountLevel;\r
-    uint32_t mIndex;\r
-    uint32_t mCharID;\r
-\r
-//  uint16_t mUDP_ID;\r
-//  uint16_t mSessionID;\r
-//  uint16_t mTransactionID;\r
-\r
-    // AccountLevel handling is part of accounts.cpp\r
-    //PClientLevel mLevel;\r
-    int mConnection;\r
-    int mRemotePort;\r
-\r
-    bool mDebugMode[DEBUG_MODES];\r
-    // new multiuser-chat implementation //\r
-    int m_ZoneID;\r
-    //int[4] m_IP;\r
-\r
-    //*******\r
-    bool mActorRemoveMode;\r
-    //*******\r
-    bool mAwaitingWarpto;\r
-    uint16_t mTargetX;\r
-    uint16_t mTargetY;\r
-    uint16_t mTargetZ;\r
-    //*******\r
-    bool mAcceptNPCUpdates;\r
-    bool mZoning;\r
-    bool mVhcZoning;\r
-\r
-  public :\r
-    PClient( int Index );\r
-    ~PClient();\r
-\r
-    bool GetDebugMode(PDebugMode nDebugID);\r
-    void SetDebugMode(PDebugMode nDebugID, bool nVal = true);\r
-\r
-    bool IsAcceptingNPCUpdates();\r
-    void SetAcceptNPCUpdates(bool nVal);\r
-    bool IsZoning();\r
-    void SetZoning(bool nVal = true);\r
-    bool IsVhcZoning();\r
-    void SetVhcZoning(bool nVal = true);\r
-\r
-    uint32_t GetIndex() const; // better use GetID()\r
-    uint32_t GetID() const; // for better coherency with other classes\r
-    uint32_t GetLocalID() const;\r
-    uint32_t GetCharID() const;\r
-    PChar* GetChar() const;\r
-    bool ChangeCharLocation(uint32_t nLocation, bool DoForce = false);\r
-\r
-    int GetRemoteUDPPort() const; // Temp solution\r
-\r
-    bool IsInRemoveActorMode();\r
-    void SetRemoveActorMode(bool nNewValue);\r
-\r
-    void SetRemoteUDPPort(int port); // Temp solution\r
-    void SetCharID(int id);//NEW added\r
-\r
-    /*\r
-        inline uint16_t GetUDP_ID() const { return mUDP_ID; }\r
-        inline uint16_t GetSessionID() const { return SESSION_UDP_OFFSET + mUDP_ID ; }\r
-        inline uint16_t GetTransactionID() {return mTransactionID; }\r
-        void SetUDP_ID(int id);\r
-        inline void IncreaseUDP_ID() { SetUDP_ID(mUDP_ID + 1); }\r
-        inline void ResetTransactionID() { mTransactionID = 10170; }\r
-\r
-        inline void IncreaseTransactionID(uint8_t nInc = 1) { mTransactionID += nInc; }\r
-    */\r
-\r
-    // All outgoing ID's and stuff is now part of the ConnectionUDP class itself!\r
-    //    (which is not so good.... comment from Hammag)\r
-    // However, we still have full access to it through these functions\r
-    uint16_t GetUDP_ID();\r
-    void SetUDP_ID( int id );\r
-    void IncreaseUDP_ID();\r
-\r
-    uint16_t GetSessionID();\r
-\r
-    uint16_t GetTransactionID();\r
-    void ResetTransactionID();\r
-    void IncreaseTransactionID( uint8_t nInc = 1 );\r
-\r
-    void FillInUDP_ID( PMessage* nMessage );\r
-\r
-// ************************************************************************ //\r
-    // AccountLevel handling is part of accounts.cpp\r
-    //inline PClientLevel GetLevel() const { return mLevel; }\r
-\r
-    void setTCPConnection(ConnectionTCP *conn);\r
-    void setUDPConnection(ConnectionUDP *conn);\r
-\r
-    ConnectionTCP* getTCPConn();\r
-    ConnectionUDP* getUDPConn();\r
-\r
-    void SendTCPMessage(PMessage *nMessage);\r
-    void FragmentAndSendUDPMessage( PMessage* nMessage, uint8_t nType );\r
-    void SendUDPMessage(PMessage *nMessage, bool nVIP = false);\r
-\r
-    int GetConnection() const;\r
-    const char *GetAddress() const;\r
-    uint32_t GetAccountID() const;\r
-    int GetAccountLevel() const;\r
-\r
-    void GameDisconnect();\r
-\r
-    void RefreshAccountInfo(PAccount *Account);\r
-    void LoggedIn(PAccount *Account);\r
-    void Update();\r
-\r
-    // new multiuser-chat implementation //\r
-    int getZoneID() const;\r
-    //inline int* getIP() const { return (int*) m_IP; }\r
-\r
-    void SetAwaitingWarpto(bool yesno, uint16_t NewX, uint16_t NewY, uint16_t NewZ);\r
-    bool GetCharAwaitingWarpto(uint16_t* PosX = NULL, uint16_t* PosY = NULL, uint16_t* PosZ = NULL);\r
-\r
-    // Char broadcasted effects\r
-    void InitWarpCircle();\r
-    void InitCharVanish();\r
-\r
-    // used for dynamic ingame testing\r
-    uint8_t testval8;\r
-    uint16_t testval16;\r
-    uint32_t testval32;\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+class ConnectionTCP;
+class ConnectionUDP;
+class PMessage;
+
+//  TODO: - check that SetUDP_ID, and the mSessionID(UDP_ID_HIGH) real use,
+//          and if UDP_ID and mSessionID must be synced (like in NeoX) or not
+
+enum PClientConnection
+{
+  PCC_NONE = 0,
+  PCC_GAME = 1
+};
+
+// AccountLevel handling is part of accounts.cpp
+/*
+enum PClientLevel
+{
+ PCL_BANNED = -1,
+ PCL_UNREGPLAYER = 0,
+ PCL_REGPLAYER = 1,
+ PCL_VOLUNTEER = 30,
+ PCL_GM = 50,
+ PCL_ADMIN = 100
+};
+*/
+#define DEBUG_MODES 3
+enum PDebugMode
+{
+  DBG_LOCATION = 0,
+  DBG_ITEMID = 1,
+  DBG_SUBWAY = 2,
+  DBG_ALL = DEBUG_MODES // must always be last, with DEBUG_MODES updated as needed
+};
+
+
+class PClient
+{
+  private :
+    ConnectionTCP* m_TCPConnection;
+    ConnectionUDP* m_UDPConnection;
+
+    uint32_t mAccountID;
+    int mAccountLevel;
+    uint32_t mIndex;
+    uint32_t mCharID;
+
+//  uint16_t mUDP_ID;
+//  uint16_t mSessionID;
+//  uint16_t mTransactionID;
+
+    // AccountLevel handling is part of accounts.cpp
+    //PClientLevel mLevel;
+    int mConnection;
+    int mRemotePort;
+
+    bool mDebugMode[DEBUG_MODES];
+    // new multiuser-chat implementation //
+    int m_ZoneID;
+    //int[4] m_IP;
+
+    //*******
+    bool mActorRemoveMode;
+    //*******
+    bool mAwaitingWarpto;
+    uint16_t mTargetX;
+    uint16_t mTargetY;
+    uint16_t mTargetZ;
+    //*******
+    bool mAcceptNPCUpdates;
+    bool mZoning;
+    bool mVhcZoning;
+
+  public :
+    PClient( int Index );
+    ~PClient();
+
+    bool GetDebugMode(PDebugMode nDebugID);
+    void SetDebugMode(PDebugMode nDebugID, bool nVal = true);
+
+    bool IsAcceptingNPCUpdates();
+    void SetAcceptNPCUpdates(bool nVal);
+    bool IsZoning();
+    void SetZoning(bool nVal = true);
+    bool IsVhcZoning();
+    void SetVhcZoning(bool nVal = true);
+
+    uint32_t GetIndex() const; // better use GetID()
+    uint32_t GetID() const; // for better coherency with other classes
+    uint32_t GetLocalID() const;
+    uint32_t GetCharID() const;
+    PChar* GetChar() const;
+    bool ChangeCharLocation(uint32_t nLocation, bool DoForce = false);
+
+    int GetRemoteUDPPort() const; // Temp solution
+
+    bool IsInRemoveActorMode();
+    void SetRemoveActorMode(bool nNewValue);
+
+    void SetRemoteUDPPort(int port); // Temp solution
+    void SetCharID(int id);//NEW added
+
+    /*
+        inline uint16_t GetUDP_ID() const { return mUDP_ID; }
+        inline uint16_t GetSessionID() const { return SESSION_UDP_OFFSET + mUDP_ID ; }
+        inline uint16_t GetTransactionID() {return mTransactionID; }
+        void SetUDP_ID(int id);
+        inline void IncreaseUDP_ID() { SetUDP_ID(mUDP_ID + 1); }
+        inline void ResetTransactionID() { mTransactionID = 10170; }
+
+        inline void IncreaseTransactionID(uint8_t nInc = 1) { mTransactionID += nInc; }
+    */
+
+    // All outgoing ID's and stuff is now part of the ConnectionUDP class itself!
+    //    (which is not so good.... comment from Hammag)
+    // However, we still have full access to it through these functions
+    uint16_t GetUDP_ID();
+    void SetUDP_ID( int id );
+    void IncreaseUDP_ID();
+
+    uint16_t GetSessionID();
+
+    uint16_t GetTransactionID();
+    void ResetTransactionID();
+    void IncreaseTransactionID( uint8_t nInc = 1 );
+
+    void FillInUDP_ID( PMessage* nMessage );
+
+// ************************************************************************ //
+    // AccountLevel handling is part of accounts.cpp
+    //inline PClientLevel GetLevel() const { return mLevel; }
+
+    void setTCPConnection(ConnectionTCP *conn);
+    void setUDPConnection(ConnectionUDP *conn);
+
+    ConnectionTCP* getTCPConn();
+    ConnectionUDP* getUDPConn();
+
+    void SendTCPMessage(PMessage *nMessage);
+    void FragmentAndSendUDPMessage( PMessage* nMessage, uint8_t nType );
+    void SendUDPMessage(PMessage *nMessage, bool nVIP = false);
+
+    int GetConnection() const;
+    const char *GetAddress() const;
+    uint32_t GetAccountID() const;
+    int GetAccountLevel() const;
+
+    void GameDisconnect();
+
+    void RefreshAccountInfo(PAccount *Account);
+    void LoggedIn(PAccount *Account);
+    void Update();
+
+    // new multiuser-chat implementation //
+    int getZoneID() const;
+    //inline int* getIP() const { return (int*) m_IP; }
+
+    void SetAwaitingWarpto(bool yesno, uint16_t NewX, uint16_t NewY, uint16_t NewZ);
+    bool GetCharAwaitingWarpto(uint16_t* PosX = NULL, uint16_t* PosY = NULL, uint16_t* PosZ = NULL);
+
+    // Char broadcasted effects
+    void InitWarpCircle();
+    void InitCharVanish();
+
+    // used for dynamic ingame testing
+    uint8_t testval8;
+    uint16_t testval16;
+    uint32_t testval32;
+};
index efe902a..433e8fe 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// TODO:   - these are just begining of modif, as the Client Manager is bound to be a major component for multiplayer management\r
-\r
-PClientManager::PClientManager()\r
-{\r
-  //mLastID = 0;\r
-}\r
-\r
-\r
-PClientManager::~PClientManager()\r
-{\r
-  /*\r
-    for(PClientMap::iterator it=mClientList.begin(); it!=mClientList.end(); it++)\r
-    {\r
-        delete it->second;\r
-    }\r
-  */\r
-}\r
-\r
-bool PClientManager::addClientToList( PClient* newClient )\r
-{\r
-  if ( !newClient )\r
-    return false;\r
-\r
-  PClientMap::const_iterator it = mClientList.find( newClient->GetLocalID() );\r
-  if ( it == mClientList.end() ) // only if client not found in list\r
-  {\r
-    /*     mClientList.insert(std::make_pair(m_LastID, newClient));\r
-            ++m_LastID; */\r
-\r
-    mClientList.insert( std::make_pair( newClient->GetLocalID(), newClient ) );\r
-    //Console->Print(GREEN, BLACK, "Client %d added to clientmanager", newClient->GetIndex());\r
-    /*        if(newClient)\r
-            {\r
-                return true;\r
-            } */\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-// Check if a zone is in use\r
-bool PClientManager::IsWorldInUse( uint32_t nWorldID ) const\r
-{\r
-  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )\r
-  {\r
-    if ( it->second &&  it->second->GetChar() )\r
-    {\r
-      if ( it->second->GetChar()->GetLocation() == nWorldID )\r
-        return true;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-// Check if a rawObjectId belongs to a char is in use\r
-PClient* PClientManager::GetClientByCharLocalId( uint32_t rawObjectId, uint32_t nWorldID ) const\r
-{\r
-  PClient* nClient;\r
-  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )\r
-  {\r
-    // note: atm, charid = clientid+1 in any zone (client.h)\r
-    if ( (nClient = it->second) && ( nClient->GetLocalID() == rawObjectId ) )\r
-    {\r
-      if ( nClient->GetChar() && ( nClient->GetChar()->GetLocation() == nWorldID ) )\r
-        return nClient;\r
-    }\r
-  }\r
-  return 0;\r
-}\r
-\r
-void PClientManager::deleteClientFromList( uint32_t id )\r
-{\r
-  PClientMap::iterator it = mClientList.find( id );\r
-  if ( it != mClientList.end() )\r
-  {\r
-    mClientList.erase( it );\r
-    //Console->Print(YELLOW, BLACK, "Client %d removed from clientmanager", ((PClient*)(it->second))->GetIndex());\r
-  }\r
-}\r
-\r
-/* bool PClientManager::deleteClientFromList(PClient* delClient)\r
-{\r
-    for(PClientMap::iterator it=mClientList.begin(); it!=mClientList.end(); it++)\r
-    {\r
-        if(delClient == it->second)\r
-        {\r
-      //     if(it->second)\r
-      //    {\r
-      //         delete delClient;\r
-                mClientList.erase( it );\r
-                return true;\r
-      //    }\r
-        }\r
-    }\r
-    return false;\r
-} */\r
-\r
-PClient* PClientManager::getClientByID( uint32_t id ) const\r
-{\r
-  PClientMap::const_iterator it = mClientList.find( id );\r
-  return (( it != mClientList.end() ) ? ( PClient* )( it->second ) : NULL );\r
-}\r
-\r
-PClient* PClientManager::getClientByChar( uint32_t CharID ) const\r
-{\r
-  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )\r
-  {\r
-    if ( it->second )\r
-    {\r
-      if ( it->second->GetCharID() == CharID )\r
-        return it->second;\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-PClient* PClientManager::getClientByChar( const std::string &Name ) const\r
-{\r
-  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )\r
-  {\r
-    if ( it->second )\r
-    {\r
-      if ( it->second->GetChar()->GetName() == Name )\r
-        return it->second;\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-/* uint32_t PClientManager::getClientID(PClient* _client)\r
-{\r
-    for(PClientMap::iterator it=mClientList.begin(); it!=mClientList<p align="center"></p>.end(); it++)\r
-    {\r
-        if(_client == it->second)\r
-        {\r
-            return it->first;\r
-        }\r
-    }\r
-\r
-    return -1;\r
-} */\r
-\r
-// Distance checking doesn't care for Z axis ATM\r
-int PClientManager::UDPBroadcast( PMessage* nMessage, uint32_t nZoneID, uint16_t nX, uint16_t nY, uint16_t nZ, uint16_t nMaxDist, uint32_t nSkipCharId, bool nNPCPing )\r
-{\r
-  int msgCount = 0;\r
-  PChar* nChar;\r
-  PMessage* tmpMsg;\r
-  PClient* itClient;\r
-  uint16_t Dapprox;\r
-\r
-  for ( PClientMap::iterator it = mClientList.begin(); it != mClientList.end(); it++ )\r
-  {\r
-    itClient = ( PClient* )( it->second );\r
-\r
-    // Dont send NPC alive messages when client is not ready for them\r
-    if ( !itClient->IsAcceptingNPCUpdates() && nNPCPing )\r
-      continue;\r
-\r
-    if ( itClient->getUDPConn() )\r
-    {\r
-      nChar = itClient->GetChar();\r
-      if ( nChar && ( nChar->GetLocation() != nZoneID ) )// if limited to zone, do check\r
-        continue;\r
-\r
-      if (itClient->GetCharID() == nSkipCharId ) // if source of broadcast should be skipped\r
-        continue;\r
-\r
-      if ( nMaxDist ) // if limited to distance, do check\r
-      {\r
-        Dapprox = DistanceApprox(( nChar->Coords ).mX, ( nChar->Coords ).mY, ( nChar->Coords ).mZ, nX, nY, nZ );\r
-        if ( Dapprox >  nMaxDist )\r
-          continue;\r
-      }\r
-\r
-      /*tmpMsg = new PMessage(nMessage->GetMaxSize());\r
-      (*tmpMsg) = (*nMessage);*/\r
-      tmpMsg = new PMessage( *nMessage );\r
-\r
-      itClient->FillInUDP_ID( tmpMsg );\r
-      itClient->SendUDPMessage( tmpMsg );\r
-      ++msgCount;\r
-    }\r
-  }\r
-\r
-  //Console->Print("Broadcast in zone %d to %d chars", nZoneID, msgCount);\r
-  delete nMessage;\r
-  return msgCount;\r
-}\r
-\r
-int PClientManager::UDPBroadcast( PMessage* nMessage, PClient* nClient, uint16_t nMaxDist, bool nSkipSource, bool nNPCPing )\r
-{\r
-  PChar* nChar;\r
-  uint32_t skipCharId = nSkipSource ? nClient->GetCharID() : 0 ;\r
-\r
-  if ( nClient && ( nChar = nClient->GetChar() ) )\r
-  {\r
-    return UDPBroadcast( nMessage, nChar->GetLocation(), ( nChar->Coords ).mX, ( nChar->Coords ).mY, ( nChar->Coords ).mZ, nMaxDist, skipCharId, nNPCPing );\r
-  }\r
-  else\r
-  {\r
-    delete nMessage;\r
-    return 0;\r
-  }\r
-}\r
-\r
-int PClientManager::SendUDPZoneWelcomeToClient( PClient* nClient )\r
-{\r
-  int msgCount = 0;\r
-  PChar* nChar;\r
-  PChar* itChar;\r
-  PMessage* tmpMsg;\r
-  uint32_t nZoneID;\r
-  PClient* itClient;\r
-\r
-  if ( nClient && ( nChar = nClient->GetChar() ) ) // if nClient is set, always use its zone\r
-  {\r
-    nZoneID = nChar->GetLocation();\r
-  }\r
-  else\r
-    return 0;\r
-\r
-  for ( PClientMap::iterator it = mClientList.begin(); it != mClientList.end(); it++ )\r
-  {\r
-    if ( nClient->GetLocalID() == it->first )\r
-      continue;\r
-\r
-    itClient = ( PClient* )( it->second );\r
-    if ( itClient->getUDPConn() )\r
-    {\r
-      itChar = itClient->GetChar();\r
-      if ( itChar->GetLocation() != nZoneID ) // limit to zone\r
-        continue;\r
-\r
-      tmpMsg = MsgBuilder->BuildCharHelloMsg( itClient );\r
-\r
-      nClient->FillInUDP_ID( tmpMsg );\r
-      nClient->SendUDPMessage( tmpMsg );\r
-      //Console->Print("Welcome data sent from client %d to client %d", itClient->GetIndex(), nClient->GetIndex());\r
-      //tmpMsg->Dump();\r
-\r
-      if ( itChar->GetSeatInUse() != seat_none )\r
-      {\r
-        tmpMsg = MsgBuilder->BuildCharPosUpdateMsg( itClient );\r
-        nClient->FillInUDP_ID( tmpMsg );\r
-        nClient->SendUDPMessage( tmpMsg );\r
-\r
-        //Console->Print("Sit on chair %d sent from client %d to client %d", (itChar->GetChairInUse()+1)*1024, itClient->GetIndex(), nClient->GetIndex());\r
-        /*tmpMsg = MsgBuilder->BuildCharUseSeatMsg(itClient, (itChar->GetChairInUse()+1)*1024);\r
-        nClient->FillInUDP_ID(tmpMsg);\r
-        nClient->SendUDPMessage(tmpMsg);*/\r
-      }\r
-      ++msgCount;\r
-    }\r
-  }\r
-\r
-  return msgCount;\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// TODO:   - these are just begining of modif, as the Client Manager is bound to be a major component for multiplayer management
+
+PClientManager::PClientManager()
+{
+  //mLastID = 0;
+}
+
+
+PClientManager::~PClientManager()
+{
+  /*
+    for(PClientMap::iterator it=mClientList.begin(); it!=mClientList.end(); it++)
+    {
+        delete it->second;
+    }
+  */
+}
+
+bool PClientManager::addClientToList( PClient* newClient )
+{
+  if ( !newClient )
+    return false;
+
+  PClientMap::const_iterator it = mClientList.find( newClient->GetLocalID() );
+  if ( it == mClientList.end() ) // only if client not found in list
+  {
+    /*     mClientList.insert(std::make_pair(m_LastID, newClient));
+            ++m_LastID; */
+
+    mClientList.insert( std::make_pair( newClient->GetLocalID(), newClient ) );
+    //Console->Print(GREEN, BLACK, "Client %d added to clientmanager", newClient->GetIndex());
+    /*        if(newClient)
+            {
+                return true;
+            } */
+    return true;
+  }
+  else
+    return false;
+}
+
+// Check if a zone is in use
+bool PClientManager::IsWorldInUse( uint32_t nWorldID ) const
+{
+  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )
+  {
+    if ( it->second &&  it->second->GetChar() )
+    {
+      if ( it->second->GetChar()->GetLocation() == nWorldID )
+        return true;
+    }
+  }
+  return false;
+}
+
+// Check if a rawObjectId belongs to a char is in use
+PClient* PClientManager::GetClientByCharLocalId( uint32_t rawObjectId, uint32_t nWorldID ) const
+{
+  PClient* nClient;
+  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )
+  {
+    // note: atm, charid = clientid+1 in any zone (client.h)
+    if ( (nClient = it->second) && ( nClient->GetLocalID() == rawObjectId ) )
+    {
+      if ( nClient->GetChar() && ( nClient->GetChar()->GetLocation() == nWorldID ) )
+        return nClient;
+    }
+  }
+  return 0;
+}
+
+void PClientManager::deleteClientFromList( uint32_t id )
+{
+  PClientMap::iterator it = mClientList.find( id );
+  if ( it != mClientList.end() )
+  {
+    mClientList.erase( it );
+    //Console->Print(YELLOW, BLACK, "Client %d removed from clientmanager", ((PClient*)(it->second))->GetIndex());
+  }
+}
+
+/* bool PClientManager::deleteClientFromList(PClient* delClient)
+{
+    for(PClientMap::iterator it=mClientList.begin(); it!=mClientList.end(); it++)
+    {
+        if(delClient == it->second)
+        {
+      //     if(it->second)
+      //    {
+      //         delete delClient;
+                mClientList.erase( it );
+                return true;
+      //    }
+        }
+    }
+    return false;
+} */
+
+PClient* PClientManager::getClientByID( uint32_t id ) const
+{
+  PClientMap::const_iterator it = mClientList.find( id );
+  return (( it != mClientList.end() ) ? ( PClient* )( it->second ) : NULL );
+}
+
+PClient* PClientManager::getClientByChar( uint32_t CharID ) const
+{
+  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )
+  {
+    if ( it->second )
+    {
+      if ( it->second->GetCharID() == CharID )
+        return it->second;
+    }
+  }
+  return NULL;
+}
+
+PClient* PClientManager::getClientByChar( const std::string &Name ) const
+{
+  for ( PClientMap::const_iterator it = mClientList.begin(); it != mClientList.end(); it++ )
+  {
+    if ( it->second )
+    {
+      if ( it->second->GetChar()->GetName() == Name )
+        return it->second;
+    }
+  }
+  return NULL;
+}
+
+/* uint32_t PClientManager::getClientID(PClient* _client)
+{
+    for(PClientMap::iterator it=mClientList.begin(); it!=mClientList<p align="center"></p>.end(); it++)
+    {
+        if(_client == it->second)
+        {
+            return it->first;
+        }
+    }
+
+    return -1;
+} */
+
+// Distance checking doesn't care for Z axis ATM
+int PClientManager::UDPBroadcast( PMessage* nMessage, uint32_t nZoneID, uint16_t nX, uint16_t nY, uint16_t nZ, uint16_t nMaxDist, uint32_t nSkipCharId, bool nNPCPing )
+{
+  int msgCount = 0;
+  PChar* nChar;
+  PMessage* tmpMsg;
+  PClient* itClient;
+  uint16_t Dapprox;
+
+  for ( PClientMap::iterator it = mClientList.begin(); it != mClientList.end(); it++ )
+  {
+    itClient = ( PClient* )( it->second );
+
+    // Dont send NPC alive messages when client is not ready for them
+    if ( !itClient->IsAcceptingNPCUpdates() && nNPCPing )
+      continue;
+
+    if ( itClient->getUDPConn() )
+    {
+      nChar = itClient->GetChar();
+      if ( nChar && ( nChar->GetLocation() != nZoneID ) )// if limited to zone, do check
+        continue;
+
+      if (itClient->GetCharID() == nSkipCharId ) // if source of broadcast should be skipped
+        continue;
+
+      if ( nMaxDist ) // if limited to distance, do check
+      {
+        Dapprox = DistanceApprox(( nChar->Coords ).mX, ( nChar->Coords ).mY, ( nChar->Coords ).mZ, nX, nY, nZ );
+        if ( Dapprox >  nMaxDist )
+          continue;
+      }
+
+      /*tmpMsg = new PMessage(nMessage->GetMaxSize());
+      (*tmpMsg) = (*nMessage);*/
+      tmpMsg = new PMessage( *nMessage );
+
+      itClient->FillInUDP_ID( tmpMsg );
+      itClient->SendUDPMessage( tmpMsg );
+      ++msgCount;
+    }
+  }
+
+  //Console->Print("Broadcast in zone %d to %d chars", nZoneID, msgCount);
+  delete nMessage;
+  return msgCount;
+}
+
+int PClientManager::UDPBroadcast( PMessage* nMessage, PClient* nClient, uint16_t nMaxDist, bool nSkipSource, bool nNPCPing )
+{
+  PChar* nChar;
+  uint32_t skipCharId = nSkipSource ? nClient->GetCharID() : 0 ;
+
+  if ( nClient && ( nChar = nClient->GetChar() ) )
+  {
+    return UDPBroadcast( nMessage, nChar->GetLocation(), ( nChar->Coords ).mX, ( nChar->Coords ).mY, ( nChar->Coords ).mZ, nMaxDist, skipCharId, nNPCPing );
+  }
+  else
+  {
+    delete nMessage;
+    return 0;
+  }
+}
+
+int PClientManager::SendUDPZoneWelcomeToClient( PClient* nClient )
+{
+  int msgCount = 0;
+  PChar* nChar;
+  PChar* itChar;
+  PMessage* tmpMsg;
+  uint32_t nZoneID;
+  PClient* itClient;
+
+  if ( nClient && ( nChar = nClient->GetChar() ) ) // if nClient is set, always use its zone
+  {
+    nZoneID = nChar->GetLocation();
+  }
+  else
+    return 0;
+
+  for ( PClientMap::iterator it = mClientList.begin(); it != mClientList.end(); it++ )
+  {
+    if ( nClient->GetLocalID() == it->first )
+      continue;
+
+    itClient = ( PClient* )( it->second );
+    if ( itClient->getUDPConn() )
+    {
+      itChar = itClient->GetChar();
+      if ( itChar->GetLocation() != nZoneID ) // limit to zone
+        continue;
+
+      tmpMsg = MsgBuilder->BuildCharHelloMsg( itClient );
+
+      nClient->FillInUDP_ID( tmpMsg );
+      nClient->SendUDPMessage( tmpMsg );
+      //Console->Print("Welcome data sent from client %d to client %d", itClient->GetIndex(), nClient->GetIndex());
+      //tmpMsg->Dump();
+
+      if ( itChar->GetSeatInUse() != seat_none )
+      {
+        tmpMsg = MsgBuilder->BuildCharPosUpdateMsg( itClient );
+        nClient->FillInUDP_ID( tmpMsg );
+        nClient->SendUDPMessage( tmpMsg );
+
+        //Console->Print("Sit on chair %d sent from client %d to client %d", (itChar->GetChairInUse()+1)*1024, itClient->GetIndex(), nClient->GetIndex());
+        /*tmpMsg = MsgBuilder->BuildCharUseSeatMsg(itClient, (itChar->GetChairInUse()+1)*1024);
+        nClient->FillInUDP_ID(tmpMsg);
+        nClient->SendUDPMessage(tmpMsg);*/
+      }
+      ++msgCount;
+    }
+  }
+
+  return msgCount;
+}
index 71eb2db..c99887a 100644 (file)
@@ -1,35 +1,35 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-\r
-typedef std::map<uint32_t, PClient*> PClientMap;\r
-\r
-class PClientManager {\r
-private:\r
-    //int       mLastID;\r
-    PClientMap mClientList;\r
-\r
-public:\r
-    PClientManager();\r
-    ~PClientManager();\r
-\r
-    PClientMap::iterator   getClientListBegin() { return mClientList.begin(); }\r
-    PClientMap::iterator   getClientListEnd() { return mClientList.end(); }\r
-\r
-    bool addClientToList( PClient* newClient );\r
-    //void deleteClientFromListByID(int id);\r
-    void deleteClientFromList( uint32_t id );\r
-    //bool deleteClientFromList(PClient* delClient); // maybe no use for this...\r
-    PClient* getClientByID( uint32_t uint32_t ) const; // returns pointer to a client for further use\r
-    PClient* getClientByChar( uint32_t CharID ) const;\r
-    PClient* getClientByChar( const std::string &Name ) const;\r
-    // int getClientID(PClient* _client); do _client->GetLocalID()\r
-    bool IsWorldInUse( uint32_t nWorldID ) const; // Temp until world content fully managed by world\r
-    PClient* GetClientByCharLocalId( uint32_t rawObjectId, uint32_t nWorldID  ) const; // Temp (called by world) until world content fuly managed by world\r
-\r
-    // each function return the number of messages sent.\r
-    int UDPBroadcast( PMessage* nMessage, uint32_t nZoneID, uint16_t nX = 0, uint16_t nY = 0, uint16_t nZ = 0, uint16_t nMaxDist = 0, uint32_t nSkipCharId = 0, bool nNPCPing = false );\r
-    int UDPBroadcast( PMessage* nMessage, PClient* nClient, uint16_t nMaxDist = 0, bool nSkipSource = false, bool nNPCPing = false );\r
-    int SendUDPZoneWelcomeToClient( PClient* nClient );\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+typedef std::map<uint32_t, PClient*> PClientMap;
+
+class PClientManager {
+private:
+    //int       mLastID;
+    PClientMap mClientList;
+
+public:
+    PClientManager();
+    ~PClientManager();
+
+    PClientMap::iterator   getClientListBegin() { return mClientList.begin(); }
+    PClientMap::iterator   getClientListEnd() { return mClientList.end(); }
+
+    bool addClientToList( PClient* newClient );
+    //void deleteClientFromListByID(int id);
+    void deleteClientFromList( uint32_t id );
+    //bool deleteClientFromList(PClient* delClient); // maybe no use for this...
+    PClient* getClientByID( uint32_t uint32_t ) const; // returns pointer to a client for further use
+    PClient* getClientByChar( uint32_t CharID ) const;
+    PClient* getClientByChar( const std::string &Name ) const;
+    // int getClientID(PClient* _client); do _client->GetLocalID()
+    bool IsWorldInUse( uint32_t nWorldID ) const; // Temp until world content fully managed by world
+    PClient* GetClientByCharLocalId( uint32_t rawObjectId, uint32_t nWorldID  ) const; // Temp (called by world) until world content fuly managed by world
+
+    // each function return the number of messages sent.
+    int UDPBroadcast( PMessage* nMessage, uint32_t nZoneID, uint16_t nX = 0, uint16_t nY = 0, uint16_t nZ = 0, uint16_t nMaxDist = 0, uint32_t nSkipCharId = 0, bool nNPCPing = false );
+    int UDPBroadcast( PMessage* nMessage, PClient* nClient, uint16_t nMaxDist = 0, bool nSkipSource = false, bool nNPCPing = false );
+    int SendUDPZoneWelcomeToClient( PClient* nClient );
+};
index 03aed73..99d327b 100644 (file)
-#pragma once\r
-\r
-/*\r
-  TODO: put a single data_directory entry as the root directory for all NC data\r
-*/\r
-\r
-static const char *GameConfigTemplate[][2] = {\r
-  // {option_name, default_value} if default_value is empty string, it means option is mandatory\r
-  // List ends with empty string for option_name\r
-  {"info_sql_host", "127.0.0.1"},\r
-  {"info_sql_port", "3306"},\r
-  {"info_sql_username", ""},\r
-  {"info_sql_password", ""},\r
-  {"info_sql_database", "infoserver"},\r
-  {"game_sql_host", "127.0.0.1"},\r
-  {"game_sql_port", "3306"},\r
-  {"gameserver_udpport_min", "5000"},\r
-  {"gameserver_udpport_max", "5099"},\r
-  {"game_sql_username", ""},\r
-  {"game_sql_password", ""},\r
-  {"game_sql_database", "gameserver"},\r
-  {"mysql_wait_timeout", "28800"}, // value of the wait_timout system variable from the MySQL server (same for game & info DB atm). 0 to disable keepalive.\r
-  {"server_name", "TinNS"},\r
-  {"server_ip", "127.0.0.1"}, //IP address used with clients reached without NAT (see localnet)\r
-  {"no_nat_net", "0"}, // 0 is for "don't bother with NAT", else format is like 192.168.1. (with trailing dot)\r
-  {"server_nat_ip", "127.0.0.1"}, //IP address used with clients reached through NAT\r
-  {"gameserver_port", "12000"},\r
-  {"server_version", ""},\r
-  {"maxclients", "128"},\r
-  {"gm_slots", "10"},\r
-  //{"defs_path", "./defs"},\r
-  //{"worlds_path", "./worlds"},\r
-  {"nc_data_path", "."},\r
-  {"isc_method", "1"},\r
-  {"isc_server_id", ""},\r
-  {"isc_update_intervall", "60"},\r
-  {"isc_delayed_update_intervall", "6"}, // the purpose of this option is to avoid multiple infoDB update when client just disconnects/reconnects during login phases\r
-  {"isc_infoserverip", "127.0.0.1"},\r
-  {"isc_infoserverport", "9991"},\r
-  {"isc_connect_pw", "change_me"}, // make default value empty when isc ready\r
-  {"dev_debug", "0"}, // set to non-zero to activate development outputs\r
-  {"auto_save_period", "300"},\r
-  {"new_char_location", "1085"},\r
-  {"broadcast_new", "0"},\r
-  {"broadcast_new_hidestaff", "0"},\r
-  {"max_cash", "20000000"},\r
-  {"item_price", "70"},\r
-  {"require_validation", "0"},\r
-  {"minlevel", "0"},\r
-  {"username_filter", "^[a-z][\\w\\-]{2,14}$"},\r
-  {"password_filter", "^[[:graph:]]{3,15}$"},\r
-  {"charname_filter", "^[a-z]+([\\-\\ ]?[a-z]+){0,2}$"},\r
-  {"clanname_filter", "^[a-z][\\w\\-\\ ]{2,14}$"},\r
-\r
-// For futur use:\r
-//  {"max_chars_per_account", "4"},\r
-//  {"multiple_logins_per_account", "0"}, // 0=nobody, 1=gm+ only, 2=everybody\r
-//  {"multiple_ingames_per_account", "0"}, // 0=nobody, 1=gm+ only, 2=everybody (needs multiple logins ...)\r
-\r
-//  {"local_chat_range", "500"},\r
-\r
-  {"", ""} // do not change this line (end mark)\r
-};\r
-\r
-static const char *CommandsTemplate[][2] = {\r
-    {"debug", "100"},\r
-    {"settime", "100"},\r
-    {"warp", "0"},\r
-//    {"delworlditem", "100"},\r
-//    {"addworlditem", "100"},\r
-//    {"adddoor", "100"},\r
-    {"online", "0"},\r
-    {"sendchat", "50"},\r
-    {"skin", "50"},\r
-    {"effect", "0"},\r
-    {"speed", "0"},\r
-    {"color", "0"},\r
-    {"brightness", "0"},\r
-    {"remove", "50"},\r
-    {"rehash", "100"},\r
-    {"uptime", "0"},\r
-    {"version", "0"},\r
-    {"broadcast", "100"},\r
-    {"kick", "50"},\r
-    {"info", "50"},\r
-    {"setlevel", "100"},\r
-    {"warpto", "50"},\r
-    {"recall", "50"},\r
-\r
-    {"ban", "50"},          // Set ban\r
-    {"unban", "50"},        // Remove ban\r
-    {"listbans", "50"},     // Show list of all banned accounts\r
-    {"shun", "50"},         // Quiet all chat\r
-    {"unshun", "50"},       // UnQuiet all chat\r
-    {"jail", "50"},         // "Jail" someone (Regants ^^)\r
-    {"unjail", "50"},       // Move him out\r
-    {"teleport", "50"},     // Warp targetplayer XX to zone YY\r
-    {"givemoney", "50"},     // Warp targetplayer XX to zone YY\r
-    {"takemoney", "50"},     // Warp targetplayer XX to zone YY\r
-    {"spawnactor", "50"},     // Spawn given actor next to player\r
-\r
-    {"weather", "50"},     // Set weather in a zone\r
-    {"setmainskill", "50"},     // Set mainskill (INT,PSI,DEX,CON,STR) of own char or someone else\r
-    {"setsubskill", "50"},     // Set subskill (BRT,HCK,PPU,...) of own char or someone else\r
-    {"npc", "50"},     // do actions with NPCs\r
-\r
-    {"", ""} // do not change this line (end mark)\r
-};\r
+#pragma once
+
+/*
+  TODO: put a single data_directory entry as the root directory for all NC data
+*/
+
+static const char *GameConfigTemplate[][2] = {
+  // {option_name, default_value} if default_value is empty string, it means option is mandatory
+  // List ends with empty string for option_name
+  {"info_sql_host", "127.0.0.1"},
+  {"info_sql_port", "3306"},
+  {"info_sql_username", ""},
+  {"info_sql_password", ""},
+  {"info_sql_database", "infoserver"},
+  {"game_sql_host", "127.0.0.1"},
+  {"game_sql_port", "3306"},
+  {"gameserver_udpport_min", "5000"},
+  {"gameserver_udpport_max", "5099"},
+  {"game_sql_username", ""},
+  {"game_sql_password", ""},
+  {"game_sql_database", "gameserver"},
+  {"mysql_wait_timeout", "28800"}, // value of the wait_timout system variable from the MySQL server (same for game & info DB atm). 0 to disable keepalive.
+  {"server_name", "TinNS"},
+  {"server_ip", "127.0.0.1"}, //IP address used with clients reached without NAT (see localnet)
+  {"no_nat_net", "0"}, // 0 is for "don't bother with NAT", else format is like 192.168.1. (with trailing dot)
+  {"server_nat_ip", "127.0.0.1"}, //IP address used with clients reached through NAT
+  {"gameserver_port", "12000"},
+  {"server_version", ""},
+  {"maxclients", "128"},
+  {"gm_slots", "10"},
+  //{"defs_path", "./defs"},
+  //{"worlds_path", "./worlds"},
+  {"nc_data_path", "."},
+  {"isc_method", "1"},
+  {"isc_server_id", ""},
+  {"isc_update_intervall", "60"},
+  {"isc_delayed_update_intervall", "6"}, // the purpose of this option is to avoid multiple infoDB update when client just disconnects/reconnects during login phases
+  {"isc_infoserverip", "127.0.0.1"},
+  {"isc_infoserverport", "9991"},
+  {"isc_connect_pw", "change_me"}, // make default value empty when isc ready
+  {"dev_debug", "0"}, // set to non-zero to activate development outputs
+  {"auto_save_period", "300"},
+  {"new_char_location", "1085"},
+  {"broadcast_new", "0"},
+  {"broadcast_new_hidestaff", "0"},
+  {"max_cash", "20000000"},
+  {"item_price", "70"},
+  {"require_validation", "0"},
+  {"minlevel", "0"},
+  {"username_filter", "^[a-z][\\w\\-]{2,14}$"},
+  {"password_filter", "^[[:graph:]]{3,15}$"},
+  {"charname_filter", "^[a-z]+([\\-\\ ]?[a-z]+){0,2}$"},
+  {"clanname_filter", "^[a-z][\\w\\-\\ ]{2,14}$"},
+
+// For futur use:
+//  {"max_chars_per_account", "4"},
+//  {"multiple_logins_per_account", "0"}, // 0=nobody, 1=gm+ only, 2=everybody
+//  {"multiple_ingames_per_account", "0"}, // 0=nobody, 1=gm+ only, 2=everybody (needs multiple logins ...)
+
+//  {"local_chat_range", "500"},
+
+  {"", ""} // do not change this line (end mark)
+};
+
+static const char *CommandsTemplate[][2] = {
+    {"debug", "100"},
+    {"settime", "100"},
+    {"warp", "0"},
+//    {"delworlditem", "100"},
+//    {"addworlditem", "100"},
+//    {"adddoor", "100"},
+    {"online", "0"},
+    {"sendchat", "50"},
+    {"skin", "50"},
+    {"effect", "0"},
+    {"speed", "0"},
+    {"color", "0"},
+    {"brightness", "0"},
+    {"remove", "50"},
+    {"rehash", "100"},
+    {"uptime", "0"},
+    {"version", "0"},
+    {"broadcast", "100"},
+    {"kick", "50"},
+    {"info", "50"},
+    {"setlevel", "100"},
+    {"warpto", "50"},
+    {"recall", "50"},
+
+    {"ban", "50"},          // Set ban
+    {"unban", "50"},        // Remove ban
+    {"listbans", "50"},     // Show list of all banned accounts
+    {"shun", "50"},         // Quiet all chat
+    {"unshun", "50"},       // UnQuiet all chat
+    {"jail", "50"},         // "Jail" someone (Regants ^^)
+    {"unjail", "50"},       // Move him out
+    {"teleport", "50"},     // Warp targetplayer XX to zone YY
+    {"givemoney", "50"},     // Warp targetplayer XX to zone YY
+    {"takemoney", "50"},     // Warp targetplayer XX to zone YY
+    {"spawnactor", "50"},     // Spawn given actor next to player
+
+    {"weather", "50"},     // Set weather in a zone
+    {"setmainskill", "50"},     // Set mainskill (INT,PSI,DEX,CON,STR) of own char or someone else
+    {"setsubskill", "50"},     // Set subskill (BRT,HCK,PPU,...) of own char or someone else
+    {"npc", "50"},     // do actions with NPCs
+
+    {"", ""} // do not change this line (end mark)
+};
index 64b1991..43fbe1d 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/* --- PContainerEntry class --- */\r
-\r
-PContainerEntry::PContainerEntry( PItem* nItem, uint8_t X, uint8_t Y, uint32_t nInvID, bool SetDirty )\r
-{\r
-  mItem = nItem;\r
-  mPosX = X;\r
-  mPosY = Y;\r
-  mInvID = nInvID;\r
-  mDirtyFlag = SetDirty;\r
-}\r
-\r
-PContainerEntry::PContainerEntry( MYSQL_ROW row )\r
-{\r
-  mItem = NULL;\r
-  mInvID = atoi( row[i_invid] );\r
-  mPosX = atoi( row[i_x] );\r
-  mPosY = atoi( row[i_y] );\r
-  mDirtyFlag = false;\r
-\r
-  uint32_t nItemID = atoi( row[i_itemid] );\r
-  uint8_t nStackSize = atoi( row[i_qty] );\r
-  //     = std::atoi(row[i_type]);\r
-  uint8_t CurDur = atoi( row[i_curdur] );\r
-  uint8_t Dmg = atoi( row[i_dmg] );\r
-  uint8_t Freq = atoi( row[i_freq] );\r
-  uint8_t Hand = atoi( row[i_hand] );\r
-  uint8_t Rng = atoi( row[i_rng] );\r
-  uint8_t Dur = atoi( row[i_maxdur] );\r
-\r
-  mItem = new PItem( nItemID, nStackSize, CurDur, Dur, Dmg, Freq, Hand, Rng );\r
-}\r
-\r
-PContainerEntry::~PContainerEntry()\r
-{\r
-  delete mItem;\r
-}\r
-\r
-bool PContainerEntry::SQLSave( uint32_t CharID, uint32_t InvLoc )\r
-{\r
-  std::string query, queryv;\r
-\r
-  queryv += Ssprintf( " inv_charid='%u',inv_loc='%u',inv_x='%u',inv_y='%u'", CharID, InvLoc, mPosX, mPosY );\r
-  queryv += Ssprintf( ",inv_itemid='%u',inv_qty='%u'", mItem->mItemID, mItem->mStackSize );\r
-  //queryv += Ssprintf( ",inv_type='%u'", 0 );\r
-  queryv += Ssprintf( ",inv_cdur='%u'", mItem->mCurDuration );\r
-  queryv += Ssprintf( ",inv_dmg='%u'", mItem->mDamages );\r
-  queryv += Ssprintf( ",inv_frq='%u'", mItem->mFrequency );\r
-  queryv += Ssprintf( ",inv_hnd='%u'", mItem->mHandling );\r
-  queryv += Ssprintf( ",inv_rng='%u'", mItem->mRange );\r
-  queryv += Ssprintf( ",inv_mdur='%u'", mItem->mMaxDuration );\r
-\r
-  if ( mInvID )\r
-  {\r
-    query = "UPDATE inventory SET " + queryv;\r
-    query += Ssprintf( " WHERE inv_id='%u' LIMIT 1;", mInvID );\r
-  }\r
-  else\r
-  {\r
-    query = "INSERT INTO inventory SET " + queryv + ";";\r
-  }\r
-\r
-  if ( MySQL->GameQuery( query.c_str() ) )\r
-  {\r
-    Console->Print( RED, BLACK, "PContainerEntry::SQLSave could not add/update some inventory item in the database" );\r
-    Console->Print( "Query was:" );\r
-    Console->Print( "%s", query.c_str() );\r
-    MySQL->ShowGameSQLError();\r
-    return false;\r
-  }\r
-  else\r
-  {\r
-    if ( !mInvID )\r
-    {\r
-      mInvID = MySQL->GetLastGameInsertId();\r
-      if ( gDevDebug )\r
-        Console->Print( GREEN, BLACK, "New item %d added to inventory DB", mInvID );\r
-    }\r
-//Console->Print(YELLOW, BLACK, "PContainerEntry::SQLSave - Query was:");\r
-//Console->Print(YELLOW, BLACK, "%s", query.c_str());\r
-    mDirtyFlag = false;\r
-    return true;\r
-  }\r
-}\r
-\r
-bool PContainerEntry::SQLDelete()\r
-{\r
-  std::string query;\r
-\r
-  if ( mInvID )\r
-  {\r
-    query = Ssprintf( "DELETE FROM inventory WHERE inv_id='%u' LIMIT 1;", mInvID );\r
-\r
-    if ( MySQL->GameQuery( query.c_str() ) )\r
-    {\r
-      Console->Print( RED, BLACK, "PContainerEntry::SQLDelete could not delete some container item from the database" );\r
-      Console->Print( "Query was:" );\r
-      Console->Print( "%s", query.c_str() );\r
-      MySQL->ShowGameSQLError();\r
-      return false;\r
-    }\r
-    else\r
-    {\r
-      if ( gDevDebug )\r
-        Console->Print( GREEN, BLACK, "Item %d deleted from container DB", mInvID );\r
-      mInvID = 0;\r
-      delete mItem;\r
-      mItem = NULL;\r
-\r
-      mDirtyFlag = false;\r
-      return true;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Console->Print( YELLOW, BLACK, "PContainerEntry::SQLDelete: Item was not in inventory DB" );\r
-    return true;\r
-  }\r
-}\r
-\r
-/* --- PContainer class --- */\r
-\r
-PContainer::PContainer( uint8_t nMaxSlots )\r
-{\r
-  mMaxSlots = ( nMaxSlots > CONTAINER_MAX_SIZE ? CONTAINER_MAX_SIZE : nMaxSlots ) ;\r
-  if ( mMaxSlots )\r
-    mContContent = new std::vector< PContainerEntry* >( mMaxSlots, NULL );\r
-  else\r
-    mContContent = new std::vector< PContainerEntry* >;\r
-  mCharID = 0;\r
-  mInvLoc = 0;\r
-  mExclusiveUseCharID = 0;\r
-  mDirtyFlag = false;\r
-}\r
-\r
-PContainer::~PContainer()\r
-{\r
-  for ( uint8_t i = 0; i < mContContent->size(); ++i )\r
-    delete mContContent->at( i );\r
-\r
-  if ( mExclusiveUseCharID )\r
-    Console->Print( RED, BLACK, "[ERROR] PContainer::~PContainer: Char %d still has exclusive access to container !!! Bad Pointer error will happen.", mExclusiveUseCharID );\r
-}\r
-\r
-bool PContainer::AddEntry( PContainerEntry* NewEntry, uint8_t nSlotId )\r
-{\r
-  if ( IsSlotAllowed( nSlotId ) )\r
-  {\r
-    for ( uint8_t i = mContContent->size(); i <= nSlotId; ++i ) // Extend as needed\r
-      mContContent->push_back( static_cast<PContainerEntry*>(NULL) );\r
-    if ( mContContent->at( nSlotId ) )\r
-    {\r
-      Console->Print( RED, BLACK, "[Warning] PContainer::AddEntry: Target entry already %d in use !!!", nSlotId );\r
-      return false;\r
-    }\r
-    mContContent->at( nSlotId ) = NewEntry;\r
-    mDirtyFlag = true;\r
-    this->SetEntryPosXY( NewEntry, nSlotId, NewEntry->mPosX, NewEntry->mPosY );\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Warning] PContainer::AddEntry: Target entry %d not allowed (max = %d) !!!", nSlotId, mMaxSlots );\r
-    return false;\r
-  }\r
-  /* --- degug only ---\r
-  Console->Print(GREEN, BLACK, "PContainer::AddEntry: added item %d at pos (%d,%d)", NewEntry->mItem->GetItemID(), NewEntry->mPosX, NewEntry->mPosY);\r
-\r
-  Dump();\r
-  ---            --- */\r
-}\r
-\r
-void PContainer::SetEntryPosXY( PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX, uint8_t nPosY )\r
-{\r
-  nPosX = nPosY;\r
-  nEntry->Set2DPos( nSlotId, 0 );\r
-  mDirtyFlag = mDirtyFlag || nEntry->mDirtyFlag;\r
-}\r
-\r
-PContainerEntry* PContainer::RemoveEntry( uint8_t nSlotId )\r
-{\r
-  PContainerEntry* tEntry = NULL;\r
-\r
-  if ( nSlotId < mContContent->size() )\r
-  {\r
-    tEntry = mContContent->at( nSlotId );\r
-    mContContent->at( nSlotId ) = NULL;\r
-  }\r
-  return tEntry;\r
-}\r
-\r
-bool PContainer::GetFreeSlot( uint8_t* nSlotId )\r
-{\r
-  return IsSlotFree( *nSlotId );\r
-}\r
-\r
-void PContainer::Compact( uint8_t startSlotId )\r
-{\r
-  uint8_t i, j;\r
-  PContainerEntry* tEntry;\r
-\r
-  for ( i = j = startSlotId; i < mContContent->size(); ++i )\r
-  {\r
-    if ( mContContent->at( i ) )\r
-    {\r
-      if ( j < i )\r
-      {\r
-        mContContent->at( j ) = tEntry = mContContent->at( i );\r
-        this->SetEntryPosXY( tEntry, j, tEntry->mPosX, tEntry->mPosX );\r
-        mContContent->at( i ) = NULL;\r
-        mDirtyFlag = true;\r
-      }\r
-      ++j;\r
-    }\r
-  }\r
-\r
-  if ( !mMaxSlots ) // reduce size only if not fixed-size\r
-  {\r
-    for ( ; j < i; ++j )\r
-      mContContent->pop_back();\r
-  }\r
-}\r
-\r
-bool PContainer::StartUse( uint32_t nExclusiveUseCharID )\r
-{\r
-  if ( mExclusiveUseCharID )\r
-    return false;\r
-  else\r
-  {\r
-    mExclusiveUseCharID = nExclusiveUseCharID;\r
-    return true;\r
-  }\r
-}\r
-\r
-bool PContainer::EndUse( uint32_t nExclusiveUseCharID )\r
-{\r
-  if ( nExclusiveUseCharID == mExclusiveUseCharID )\r
-  {\r
-    mExclusiveUseCharID = 0;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Warning] PContainer::EndUse called with CharID %d when CharID %d had exclusive use", nExclusiveUseCharID, mExclusiveUseCharID );\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PContainer::SQLLoad()\r
-{\r
-  if ( !mCharID )\r
-  {\r
-    return false;\r
-  }\r
-\r
-  MYSQL_RES *result;\r
-  MYSQL_ROW row;\r
-  char query[1024];\r
-  PContainerEntry* NewEntry;\r
-  bool SaveDirtyFlag;\r
-  uint8_t nSlotId;\r
-  //uint8_t nPosX, nPosY, nSizeX, nSizeY;\r
-\r
-  /*if (!mContContent.empty())\r
-  {\r
-    Console->Print(RED, BLACK, "PContainer::SQLLoad: We don't want to load inventory on non-empty inventory for char %d", mCharID);\r
-    return false;\r
-  }*/\r
-\r
-  snprintf( query, 1024, "SELECT * FROM inventory WHERE inv_charid='%d' AND inv_loc='%d' ORDER BY inv_x ASC", mCharID, mInvLoc );\r
-  result = MySQL->GameResQuery( query );\r
-  if ( result == NULL )\r
-  {\r
-    Console->Print( RED, BLACK, "[Warning] PContainer::SQLLoad could not load inventory from the database" );\r
-    Console->Print( "Query was:" );\r
-    Console->Print( "%s", query );\r
-    MySQL->ShowGameSQLError();\r
-    return false;\r
-  }\r
-  while (( row = mysql_fetch_row( result ) ) )\r
-  {\r
-    NewEntry = new PContainerEntry( row );\r
-    if ( NewEntry->mItem->GetItemID() )\r
-    {\r
-      nSlotId = NewEntry->mPosX;\r
-      SaveDirtyFlag = mDirtyFlag;\r
-\r
-      if ( ! this->GetFreeSlot( &nSlotId ) || ! this->AddEntry( NewEntry, nSlotId ) )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Warning] PContainer::SQLLoad: Can't add item %d in slot %d of char %d inventory", NewEntry->mItem->GetItemID(), nSlotId, mCharID );\r
-        delete NewEntry;\r
-        mDirtyFlag = SaveDirtyFlag;\r
-      }\r
-      else\r
-      {\r
-        mDirtyFlag  = SaveDirtyFlag || ( nSlotId != NewEntry->mPosX );\r
-      }\r
-    }\r
-    else\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Notice] Invalid item in DB (inv_id = %d) - Ignored", NewEntry->mInvID );\r
-      delete NewEntry;\r
-    }\r
-  }\r
-  MySQL->FreeGameSQLResult( result );\r
-  return true;\r
-}\r
-\r
-bool PContainer::SQLSave()\r
-{\r
-  if ( !mCharID )\r
-    return false;\r
-\r
-  PContainerEntry* ContEntry;\r
-  bool SavedOK = true;\r
-\r
-  for ( uint8_t i = 0; i < mContContent->size(); ++i )\r
-  {\r
-    if (( ContEntry = mContContent->at( i ) ) )\r
-    {\r
-      if (( ContEntry->mDirtyFlag ) )\r
-      {\r
-        SavedOK = SavedOK && ContEntry->SQLSave( mCharID, mInvLoc );\r
-      }\r
-    }\r
-  }\r
-\r
-  if ( SavedOK )\r
-  {\r
-    mDirtyFlag = false;\r
-  }\r
-  return SavedOK;\r
-}\r
-\r
-bool PContainer::IsSlotFree( uint8_t nSlotId )\r
-{\r
-  if ( !IsSlotAllowed( nSlotId ) )\r
-    return false;\r
-\r
-  if ( nSlotId >= mContContent->size() )\r
-    return true;\r
-  else\r
-    return !( mContContent->at( nSlotId ) );\r
-}\r
-\r
-bool PContainer::AddItem( PItem* NewItem, uint32_t nInvID, uint8_t nPosX, uint8_t nPosY, bool SetDirty )\r
-{\r
-  /* --- auto stacking not implemented yet\r
-  1 - if stackable, check if same item(S) exists\r
-  2 - - if exist\r
-  3 - - - add to stack\r
-  4 - - - if no new stack remains, update LastPutXY & return true\r
-  5 - find an empty space\r
-  6 -\r
-  x - put in new space, update LastPutXY & return true\r
-\r
-  */\r
-\r
-  if ( NewItem->GetItemID() == 0 )\r
-  {\r
-    Console->Print( RED, BLACK, "[Warning] PContainer::AddItem: invalid item : ID 0" );\r
-    return false;\r
-  }\r
-\r
-  PContainerEntry* NewEntry = new PContainerEntry( NewItem, nPosX, nPosY, nInvID, SetDirty );\r
-\r
-  if ( this->GetFreeSlot( &nPosX ) && this->AddEntry( NewEntry, nPosX ) ) // !!!! nPosX not good\r
-    return true;\r
-  else\r
-  {\r
-    delete NewEntry;\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PContainer::MoveItem( uint8_t srcSlotId, uint8_t nCount, PContainer* dstContainer, uint8_t dstSlotId, uint8_t nPosX, uint8_t nPosY )\r
-{\r
-  if ( dstContainer == this )\r
-    return this->MoveItem( srcSlotId, nCount, dstSlotId );\r
-  else if ( dstContainer->GetFreeSlot( &dstSlotId ) )\r
-  {\r
-    uint8_t savePosX, savePosY;\r
-    PContainerEntry* tEntry = this->GetEntry( srcSlotId );\r
-    if ( tEntry )\r
-    {\r
-      tEntry->Get2DPos( &savePosX, &savePosY );\r
-      tEntry->Set2DPos( nPosX, nPosY );\r
-      if ( !dstContainer->AddEntry( tEntry, dstSlotId ) )\r
-      {\r
-        tEntry->Set2DPos( savePosX, savePosY );\r
-        Console->Print( RED, BLACK, "[Warning] PContainer::MoveItem - Couldn't add entry !" );\r
-        return false;\r
-      }\r
-      tEntry->Get2DPos( &nPosX, &nPosY );\r
-      tEntry->Set2DPos( savePosX, savePosY );\r
-      RemoveEntry( srcSlotId );\r
-      tEntry->Set2DPos( nPosX, nPosY );\r
-\r
-      if ( dstContainer->mCharID != this->mCharID ) // save at once if owner changes\r
-      {\r
-        if ( !tEntry->SQLSave( dstContainer->mCharID, dstContainer->mInvLoc ) ) // TODO: improve to manage non-persistent containers\r
-        {\r
-          Console->Print( RED, BLACK, "[Warning] PContainer::MoveItem - Moved entry not saved" );\r
-        }\r
-        //else\r
-        //{\r
-        //  Console->Print(GREEN, BLACK, "[Succes] PContainer::MoveItem - Moved entry saved");\r
-        //}\r
-      }\r
-      return true;\r
-    }\r
-    else\r
-    {\r
-      Console->Print( RED, BLACK, "[Warning] trying to move invalid entry %d", srcSlotId );\r
-      return false;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-// !!! Not partial move yet !!!\r
-bool PContainer::MoveItem( uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId )\r
-{\r
-  if ( !( IsSlotAllowed( srcSlotId ) && IsSlotAllowed( dstSlotId ) ) )\r
-    return false;\r
-\r
-  if ( srcSlotId == dstSlotId )\r
-    return true;\r
-\r
-  if (( mContContent->at( srcSlotId ) )\r
-      && ( mContContent->at( srcSlotId )->mItem->GetStackSize() >= nCount )\r
-      && IsSlotFree( dstSlotId ) )\r
-  {\r
-    PContainerEntry* tEntry = mContContent->at( dstSlotId ) = mContContent->at( srcSlotId );\r
-    tEntry->mPosX = dstSlotId;\r
-    tEntry->mPosY = 0;\r
-    tEntry->mDirtyFlag = true;\r
-    mContContent->at( srcSlotId ) = NULL;\r
-    mDirtyFlag = true;\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-std::vector< PContainerEntry* >* PContainer::GetEntries()\r
-{\r
-  std::vector< PContainerEntry* >* Entries = new std::vector< PContainerEntry* >;\r
-\r
-  for ( uint8_t i = 0; i < mContContent->size(); ++i )\r
-  {\r
-    if ( mContContent->at( i ) )\r
-      Entries->push_back( mContContent->at( i ) );\r
-  }\r
-\r
-  return Entries;\r
-}\r
-\r
-PContainerEntry* PContainer::GetEntry( uint8_t nSlotId )\r
-{\r
-  if ( nSlotId >= mContContent->size() )\r
-    return NULL;\r
-\r
-  return mContContent->at( nSlotId );\r
-}\r
-\r
-PItem* PContainer::GetItem( uint8_t nSlotId )\r
-{\r
-  PContainerEntry* tEntry = this->GetEntry( nSlotId );\r
-  return ( tEntry ? tEntry->mItem : NULL );\r
-}\r
-\r
-uint8_t PContainer::RandomFill( uint8_t nItemCount, int nItemContainerDefIndex )\r
-{\r
-  PItem* nItem = NULL;\r
-  const PDefItems* nItemDef;\r
-  uint32_t nItemSeqId;\r
-  uint8_t CreatedCount = 0;\r
-\r
-  if ( !nItemCount )\r
-    nItemCount = mMaxSlots;\r
-  if ( !nItemCount )\r
-    nItemCount = CONTAINER_MAX_SIZE;\r
-\r
-  if ( nItemContainerDefIndex >= 0 )\r
-  {\r
-    int newItemIdx, newItemIndex;\r
-    uint8_t newItemQuality;\r
-\r
-    const PDefItemContainer* containerDef = GameDefs->ItemContainers()->GetDef( nItemContainerDefIndex );\r
-    if ( containerDef )\r
-    {\r
-      for ( uint8_t i = 0; i < nItemCount; ++i )\r
-      {\r
-        newItemIdx = containerDef->GetRandomItemIdx();\r
-        if ( newItemIdx >= 0 )\r
-        {\r
-          newItemIndex = containerDef->GetItemId( newItemIdx );\r
-          newItemQuality = ( uint8_t )( 255 & int( 255.0 * containerDef->GetQuality( newItemIdx ) ) );\r
-          if ( newItemIndex <= 0 ) // Item group\r
-          {\r
-            newItemIndex = GameDefs->Items()->GetRandomItemIdFromGroup( -newItemIndex );\r
-          }\r
-          nItem = new PItem( newItemIndex, 1, 255, newItemQuality, newItemQuality, newItemQuality, newItemQuality, 255 );\r
-          if ( nItem->GetItemID() )\r
-          {\r
-            if ( this->AddItem( nItem ) )\r
-            {\r
-              ++CreatedCount;\r
-            }\r
-            else\r
-            {\r
-              Console->Print( YELLOW, BLACK, "[Warning] Couldn't add item %d at pos %d", nItem->GetItemID(), i );\r
-              delete nItem;\r
-            }\r
-          }\r
-        }\r
-      }\r
-    }\r
-    else\r
-      Console->Print( YELLOW, BLACK, "[Warning] Container def not found: %d", nItemContainerDefIndex );\r
-  }\r
-  else\r
-  {\r
-    int NumItemsDefs = GameDefs->Items()->GetNumDefs();\r
-\r
-    for ( uint8_t i = 0; i < nItemCount; ++i )\r
-    {\r
-      nItemSeqId = GetRandom( NumItemsDefs, 1 );\r
-\r
-      if (( nItemDef = GameDefs->Items()->GetDefBySeqIndex( nItemSeqId ) ) )\r
-      {\r
-        nItem = new PItem( nItemDef->GetIndex(), 1, 255, 255, 255, 255, 255, 255 );\r
-        if ( nItem->GetItemID() )\r
-        {\r
-          if ( this->AddItem( nItem ) )\r
-          {\r
-            ++CreatedCount;\r
-          }\r
-          else\r
-          {\r
-            //Console->Print(GREEN, BLACK, "Couldn't add item % d at pos % d", nItem->GetItemID(), i);\r
-            delete nItem;\r
-          }\r
-        }\r
-      }\r
-      else\r
-        Console->Print( RED, BLACK, "[Warning] PContainer::RandomFill Couldn't find item for SEQ %d", nItemSeqId );\r
-    }\r
-  }\r
-  return CreatedCount;\r
-}\r
-\r
-void PContainer::Dump()\r
-{\r
-  PContainerEntry* tmpEntry;\r
-  PItem* tmpItem;\r
-  uint8_t i;\r
-  //uint8_t y, x;\r
-\r
-  for ( i = 0; i < mContContent->size(); ++i )\r
-  {\r
-    if (( tmpEntry = mContContent->at( i ) ) )\r
-    {\r
-      tmpItem = tmpEntry->mItem;\r
-      Console->Print( GREEN, BLACK, "%d: (%d,%d) (%d x %d) Item %d (InvID %d) %s %s", i, tmpEntry->mPosX, tmpEntry->mPosY, tmpItem->GetSizeX(), tmpItem->GetSizeY(), tmpItem->GetItemID(), tmpEntry->mInvID, tmpItem->GetName().c_str(), tmpEntry->mDirtyFlag ? "[*]" : "" );\r
-    }\r
-  }\r
-\r
-  if ( mDirtyFlag )\r
-    Console->Print( GREEN, BLACK, "Dirty" );\r
-  Console->Print( GREEN, BLACK, "------------------------------------" );\r
-}\r
-\r
-/* --- PContainerWithHoles class --- */\r
-\r
-\r
-/* --- PContainerAutoCompact --- */\r
-PContainerEntry* PContainerAutoCompact::RemoveEntry( uint8_t nSlotId )\r
-{\r
-  PContainerEntry* tEntry = NULL;\r
-\r
-  if ( nSlotId < mContContent->size() )\r
-  {\r
-    tEntry = mContContent->at( nSlotId );\r
-    mContContent->at( nSlotId ) = NULL;\r
-    if ( nSlotId == ( mContContent->size() - 1 ) )\r
-      mContContent->pop_back();\r
-    else\r
-      Compact( nSlotId );\r
-  }\r
-  return tEntry;\r
-}\r
-\r
-bool PContainerAutoCompact::GetFreeSlot( uint8_t* nSlotId ) // not optimal. A "first free from end" would be better at PContainer level\r
-{\r
-  bool Found = false;\r
-\r
-  for ( *nSlotId = 0; *nSlotId < mContContent->size(); ++*nSlotId )\r
-    if ( ! mContContent->at( *nSlotId ) )\r
-    {\r
-      Found = true;\r
-      break;\r
-    }\r
-  return ( Found || IsSlotAllowed( *nSlotId ) );\r
-}\r
-\r
-bool PContainerAutoCompact::MoveItem( uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId )\r
-{\r
-  srcSlotId = nCount = dstSlotId;\r
-  return false;\r
-}\r
-\r
-/* --- PContainer2D class --- */\r
-\r
-void PContainer2D::SetEntryPosXY( PContainerEntry* nEntry, uint8_t /*nSlotId*/, uint8_t nPosX, uint8_t nPosY )\r
-{\r
-  //nSlotId = nSlotId;\r
-  if (( nPosX >= INV_BACKPACK_COLS ) || ( nPosY == 255 ) )\r
-  {\r
-    nPosX = nPosY = 0;\r
-  }\r
-  nEntry->Set2DPos( nPosX, nPosY );\r
-  mDirtyFlag = mDirtyFlag || nEntry->mDirtyFlag;\r
-}\r
-\r
-/* --- PContainer2DWorkaround --- */\r
-/////\r
-PContainer2DWorkaround::PContainer2DWorkaround( uint8_t nMaxSlots ) : PContainerWithHoles( nMaxSlots )\r
-{\r
-  mNextFreeSlot = 0;\r
-  mMaxCols = 254;\r
-  mMaxRows = 254;\r
-  mRows = 0;\r
-  AddRow();\r
-}\r
-\r
-PContainer2DWorkaround::~PContainer2DWorkaround()\r
-{\r
-  for ( int i = 0; i < mRows; i++ )\r
-    delete mContSpace[i];\r
-}\r
-\r
-bool PContainer2DWorkaround::AddEntry( PContainerEntry* tEntry, uint8_t nSlotId )\r
-{\r
-  if ( IsSlotAllowed( nSlotId ) )\r
-  {\r
-    if ( FindValid2DPos( tEntry ) )\r
-    {\r
-      for ( uint8_t i = mContContent->size(); i <= nSlotId; ++i ) // Extend as needed\r
-        mContContent->push_back( static_cast<PContainerEntry *>(NULL) );\r
-      if ( mContContent->at( nSlotId ) )\r
-      {\r
-        Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::AddEntry: Target entry already %d in use !!!", nSlotId );\r
-        return false;\r
-      }\r
-      mContContent->at( nSlotId ) = tEntry;\r
-      mDirtyFlag = true;\r
-      //this->SetEntryPosXY(tEntry, nSlotId, tEntry->mPosX, tEntry->mPosY);\r
-      mDirtyFlag = mDirtyFlag || tEntry->mDirtyFlag;\r
-      SetUsed( tEntry );\r
-      return true;\r
-    }\r
-    else\r
-    {\r
-      Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::AddEntry: No 2D space left !!!", nSlotId, mMaxSlots );\r
-      return false;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::AddEntry: Target entry %d not allowed (max = %d) !!!", nSlotId, mMaxSlots );\r
-    return false;\r
-  }\r
-\r
-}\r
-\r
-PContainerEntry* PContainer2DWorkaround::RemoveEntry( uint8_t nSlotId )\r
-{\r
-  PContainerEntry* tEntry = NULL;\r
-\r
-  if ( nSlotId < mContContent->size() )\r
-  {\r
-    tEntry = mContContent->at( nSlotId );\r
-    mContContent->at( nSlotId ) = NULL;\r
-    //Console->Print(YELLOW, BLACK, "Cleaning (%d,%d) (%d x %d)", tEntry->mPosX, tEntry->mPosY, tEntry->mItem->GetSizeX(), tEntry->mItem->GetSizeY());\r
-    SetUsed( tEntry, false );\r
-  }\r
-  return tEntry;\r
-}\r
-\r
-bool PContainer2DWorkaround::GetFreeSlot( uint8_t* nSlotId )\r
-{\r
-  if ( IsSlotAllowed( mNextFreeSlot ) )\r
-  {\r
-    *nSlotId = mNextFreeSlot++;\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-void PContainer2DWorkaround::SetEntryPosXY( PContainerEntry* nEntry, uint8_t /*nSlotId*/, uint8_t nPosX, uint8_t nPosY )\r
-{\r
-  //nSlotId = nSlotId;\r
-  if (( nPosX == 255 ) && ( nPosY == 255 ) )\r
-  {\r
-    nEntry->Set2DPos( 255, 255 );\r
-  }\r
-  else\r
-  {\r
-    if (( nPosX >= mMaxCols ) || ( nPosY >= mMaxRows ) )\r
-    {\r
-      nPosX = nPosY = 0;\r
-    }\r
-    nEntry->Set2DPos( nPosX, nPosY );\r
-\r
-    if ( !FindValid2DPos( nEntry ) )\r
-    {\r
-      nEntry->Set2DPos( 255, 255 );\r
-      Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::SetEntryPosXY - Space position already used" );\r
-    }\r
-  }\r
-  mDirtyFlag = mDirtyFlag || nEntry->mDirtyFlag;\r
-}\r
-\r
-bool PContainer2DWorkaround::MoveItem( uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId )\r
-{\r
-  srcSlotId = nCount = dstSlotId;\r
-  return false;\r
-}\r
-\r
-void PContainer2DWorkaround::AddRow()\r
-{\r
-  if ( mRows + 1 < mMaxRows )\r
-  {\r
-    std::vector<bool>* NewRow = new std::vector<bool>( mMaxCols, 0 );\r
-    mContSpace.push_back( NewRow );\r
-    ++mRows;\r
-  }\r
-}\r
-\r
-bool PContainer2DWorkaround::Is2DFree( uint8_t PosX, uint8_t PosY, uint8_t SizeX, uint8_t SizeY )\r
-{\r
-  if (( PosX == 255 ) && ( PosY == 255 ) )\r
-  {\r
-    return true;\r
-  }\r
-  if ( !Is2DPosAllowed( PosX, PosY, SizeX, SizeY ) )\r
-    return false;\r
-\r
-  uint8_t h, v;\r
-  for ( v = 0; ( v < SizeY ) && ( PosY + v < mRows ) ; v++ ) // what is over existing rows is free\r
-  {\r
-    for ( h = 0; h < SizeX; h++ )\r
-    {\r
-      if ( PosX + h >= mMaxCols ) // what is over max col is not free\r
-        return false;\r
-\r
-      if (( *mContSpace[PosY+v] )[PosX+h] )\r
-        return false;\r
-    }\r
-  }\r
-  return ( PosY + SizeY <= mMaxRows );\r
-}\r
-\r
-void PContainer2DWorkaround::SetUsed( PContainerEntry* nEntry, bool Value )\r
-{\r
-  uint8_t PosX = nEntry->mPosX;;\r
-  uint8_t PosY = nEntry->mPosY;\r
-  uint8_t SizeX = nEntry->mItem->GetSizeX();\r
-  uint8_t SizeY = nEntry->mItem->GetSizeY();\r
-\r
-  if ( !Is2DPosAllowed( PosX, PosY, SizeX, SizeY ) )\r
-    return;\r
-\r
-  while ( PosY + SizeY > mRows ) // add new rows when needed\r
-    AddRow();\r
-\r
-  uint8_t h, v;\r
-  for ( v = 0; ( v < SizeY ) && ( PosY + v < mRows ) ; v++ )\r
-  {\r
-    for ( h = 0; ( h < SizeX ) && ( PosX + h < mMaxCols ); h++ )\r
-      ( *mContSpace[PosY+v] )[PosX+h] = Value;\r
-  }\r
-}\r
-\r
-bool PContainer2DWorkaround::FindValid2DPos( PContainerEntry* nEntry )\r
-{\r
-  bool Found = false;\r
-  uint8_t SizeX = nEntry->mItem->GetSizeX();\r
-  uint8_t SizeY = nEntry->mItem->GetSizeY();\r
-  uint8_t dPosX, dPosY;\r
-\r
-  if ( Is2DFree( nEntry->mPosX, nEntry->mPosY, SizeX, SizeY ) )\r
-    Found = true;\r
-  else\r
-  {\r
-    dPosX = nEntry->mPosX;\r
-    dPosY = nEntry->mPosY;\r
-    if ( !Is2DPosAllowed( dPosX, dPosY, SizeX, SizeY ) )\r
-    {\r
-      dPosX = dPosY = 0;\r
-      //Console->Print(YELLOW, BLACK, "Init pos RESET");\r
-    }\r
-\r
-    while ( !Found && Is2DPosAllowed( dPosX, dPosY, SizeX, SizeY ) )\r
-    {\r
-      //Console->Print(YELLOW, BLACK, "Searching line %d", dPosY);\r
-      for ( ; dPosX <= ( mMaxCols - SizeX ); ++dPosX )\r
-      {\r
-        if (( Found = Is2DFree( dPosX, dPosY, SizeX, SizeY ) ) )\r
-          break;\r
-      }\r
-      if ( Found )\r
-      {\r
-        nEntry->mPosX = dPosX;\r
-        nEntry->mPosY = dPosY;\r
-        nEntry->mDirtyFlag = true;\r
-        //Console->Print(YELLOW, BLACK, "Success: Found new space position : (%d,%d)", dPosX, dPosY);\r
-        break;\r
-      }\r
-      ++dPosY;\r
-      dPosX = 0;\r
-    }\r
-  }\r
-  return Found;\r
-}\r
-\r
-void PContainer2DWorkaround::Dump()\r
-{\r
-  PContainer::Dump();\r
-\r
-  std::string tmpS;\r
-  uint8_t y, x;\r
-  for ( y = 0 ; y < mRows; y++ )\r
-  {\r
-    tmpS = "";\r
-    for ( x = 0 ; x < mMaxCols; x++ )\r
-    {\r
-      tmpS += (( *mContSpace[y] )[x] ) ? "X" : ".";\r
-    }\r
-    Console->Print( "%s", tmpS.c_str() );\r
-  }\r
-  Console->Print( GREEN, BLACK, "------------------------------------" );\r
-}\r
-\r
-/* --- PContainerAutoFindFree --- */\r
-bool PContainerAutoFindFree::GetFreeSlot( uint8_t* nSlotId )\r
-{\r
-  bool Found = false;\r
-\r
-  for ( *nSlotId = 0; *nSlotId < mContContent->size(); ++*nSlotId )\r
-    if ( ! mContContent->at( *nSlotId ) )\r
-    {\r
-      Found = true;\r
-      break;\r
-    }\r
-\r
-  return ( Found || IsSlotAllowed( *nSlotId ) );\r
-}\r
-\r
-/* --- PContainerAutoCompactOnClose --- */\r
-bool PContainerAutoCompactOnClose::EndUse( uint32_t nExclusiveUseCharID )\r
-{\r
-  if ( nExclusiveUseCharID == mExclusiveUseCharID )\r
-  {\r
-    mExclusiveUseCharID = 0;\r
-    Compact();\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] PContainerAutoCompactOnClose::EndUse called with CharID %d when CharID %d had exclusive use", nExclusiveUseCharID, mExclusiveUseCharID );\r
-    return false;\r
-  }\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/* --- PContainerEntry class --- */
+
+PContainerEntry::PContainerEntry( PItem* nItem, uint8_t X, uint8_t Y, uint32_t nInvID, bool SetDirty )
+{
+  mItem = nItem;
+  mPosX = X;
+  mPosY = Y;
+  mInvID = nInvID;
+  mDirtyFlag = SetDirty;
+}
+
+PContainerEntry::PContainerEntry( MYSQL_ROW row )
+{
+  mItem = NULL;
+  mInvID = atoi( row[i_invid] );
+  mPosX = atoi( row[i_x] );
+  mPosY = atoi( row[i_y] );
+  mDirtyFlag = false;
+
+  uint32_t nItemID = atoi( row[i_itemid] );
+  uint8_t nStackSize = atoi( row[i_qty] );
+  //     = std::atoi(row[i_type]);
+  uint8_t CurDur = atoi( row[i_curdur] );
+  uint8_t Dmg = atoi( row[i_dmg] );
+  uint8_t Freq = atoi( row[i_freq] );
+  uint8_t Hand = atoi( row[i_hand] );
+  uint8_t Rng = atoi( row[i_rng] );
+  uint8_t Dur = atoi( row[i_maxdur] );
+
+  mItem = new PItem( nItemID, nStackSize, CurDur, Dur, Dmg, Freq, Hand, Rng );
+}
+
+PContainerEntry::~PContainerEntry()
+{
+  delete mItem;
+}
+
+bool PContainerEntry::SQLSave( uint32_t CharID, uint32_t InvLoc )
+{
+  std::string query, queryv;
+
+  queryv += Ssprintf( " inv_charid='%u',inv_loc='%u',inv_x='%u',inv_y='%u'", CharID, InvLoc, mPosX, mPosY );
+  queryv += Ssprintf( ",inv_itemid='%u',inv_qty='%u'", mItem->mItemID, mItem->mStackSize );
+  //queryv += Ssprintf( ",inv_type='%u'", 0 );
+  queryv += Ssprintf( ",inv_cdur='%u'", mItem->mCurDuration );
+  queryv += Ssprintf( ",inv_dmg='%u'", mItem->mDamages );
+  queryv += Ssprintf( ",inv_frq='%u'", mItem->mFrequency );
+  queryv += Ssprintf( ",inv_hnd='%u'", mItem->mHandling );
+  queryv += Ssprintf( ",inv_rng='%u'", mItem->mRange );
+  queryv += Ssprintf( ",inv_mdur='%u'", mItem->mMaxDuration );
+
+  if ( mInvID )
+  {
+    query = "UPDATE inventory SET " + queryv;
+    query += Ssprintf( " WHERE inv_id='%u' LIMIT 1;", mInvID );
+  }
+  else
+  {
+    query = "INSERT INTO inventory SET " + queryv + ";";
+  }
+
+  if ( MySQL->GameQuery( query.c_str() ) )
+  {
+    Console->Print( RED, BLACK, "PContainerEntry::SQLSave could not add/update some inventory item in the database" );
+    Console->Print( "Query was:" );
+    Console->Print( "%s", query.c_str() );
+    MySQL->ShowGameSQLError();
+    return false;
+  }
+  else
+  {
+    if ( !mInvID )
+    {
+      mInvID = MySQL->GetLastGameInsertId();
+      if ( gDevDebug )
+        Console->Print( GREEN, BLACK, "New item %d added to inventory DB", mInvID );
+    }
+//Console->Print(YELLOW, BLACK, "PContainerEntry::SQLSave - Query was:");
+//Console->Print(YELLOW, BLACK, "%s", query.c_str());
+    mDirtyFlag = false;
+    return true;
+  }
+}
+
+bool PContainerEntry::SQLDelete()
+{
+  std::string query;
+
+  if ( mInvID )
+  {
+    query = Ssprintf( "DELETE FROM inventory WHERE inv_id='%u' LIMIT 1;", mInvID );
+
+    if ( MySQL->GameQuery( query.c_str() ) )
+    {
+      Console->Print( RED, BLACK, "PContainerEntry::SQLDelete could not delete some container item from the database" );
+      Console->Print( "Query was:" );
+      Console->Print( "%s", query.c_str() );
+      MySQL->ShowGameSQLError();
+      return false;
+    }
+    else
+    {
+      if ( gDevDebug )
+        Console->Print( GREEN, BLACK, "Item %d deleted from container DB", mInvID );
+      mInvID = 0;
+      delete mItem;
+      mItem = NULL;
+
+      mDirtyFlag = false;
+      return true;
+    }
+  }
+  else
+  {
+    Console->Print( YELLOW, BLACK, "PContainerEntry::SQLDelete: Item was not in inventory DB" );
+    return true;
+  }
+}
+
+/* --- PContainer class --- */
+
+PContainer::PContainer( uint8_t nMaxSlots )
+{
+  mMaxSlots = ( nMaxSlots > CONTAINER_MAX_SIZE ? CONTAINER_MAX_SIZE : nMaxSlots ) ;
+  if ( mMaxSlots )
+    mContContent = new std::vector< PContainerEntry* >( mMaxSlots, NULL );
+  else
+    mContContent = new std::vector< PContainerEntry* >;
+  mCharID = 0;
+  mInvLoc = 0;
+  mExclusiveUseCharID = 0;
+  mDirtyFlag = false;
+}
+
+PContainer::~PContainer()
+{
+  for ( uint8_t i = 0; i < mContContent->size(); ++i )
+    delete mContContent->at( i );
+
+  if ( mExclusiveUseCharID )
+    Console->Print( RED, BLACK, "[ERROR] PContainer::~PContainer: Char %d still has exclusive access to container !!! Bad Pointer error will happen.", mExclusiveUseCharID );
+}
+
+bool PContainer::AddEntry( PContainerEntry* NewEntry, uint8_t nSlotId )
+{
+  if ( IsSlotAllowed( nSlotId ) )
+  {
+    for ( uint8_t i = mContContent->size(); i <= nSlotId; ++i ) // Extend as needed
+      mContContent->push_back( static_cast<PContainerEntry*>(NULL) );
+    if ( mContContent->at( nSlotId ) )
+    {
+      Console->Print( RED, BLACK, "[Warning] PContainer::AddEntry: Target entry already %d in use !!!", nSlotId );
+      return false;
+    }
+    mContContent->at( nSlotId ) = NewEntry;
+    mDirtyFlag = true;
+    this->SetEntryPosXY( NewEntry, nSlotId, NewEntry->mPosX, NewEntry->mPosY );
+    return true;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Warning] PContainer::AddEntry: Target entry %d not allowed (max = %d) !!!", nSlotId, mMaxSlots );
+    return false;
+  }
+  /* --- degug only ---
+  Console->Print(GREEN, BLACK, "PContainer::AddEntry: added item %d at pos (%d,%d)", NewEntry->mItem->GetItemID(), NewEntry->mPosX, NewEntry->mPosY);
+
+  Dump();
+  ---            --- */
+}
+
+void PContainer::SetEntryPosXY( PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX, uint8_t nPosY )
+{
+  nPosX = nPosY;
+  nEntry->Set2DPos( nSlotId, 0 );
+  mDirtyFlag = mDirtyFlag || nEntry->mDirtyFlag;
+}
+
+PContainerEntry* PContainer::RemoveEntry( uint8_t nSlotId )
+{
+  PContainerEntry* tEntry = NULL;
+
+  if ( nSlotId < mContContent->size() )
+  {
+    tEntry = mContContent->at( nSlotId );
+    mContContent->at( nSlotId ) = NULL;
+  }
+  return tEntry;
+}
+
+bool PContainer::GetFreeSlot( uint8_t* nSlotId )
+{
+  return IsSlotFree( *nSlotId );
+}
+
+void PContainer::Compact( uint8_t startSlotId )
+{
+  uint8_t i, j;
+  PContainerEntry* tEntry;
+
+  for ( i = j = startSlotId; i < mContContent->size(); ++i )
+  {
+    if ( mContContent->at( i ) )
+    {
+      if ( j < i )
+      {
+        mContContent->at( j ) = tEntry = mContContent->at( i );
+        this->SetEntryPosXY( tEntry, j, tEntry->mPosX, tEntry->mPosX );
+        mContContent->at( i ) = NULL;
+        mDirtyFlag = true;
+      }
+      ++j;
+    }
+  }
+
+  if ( !mMaxSlots ) // reduce size only if not fixed-size
+  {
+    for ( ; j < i; ++j )
+      mContContent->pop_back();
+  }
+}
+
+bool PContainer::StartUse( uint32_t nExclusiveUseCharID )
+{
+  if ( mExclusiveUseCharID )
+    return false;
+  else
+  {
+    mExclusiveUseCharID = nExclusiveUseCharID;
+    return true;
+  }
+}
+
+bool PContainer::EndUse( uint32_t nExclusiveUseCharID )
+{
+  if ( nExclusiveUseCharID == mExclusiveUseCharID )
+  {
+    mExclusiveUseCharID = 0;
+    return true;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Warning] PContainer::EndUse called with CharID %d when CharID %d had exclusive use", nExclusiveUseCharID, mExclusiveUseCharID );
+    return false;
+  }
+}
+
+bool PContainer::SQLLoad()
+{
+  if ( !mCharID )
+  {
+    return false;
+  }
+
+  MYSQL_RES *result;
+  MYSQL_ROW row;
+  char query[1024];
+  PContainerEntry* NewEntry;
+  bool SaveDirtyFlag;
+  uint8_t nSlotId;
+  //uint8_t nPosX, nPosY, nSizeX, nSizeY;
+
+  /*if (!mContContent.empty())
+  {
+    Console->Print(RED, BLACK, "PContainer::SQLLoad: We don't want to load inventory on non-empty inventory for char %d", mCharID);
+    return false;
+  }*/
+
+  snprintf( query, 1024, "SELECT * FROM inventory WHERE inv_charid='%d' AND inv_loc='%d' ORDER BY inv_x ASC", mCharID, mInvLoc );
+  result = MySQL->GameResQuery( query );
+  if ( result == NULL )
+  {
+    Console->Print( RED, BLACK, "[Warning] PContainer::SQLLoad could not load inventory from the database" );
+    Console->Print( "Query was:" );
+    Console->Print( "%s", query );
+    MySQL->ShowGameSQLError();
+    return false;
+  }
+  while (( row = mysql_fetch_row( result ) ) )
+  {
+    NewEntry = new PContainerEntry( row );
+    if ( NewEntry->mItem->GetItemID() )
+    {
+      nSlotId = NewEntry->mPosX;
+      SaveDirtyFlag = mDirtyFlag;
+
+      if ( ! this->GetFreeSlot( &nSlotId ) || ! this->AddEntry( NewEntry, nSlotId ) )
+      {
+        Console->Print( YELLOW, BLACK, "[Warning] PContainer::SQLLoad: Can't add item %d in slot %d of char %d inventory", NewEntry->mItem->GetItemID(), nSlotId, mCharID );
+        delete NewEntry;
+        mDirtyFlag = SaveDirtyFlag;
+      }
+      else
+      {
+        mDirtyFlag  = SaveDirtyFlag || ( nSlotId != NewEntry->mPosX );
+      }
+    }
+    else
+    {
+      Console->Print( YELLOW, BLACK, "[Notice] Invalid item in DB (inv_id = %d) - Ignored", NewEntry->mInvID );
+      delete NewEntry;
+    }
+  }
+  MySQL->FreeGameSQLResult( result );
+  return true;
+}
+
+bool PContainer::SQLSave()
+{
+  if ( !mCharID )
+    return false;
+
+  PContainerEntry* ContEntry;
+  bool SavedOK = true;
+
+  for ( uint8_t i = 0; i < mContContent->size(); ++i )
+  {
+    if (( ContEntry = mContContent->at( i ) ) )
+    {
+      if (( ContEntry->mDirtyFlag ) )
+      {
+        SavedOK = SavedOK && ContEntry->SQLSave( mCharID, mInvLoc );
+      }
+    }
+  }
+
+  if ( SavedOK )
+  {
+    mDirtyFlag = false;
+  }
+  return SavedOK;
+}
+
+bool PContainer::IsSlotFree( uint8_t nSlotId )
+{
+  if ( !IsSlotAllowed( nSlotId ) )
+    return false;
+
+  if ( nSlotId >= mContContent->size() )
+    return true;
+  else
+    return !( mContContent->at( nSlotId ) );
+}
+
+bool PContainer::AddItem( PItem* NewItem, uint32_t nInvID, uint8_t nPosX, uint8_t nPosY, bool SetDirty )
+{
+  /* --- auto stacking not implemented yet
+  1 - if stackable, check if same item(S) exists
+  2 - - if exist
+  3 - - - add to stack
+  4 - - - if no new stack remains, update LastPutXY & return true
+  5 - find an empty space
+  6 -
+  x - put in new space, update LastPutXY & return true
+
+  */
+
+  if ( NewItem->GetItemID() == 0 )
+  {
+    Console->Print( RED, BLACK, "[Warning] PContainer::AddItem: invalid item : ID 0" );
+    return false;
+  }
+
+  PContainerEntry* NewEntry = new PContainerEntry( NewItem, nPosX, nPosY, nInvID, SetDirty );
+
+  if ( this->GetFreeSlot( &nPosX ) && this->AddEntry( NewEntry, nPosX ) ) // !!!! nPosX not good
+    return true;
+  else
+  {
+    delete NewEntry;
+    return false;
+  }
+}
+
+bool PContainer::MoveItem( uint8_t srcSlotId, uint8_t nCount, PContainer* dstContainer, uint8_t dstSlotId, uint8_t nPosX, uint8_t nPosY )
+{
+  if ( dstContainer == this )
+    return this->MoveItem( srcSlotId, nCount, dstSlotId );
+  else if ( dstContainer->GetFreeSlot( &dstSlotId ) )
+  {
+    uint8_t savePosX, savePosY;
+    PContainerEntry* tEntry = this->GetEntry( srcSlotId );
+    if ( tEntry )
+    {
+      tEntry->Get2DPos( &savePosX, &savePosY );
+      tEntry->Set2DPos( nPosX, nPosY );
+      if ( !dstContainer->AddEntry( tEntry, dstSlotId ) )
+      {
+        tEntry->Set2DPos( savePosX, savePosY );
+        Console->Print( RED, BLACK, "[Warning] PContainer::MoveItem - Couldn't add entry !" );
+        return false;
+      }
+      tEntry->Get2DPos( &nPosX, &nPosY );
+      tEntry->Set2DPos( savePosX, savePosY );
+      RemoveEntry( srcSlotId );
+      tEntry->Set2DPos( nPosX, nPosY );
+
+      if ( dstContainer->mCharID != this->mCharID ) // save at once if owner changes
+      {
+        if ( !tEntry->SQLSave( dstContainer->mCharID, dstContainer->mInvLoc ) ) // TODO: improve to manage non-persistent containers
+        {
+          Console->Print( RED, BLACK, "[Warning] PContainer::MoveItem - Moved entry not saved" );
+        }
+        //else
+        //{
+        //  Console->Print(GREEN, BLACK, "[Succes] PContainer::MoveItem - Moved entry saved");
+        //}
+      }
+      return true;
+    }
+    else
+    {
+      Console->Print( RED, BLACK, "[Warning] trying to move invalid entry %d", srcSlotId );
+      return false;
+    }
+  }
+  return false;
+}
+
+// !!! Not partial move yet !!!
+bool PContainer::MoveItem( uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId )
+{
+  if ( !( IsSlotAllowed( srcSlotId ) && IsSlotAllowed( dstSlotId ) ) )
+    return false;
+
+  if ( srcSlotId == dstSlotId )
+    return true;
+
+  if (( mContContent->at( srcSlotId ) )
+      && ( mContContent->at( srcSlotId )->mItem->GetStackSize() >= nCount )
+      && IsSlotFree( dstSlotId ) )
+  {
+    PContainerEntry* tEntry = mContContent->at( dstSlotId ) = mContContent->at( srcSlotId );
+    tEntry->mPosX = dstSlotId;
+    tEntry->mPosY = 0;
+    tEntry->mDirtyFlag = true;
+    mContContent->at( srcSlotId ) = NULL;
+    mDirtyFlag = true;
+    return true;
+  }
+  else
+    return false;
+}
+
+std::vector< PContainerEntry* >* PContainer::GetEntries()
+{
+  std::vector< PContainerEntry* >* Entries = new std::vector< PContainerEntry* >;
+
+  for ( uint8_t i = 0; i < mContContent->size(); ++i )
+  {
+    if ( mContContent->at( i ) )
+      Entries->push_back( mContContent->at( i ) );
+  }
+
+  return Entries;
+}
+
+PContainerEntry* PContainer::GetEntry( uint8_t nSlotId )
+{
+  if ( nSlotId >= mContContent->size() )
+    return NULL;
+
+  return mContContent->at( nSlotId );
+}
+
+PItem* PContainer::GetItem( uint8_t nSlotId )
+{
+  PContainerEntry* tEntry = this->GetEntry( nSlotId );
+  return ( tEntry ? tEntry->mItem : NULL );
+}
+
+uint8_t PContainer::RandomFill( uint8_t nItemCount, int nItemContainerDefIndex )
+{
+  PItem* nItem = NULL;
+  const PDefItems* nItemDef;
+  uint32_t nItemSeqId;
+  uint8_t CreatedCount = 0;
+
+  if ( !nItemCount )
+    nItemCount = mMaxSlots;
+  if ( !nItemCount )
+    nItemCount = CONTAINER_MAX_SIZE;
+
+  if ( nItemContainerDefIndex >= 0 )
+  {
+    int newItemIdx, newItemIndex;
+    uint8_t newItemQuality;
+
+    const PDefItemContainer* containerDef = GameDefs->ItemContainers()->GetDef( nItemContainerDefIndex );
+    if ( containerDef )
+    {
+      for ( uint8_t i = 0; i < nItemCount; ++i )
+      {
+        newItemIdx = containerDef->GetRandomItemIdx();
+        if ( newItemIdx >= 0 )
+        {
+          newItemIndex = containerDef->GetItemId( newItemIdx );
+          newItemQuality = ( uint8_t )( 255 & int( 255.0 * containerDef->GetQuality( newItemIdx ) ) );
+          if ( newItemIndex <= 0 ) // Item group
+          {
+            newItemIndex = GameDefs->Items()->GetRandomItemIdFromGroup( -newItemIndex );
+          }
+          nItem = new PItem( newItemIndex, 1, 255, newItemQuality, newItemQuality, newItemQuality, newItemQuality, 255 );
+          if ( nItem->GetItemID() )
+          {
+            if ( this->AddItem( nItem ) )
+            {
+              ++CreatedCount;
+            }
+            else
+            {
+              Console->Print( YELLOW, BLACK, "[Warning] Couldn't add item %d at pos %d", nItem->GetItemID(), i );
+              delete nItem;
+            }
+          }
+        }
+      }
+    }
+    else
+      Console->Print( YELLOW, BLACK, "[Warning] Container def not found: %d", nItemContainerDefIndex );
+  }
+  else
+  {
+    int NumItemsDefs = GameDefs->Items()->GetNumDefs();
+
+    for ( uint8_t i = 0; i < nItemCount; ++i )
+    {
+      nItemSeqId = GetRandom( NumItemsDefs, 1 );
+
+      if (( nItemDef = GameDefs->Items()->GetDefBySeqIndex( nItemSeqId ) ) )
+      {
+        nItem = new PItem( nItemDef->GetIndex(), 1, 255, 255, 255, 255, 255, 255 );
+        if ( nItem->GetItemID() )
+        {
+          if ( this->AddItem( nItem ) )
+          {
+            ++CreatedCount;
+          }
+          else
+          {
+            //Console->Print(GREEN, BLACK, "Couldn't add item % d at pos % d", nItem->GetItemID(), i);
+            delete nItem;
+          }
+        }
+      }
+      else
+        Console->Print( RED, BLACK, "[Warning] PContainer::RandomFill Couldn't find item for SEQ %d", nItemSeqId );
+    }
+  }
+  return CreatedCount;
+}
+
+void PContainer::Dump()
+{
+  PContainerEntry* tmpEntry;
+  PItem* tmpItem;
+  uint8_t i;
+  //uint8_t y, x;
+
+  for ( i = 0; i < mContContent->size(); ++i )
+  {
+    if (( tmpEntry = mContContent->at( i ) ) )
+    {
+      tmpItem = tmpEntry->mItem;
+      Console->Print( GREEN, BLACK, "%d: (%d,%d) (%d x %d) Item %d (InvID %d) %s %s", i, tmpEntry->mPosX, tmpEntry->mPosY, tmpItem->GetSizeX(), tmpItem->GetSizeY(), tmpItem->GetItemID(), tmpEntry->mInvID, tmpItem->GetName().c_str(), tmpEntry->mDirtyFlag ? "[*]" : "" );
+    }
+  }
+
+  if ( mDirtyFlag )
+    Console->Print( GREEN, BLACK, "Dirty" );
+  Console->Print( GREEN, BLACK, "------------------------------------" );
+}
+
+/* --- PContainerWithHoles class --- */
+
+
+/* --- PContainerAutoCompact --- */
+PContainerEntry* PContainerAutoCompact::RemoveEntry( uint8_t nSlotId )
+{
+  PContainerEntry* tEntry = NULL;
+
+  if ( nSlotId < mContContent->size() )
+  {
+    tEntry = mContContent->at( nSlotId );
+    mContContent->at( nSlotId ) = NULL;
+    if ( nSlotId == ( mContContent->size() - 1 ) )
+      mContContent->pop_back();
+    else
+      Compact( nSlotId );
+  }
+  return tEntry;
+}
+
+bool PContainerAutoCompact::GetFreeSlot( uint8_t* nSlotId ) // not optimal. A "first free from end" would be better at PContainer level
+{
+  bool Found = false;
+
+  for ( *nSlotId = 0; *nSlotId < mContContent->size(); ++*nSlotId )
+    if ( ! mContContent->at( *nSlotId ) )
+    {
+      Found = true;
+      break;
+    }
+  return ( Found || IsSlotAllowed( *nSlotId ) );
+}
+
+bool PContainerAutoCompact::MoveItem( uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId )
+{
+  srcSlotId = nCount = dstSlotId;
+  return false;
+}
+
+/* --- PContainer2D class --- */
+
+void PContainer2D::SetEntryPosXY( PContainerEntry* nEntry, uint8_t /*nSlotId*/, uint8_t nPosX, uint8_t nPosY )
+{
+  //nSlotId = nSlotId;
+  if (( nPosX >= INV_BACKPACK_COLS ) || ( nPosY == 255 ) )
+  {
+    nPosX = nPosY = 0;
+  }
+  nEntry->Set2DPos( nPosX, nPosY );
+  mDirtyFlag = mDirtyFlag || nEntry->mDirtyFlag;
+}
+
+/* --- PContainer2DWorkaround --- */
+/////
+PContainer2DWorkaround::PContainer2DWorkaround( uint8_t nMaxSlots ) : PContainerWithHoles( nMaxSlots )
+{
+  mNextFreeSlot = 0;
+  mMaxCols = 254;
+  mMaxRows = 254;
+  mRows = 0;
+  AddRow();
+}
+
+PContainer2DWorkaround::~PContainer2DWorkaround()
+{
+  for ( int i = 0; i < mRows; i++ )
+    delete mContSpace[i];
+}
+
+bool PContainer2DWorkaround::AddEntry( PContainerEntry* tEntry, uint8_t nSlotId )
+{
+  if ( IsSlotAllowed( nSlotId ) )
+  {
+    if ( FindValid2DPos( tEntry ) )
+    {
+      for ( uint8_t i = mContContent->size(); i <= nSlotId; ++i ) // Extend as needed
+        mContContent->push_back( static_cast<PContainerEntry *>(NULL) );
+      if ( mContContent->at( nSlotId ) )
+      {
+        Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::AddEntry: Target entry already %d in use !!!", nSlotId );
+        return false;
+      }
+      mContContent->at( nSlotId ) = tEntry;
+      mDirtyFlag = true;
+      //this->SetEntryPosXY(tEntry, nSlotId, tEntry->mPosX, tEntry->mPosY);
+      mDirtyFlag = mDirtyFlag || tEntry->mDirtyFlag;
+      SetUsed( tEntry );
+      return true;
+    }
+    else
+    {
+      Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::AddEntry: No 2D space left !!!", nSlotId, mMaxSlots );
+      return false;
+    }
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::AddEntry: Target entry %d not allowed (max = %d) !!!", nSlotId, mMaxSlots );
+    return false;
+  }
+
+}
+
+PContainerEntry* PContainer2DWorkaround::RemoveEntry( uint8_t nSlotId )
+{
+  PContainerEntry* tEntry = NULL;
+
+  if ( nSlotId < mContContent->size() )
+  {
+    tEntry = mContContent->at( nSlotId );
+    mContContent->at( nSlotId ) = NULL;
+    //Console->Print(YELLOW, BLACK, "Cleaning (%d,%d) (%d x %d)", tEntry->mPosX, tEntry->mPosY, tEntry->mItem->GetSizeX(), tEntry->mItem->GetSizeY());
+    SetUsed( tEntry, false );
+  }
+  return tEntry;
+}
+
+bool PContainer2DWorkaround::GetFreeSlot( uint8_t* nSlotId )
+{
+  if ( IsSlotAllowed( mNextFreeSlot ) )
+  {
+    *nSlotId = mNextFreeSlot++;
+    return true;
+  }
+  else
+    return false;
+}
+
+void PContainer2DWorkaround::SetEntryPosXY( PContainerEntry* nEntry, uint8_t /*nSlotId*/, uint8_t nPosX, uint8_t nPosY )
+{
+  //nSlotId = nSlotId;
+  if (( nPosX == 255 ) && ( nPosY == 255 ) )
+  {
+    nEntry->Set2DPos( 255, 255 );
+  }
+  else
+  {
+    if (( nPosX >= mMaxCols ) || ( nPosY >= mMaxRows ) )
+    {
+      nPosX = nPosY = 0;
+    }
+    nEntry->Set2DPos( nPosX, nPosY );
+
+    if ( !FindValid2DPos( nEntry ) )
+    {
+      nEntry->Set2DPos( 255, 255 );
+      Console->Print( RED, BLACK, "[Warning] PContainer2DWorkaround::SetEntryPosXY - Space position already used" );
+    }
+  }
+  mDirtyFlag = mDirtyFlag || nEntry->mDirtyFlag;
+}
+
+bool PContainer2DWorkaround::MoveItem( uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId )
+{
+  srcSlotId = nCount = dstSlotId;
+  return false;
+}
+
+void PContainer2DWorkaround::AddRow()
+{
+  if ( mRows + 1 < mMaxRows )
+  {
+    std::vector<bool>* NewRow = new std::vector<bool>( mMaxCols, 0 );
+    mContSpace.push_back( NewRow );
+    ++mRows;
+  }
+}
+
+bool PContainer2DWorkaround::Is2DFree( uint8_t PosX, uint8_t PosY, uint8_t SizeX, uint8_t SizeY )
+{
+  if (( PosX == 255 ) && ( PosY == 255 ) )
+  {
+    return true;
+  }
+  if ( !Is2DPosAllowed( PosX, PosY, SizeX, SizeY ) )
+    return false;
+
+  uint8_t h, v;
+  for ( v = 0; ( v < SizeY ) && ( PosY + v < mRows ) ; v++ ) // what is over existing rows is free
+  {
+    for ( h = 0; h < SizeX; h++ )
+    {
+      if ( PosX + h >= mMaxCols ) // what is over max col is not free
+        return false;
+
+      if (( *mContSpace[PosY+v] )[PosX+h] )
+        return false;
+    }
+  }
+  return ( PosY + SizeY <= mMaxRows );
+}
+
+void PContainer2DWorkaround::SetUsed( PContainerEntry* nEntry, bool Value )
+{
+  uint8_t PosX = nEntry->mPosX;;
+  uint8_t PosY = nEntry->mPosY;
+  uint8_t SizeX = nEntry->mItem->GetSizeX();
+  uint8_t SizeY = nEntry->mItem->GetSizeY();
+
+  if ( !Is2DPosAllowed( PosX, PosY, SizeX, SizeY ) )
+    return;
+
+  while ( PosY + SizeY > mRows ) // add new rows when needed
+    AddRow();
+
+  uint8_t h, v;
+  for ( v = 0; ( v < SizeY ) && ( PosY + v < mRows ) ; v++ )
+  {
+    for ( h = 0; ( h < SizeX ) && ( PosX + h < mMaxCols ); h++ )
+      ( *mContSpace[PosY+v] )[PosX+h] = Value;
+  }
+}
+
+bool PContainer2DWorkaround::FindValid2DPos( PContainerEntry* nEntry )
+{
+  bool Found = false;
+  uint8_t SizeX = nEntry->mItem->GetSizeX();
+  uint8_t SizeY = nEntry->mItem->GetSizeY();
+  uint8_t dPosX, dPosY;
+
+  if ( Is2DFree( nEntry->mPosX, nEntry->mPosY, SizeX, SizeY ) )
+    Found = true;
+  else
+  {
+    dPosX = nEntry->mPosX;
+    dPosY = nEntry->mPosY;
+    if ( !Is2DPosAllowed( dPosX, dPosY, SizeX, SizeY ) )
+    {
+      dPosX = dPosY = 0;
+      //Console->Print(YELLOW, BLACK, "Init pos RESET");
+    }
+
+    while ( !Found && Is2DPosAllowed( dPosX, dPosY, SizeX, SizeY ) )
+    {
+      //Console->Print(YELLOW, BLACK, "Searching line %d", dPosY);
+      for ( ; dPosX <= ( mMaxCols - SizeX ); ++dPosX )
+      {
+        if (( Found = Is2DFree( dPosX, dPosY, SizeX, SizeY ) ) )
+          break;
+      }
+      if ( Found )
+      {
+        nEntry->mPosX = dPosX;
+        nEntry->mPosY = dPosY;
+        nEntry->mDirtyFlag = true;
+        //Console->Print(YELLOW, BLACK, "Success: Found new space position : (%d,%d)", dPosX, dPosY);
+        break;
+      }
+      ++dPosY;
+      dPosX = 0;
+    }
+  }
+  return Found;
+}
+
+void PContainer2DWorkaround::Dump()
+{
+  PContainer::Dump();
+
+  std::string tmpS;
+  uint8_t y, x;
+  for ( y = 0 ; y < mRows; y++ )
+  {
+    tmpS = "";
+    for ( x = 0 ; x < mMaxCols; x++ )
+    {
+      tmpS += (( *mContSpace[y] )[x] ) ? "X" : ".";
+    }
+    Console->Print( "%s", tmpS.c_str() );
+  }
+  Console->Print( GREEN, BLACK, "------------------------------------" );
+}
+
+/* --- PContainerAutoFindFree --- */
+bool PContainerAutoFindFree::GetFreeSlot( uint8_t* nSlotId )
+{
+  bool Found = false;
+
+  for ( *nSlotId = 0; *nSlotId < mContContent->size(); ++*nSlotId )
+    if ( ! mContContent->at( *nSlotId ) )
+    {
+      Found = true;
+      break;
+    }
+
+  return ( Found || IsSlotAllowed( *nSlotId ) );
+}
+
+/* --- PContainerAutoCompactOnClose --- */
+bool PContainerAutoCompactOnClose::EndUse( uint32_t nExclusiveUseCharID )
+{
+  if ( nExclusiveUseCharID == mExclusiveUseCharID )
+  {
+    mExclusiveUseCharID = 0;
+    Compact();
+    return true;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[ERROR] PContainerAutoCompactOnClose::EndUse called with CharID %d when CharID %d had exclusive use", nExclusiveUseCharID, mExclusiveUseCharID );
+    return false;
+  }
+}
index 58bc238..9d86174 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <vector>\r
-#ifdef MYSQL_INC_DIR\r
-#include <mysql/mysql.h>\r
-#else\r
-#include <mysql.h>\r
-#endif\r
-\r
-#define CONTAINER_MAX_SIZE 254\r
-\r
-class PItem;\r
-\r
-class PContainerEntry {\r
-  friend class PContainer;\r
-  friend class PContainer2D;\r
-  friend class PMsgBuilder;\r
-  friend class PContainer2DWorkaround;\r
-\r
-private:\r
-    enum {\r
-      i_invid = 0,\r
-      i_charid,\r
-      i_invloc,\r
-      i_x,\r
-      i_y,\r
-      i_itemid,\r
-      //i_type,\r
-      i_flag,\r
-      i_qty,\r
-      i_sqty,\r
-      i_curdur,\r
-      i_dmg,\r
-      i_freq,\r
-      i_hand,\r
-      i_rng,\r
-      i_maxdur,\r
-      i_slots,\r
-      i_slt1,\r
-      i_slt2,\r
-      i_slt3,\r
-      i_slt4,\r
-      i_slt5,\r
-      i_atype,\r
-      i_conatin\r
-    };\r
-\r
-    PItem* mItem;\r
-    uint8_t  mPosX;\r
-    uint8_t  mPosY;\r
-    uint32_t mInvID;\r
-    bool mDirtyFlag;\r
-\r
-    PContainerEntry(PItem* nItem, uint8_t X, uint8_t Y, uint32_t nInvID = 0, bool SetDirty = true);\r
-    PContainerEntry(MYSQL_ROW row);\r
-\r
-    bool SQLSave(uint32_t CharID, uint32_t InvLoc);\r
-    bool SQLDelete();\r
-\r
-    inline void Set2DPos(uint8_t nPosX, uint8_t nPosY) { mDirtyFlag = mDirtyFlag || (mPosX != nPosX) || (mPosY != nPosY) ; mPosX = nPosX; mPosY = nPosY; }\r
-\r
-public:\r
-    ~PContainerEntry();\r
-\r
-    inline void Get2DPos(uint8_t* oPosX, uint8_t* oPosY) { *oPosX = mPosX; *oPosY = mPosY; }\r
-};\r
-\r
-\r
-\r
-class PContainer // Holes allowed, no autofind free slots\r
-{\r
-    protected:\r
-    uint8_t mMaxSlots;\r
-    std::vector< PContainerEntry* >* mContContent;\r
-    uint32_t mCharID;\r
-    uint32_t mInvLoc;\r
-    uint32_t mExclusiveUseCharID;\r
-    bool mDirtyFlag;\r
-\r
-    inline bool IsSlotAllowed(uint8_t nSlotId) { return ((nSlotId < CONTAINER_MAX_SIZE) && (!mMaxSlots || (nSlotId < mMaxSlots))); }\r
-    virtual bool AddEntry(PContainerEntry* NewEntry, uint8_t nSlotId = 0);\r
-    virtual PContainerEntry* RemoveEntry(uint8_t nSlotId);\r
-    virtual bool GetFreeSlot(uint8_t* nSlotId);\r
-        void Compact(uint8_t startSlotId = 0);\r
-\r
-  public:\r
-    PContainer(uint8_t nMaxSlots = 0);\r
-    virtual ~PContainer();\r
-\r
-    inline void SetInfo(uint32_t CharID, uint32_t InvLoc) { mCharID = CharID; mInvLoc = InvLoc; }\r
-    inline uint32_t GetOwnerId() { return mCharID; }\r
-    inline bool IsDirty() { return mDirtyFlag; }\r
-    inline void SetDirty() { mDirtyFlag = true; }\r
-    bool StartUse(uint32_t nExclusiveUseCharID = 0);\r
-    virtual bool EndUse(uint32_t nExclusiveUseCharID = 0);\r
-    bool SQLLoad();\r
-    bool SQLSave();\r
-    bool IsSlotFree(uint8_t nSlotId);\r
-    virtual bool AddItem(PItem* NewItem, uint32_t nInvID = 0, uint8_t nPosX = 0, uint8_t nPosY = 0, bool SetDirty = true);\r
-    virtual bool MoveItem(uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId);\r
-    bool MoveItem(uint8_t srcSlotId, uint8_t nCount, PContainer* dstContainer, uint8_t dstSlotId = 0, uint8_t nPosX = 0, uint8_t nPosY = 0);\r
-      virtual void SetEntryPosXY(PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX = 0, uint8_t nPosY = 0);\r
-\r
-    virtual uint8_t RandomFill(uint8_t nItemCount = 0, int nItemContainerDefIndex = -1);\r
-    PContainerEntry* GetEntry(uint8_t nSlotId);\r
-    std::vector< PContainerEntry* >* GetEntries();\r
-    PItem* GetItem(uint8_t nSlotId);\r
-    virtual void Dump();\r
-};\r
-\r
-\r
-class PContainerWithHoles : public PContainer // Holes allowed, no autofind free slots\r
-{\r
-  public:\r
-    PContainerWithHoles(uint8_t nMaxSlots = 0) : PContainer(nMaxSlots) {}\r
-    virtual ~PContainerWithHoles() {}\r
-};\r
-\r
-\r
-class PContainerAutoCompact : public PContainer // No holes allowed, automatic add to end slot (no control on insertion slot)\r
-{\r
-protected:\r
-    virtual PContainerEntry* RemoveEntry(uint8_t nSlotId);\r
-    virtual bool GetFreeSlot(uint8_t* nSlotId);\r
-\r
-public:\r
-    PContainerAutoCompact(uint8_t nMaxSlots = 0) : PContainer(nMaxSlots) {}\r
-    virtual ~PContainerAutoCompact() {}\r
-    virtual bool MoveItem(uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId);\r
-};\r
-\r
-\r
-class PContainer2D : public PContainerAutoCompact // + slotId not used, non-significant XY used (no XY check yet)\r
-{\r
-  public:\r
-    PContainer2D(uint8_t nMaxSlots = 0) : PContainerAutoCompact(nMaxSlots) {}\r
-    virtual ~PContainer2D() {}\r
-\r
-        virtual void SetEntryPosXY(PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX = 0, uint8_t nPosY = 0);\r
-};\r
-\r
-class PContainer2DWorkaround : public PContainerWithHoles // Holes allowed, autofind free slot (always increasing id)\r
-{\r
-private:\r
-    uint8_t mNextFreeSlot;\r
-    std::vector< std::vector<bool>* > mContSpace;\r
-    uint8_t mMaxCols;\r
-    uint8_t mMaxRows;\r
-    uint8_t mRows;\r
-\r
-    void AddRow();\r
-    inline bool Is2DPosAllowed(uint8_t PosX, uint8_t PosY, uint8_t SizeX, uint8_t SizeY)\r
-    {\r
-      return ((PosX < mMaxCols-SizeX+1) && (PosY < mMaxRows-SizeY+1));\r
-    }\r
-    bool Is2DFree(uint8_t PosX, uint8_t PosY, uint8_t SizeX, uint8_t SizeY);\r
-    bool FindValid2DPos(PContainerEntry* nEntry);\r
-\r
-protected:\r
-    bool AddEntry(PContainerEntry* NewEntry, uint8_t nSlotId = 0);\r
-    PContainerEntry* RemoveEntry(uint8_t nSlotId);\r
-    bool GetFreeSlot(uint8_t* nSlotId);\r
-\r
-  public:\r
-    PContainer2DWorkaround(uint8_t nMaxSlots = 0);\r
-    ~PContainer2DWorkaround();\r
-\r
-    bool MoveItem(uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId);\r
-\r
-    void Set2DPosMax(uint8_t MaxPosX, uint8_t MaxPosY = 254) { mMaxCols = MaxPosX; mMaxRows = MaxPosY; }\r
-    void SetEntryPosXY(PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX = 0, uint8_t nPosY = 0);\r
-    void SetUsed(PContainerEntry* nEntry, bool Value = true);\r
-    void Dump();\r
-};\r
-\r
-class PContainerAutoFindFree : public PContainerWithHoles // No holes kept after EndUse, automatic find first free slots (no control on insertion slot)\r
-{\r
-  protected:\r
-    virtual bool GetFreeSlot(uint8_t* nSlotId);\r
-\r
-  public:\r
-    PContainerAutoFindFree(uint8_t nMaxSlots = 0) : PContainerWithHoles(nMaxSlots) {}\r
-    virtual ~PContainerAutoFindFree() {}\r
-};\r
-\r
-class PContainerAutoCompactOnClose : public PContainerAutoFindFree // No holes kept after EndUse, automatic find first free slots (no control on insertion slot)\r
-{\r
-  public:\r
-    PContainerAutoCompactOnClose(uint8_t nMaxSlots = 0) : PContainerAutoFindFree(nMaxSlots) {}\r
-    virtual ~PContainerAutoCompactOnClose() {}\r
-\r
-    virtual bool EndUse(uint32_t nExclusiveUseCharID = 0);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <vector>
+#ifdef MYSQL_INC_DIR
+#include <mysql/mysql.h>
+#else
+#include <mysql.h>
+#endif
+
+#define CONTAINER_MAX_SIZE 254
+
+class PItem;
+
+class PContainerEntry {
+  friend class PContainer;
+  friend class PContainer2D;
+  friend class PMsgBuilder;
+  friend class PContainer2DWorkaround;
+
+private:
+    enum {
+      i_invid = 0,
+      i_charid,
+      i_invloc,
+      i_x,
+      i_y,
+      i_itemid,
+      //i_type,
+      i_flag,
+      i_qty,
+      i_sqty,
+      i_curdur,
+      i_dmg,
+      i_freq,
+      i_hand,
+      i_rng,
+      i_maxdur,
+      i_slots,
+      i_slt1,
+      i_slt2,
+      i_slt3,
+      i_slt4,
+      i_slt5,
+      i_atype,
+      i_conatin
+    };
+
+    PItem* mItem;
+    uint8_t  mPosX;
+    uint8_t  mPosY;
+    uint32_t mInvID;
+    bool mDirtyFlag;
+
+    PContainerEntry(PItem* nItem, uint8_t X, uint8_t Y, uint32_t nInvID = 0, bool SetDirty = true);
+    PContainerEntry(MYSQL_ROW row);
+
+    bool SQLSave(uint32_t CharID, uint32_t InvLoc);
+    bool SQLDelete();
+
+    inline void Set2DPos(uint8_t nPosX, uint8_t nPosY) { mDirtyFlag = mDirtyFlag || (mPosX != nPosX) || (mPosY != nPosY) ; mPosX = nPosX; mPosY = nPosY; }
+
+public:
+    ~PContainerEntry();
+
+    inline void Get2DPos(uint8_t* oPosX, uint8_t* oPosY) { *oPosX = mPosX; *oPosY = mPosY; }
+};
+
+
+
+class PContainer // Holes allowed, no autofind free slots
+{
+    protected:
+    uint8_t mMaxSlots;
+    std::vector< PContainerEntry* >* mContContent;
+    uint32_t mCharID;
+    uint32_t mInvLoc;
+    uint32_t mExclusiveUseCharID;
+    bool mDirtyFlag;
+
+    inline bool IsSlotAllowed(uint8_t nSlotId) { return ((nSlotId < CONTAINER_MAX_SIZE) && (!mMaxSlots || (nSlotId < mMaxSlots))); }
+    virtual bool AddEntry(PContainerEntry* NewEntry, uint8_t nSlotId = 0);
+    virtual PContainerEntry* RemoveEntry(uint8_t nSlotId);
+    virtual bool GetFreeSlot(uint8_t* nSlotId);
+        void Compact(uint8_t startSlotId = 0);
+
+  public:
+    PContainer(uint8_t nMaxSlots = 0);
+    virtual ~PContainer();
+
+    inline void SetInfo(uint32_t CharID, uint32_t InvLoc) { mCharID = CharID; mInvLoc = InvLoc; }
+    inline uint32_t GetOwnerId() { return mCharID; }
+    inline bool IsDirty() { return mDirtyFlag; }
+    inline void SetDirty() { mDirtyFlag = true; }
+    bool StartUse(uint32_t nExclusiveUseCharID = 0);
+    virtual bool EndUse(uint32_t nExclusiveUseCharID = 0);
+    bool SQLLoad();
+    bool SQLSave();
+    bool IsSlotFree(uint8_t nSlotId);
+    virtual bool AddItem(PItem* NewItem, uint32_t nInvID = 0, uint8_t nPosX = 0, uint8_t nPosY = 0, bool SetDirty = true);
+    virtual bool MoveItem(uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId);
+    bool MoveItem(uint8_t srcSlotId, uint8_t nCount, PContainer* dstContainer, uint8_t dstSlotId = 0, uint8_t nPosX = 0, uint8_t nPosY = 0);
+      virtual void SetEntryPosXY(PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX = 0, uint8_t nPosY = 0);
+
+    virtual uint8_t RandomFill(uint8_t nItemCount = 0, int nItemContainerDefIndex = -1);
+    PContainerEntry* GetEntry(uint8_t nSlotId);
+    std::vector< PContainerEntry* >* GetEntries();
+    PItem* GetItem(uint8_t nSlotId);
+    virtual void Dump();
+};
+
+
+class PContainerWithHoles : public PContainer // Holes allowed, no autofind free slots
+{
+  public:
+    PContainerWithHoles(uint8_t nMaxSlots = 0) : PContainer(nMaxSlots) {}
+    virtual ~PContainerWithHoles() {}
+};
+
+
+class PContainerAutoCompact : public PContainer // No holes allowed, automatic add to end slot (no control on insertion slot)
+{
+protected:
+    virtual PContainerEntry* RemoveEntry(uint8_t nSlotId);
+    virtual bool GetFreeSlot(uint8_t* nSlotId);
+
+public:
+    PContainerAutoCompact(uint8_t nMaxSlots = 0) : PContainer(nMaxSlots) {}
+    virtual ~PContainerAutoCompact() {}
+    virtual bool MoveItem(uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId);
+};
+
+
+class PContainer2D : public PContainerAutoCompact // + slotId not used, non-significant XY used (no XY check yet)
+{
+  public:
+    PContainer2D(uint8_t nMaxSlots = 0) : PContainerAutoCompact(nMaxSlots) {}
+    virtual ~PContainer2D() {}
+
+        virtual void SetEntryPosXY(PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX = 0, uint8_t nPosY = 0);
+};
+
+class PContainer2DWorkaround : public PContainerWithHoles // Holes allowed, autofind free slot (always increasing id)
+{
+private:
+    uint8_t mNextFreeSlot;
+    std::vector< std::vector<bool>* > mContSpace;
+    uint8_t mMaxCols;
+    uint8_t mMaxRows;
+    uint8_t mRows;
+
+    void AddRow();
+    inline bool Is2DPosAllowed(uint8_t PosX, uint8_t PosY, uint8_t SizeX, uint8_t SizeY)
+    {
+      return ((PosX < mMaxCols-SizeX+1) && (PosY < mMaxRows-SizeY+1));
+    }
+    bool Is2DFree(uint8_t PosX, uint8_t PosY, uint8_t SizeX, uint8_t SizeY);
+    bool FindValid2DPos(PContainerEntry* nEntry);
+
+protected:
+    bool AddEntry(PContainerEntry* NewEntry, uint8_t nSlotId = 0);
+    PContainerEntry* RemoveEntry(uint8_t nSlotId);
+    bool GetFreeSlot(uint8_t* nSlotId);
+
+  public:
+    PContainer2DWorkaround(uint8_t nMaxSlots = 0);
+    ~PContainer2DWorkaround();
+
+    bool MoveItem(uint8_t srcSlotId, uint8_t nCount, uint8_t dstSlotId);
+
+    void Set2DPosMax(uint8_t MaxPosX, uint8_t MaxPosY = 254) { mMaxCols = MaxPosX; mMaxRows = MaxPosY; }
+    void SetEntryPosXY(PContainerEntry* nEntry, uint8_t nSlotId, uint8_t nPosX = 0, uint8_t nPosY = 0);
+    void SetUsed(PContainerEntry* nEntry, bool Value = true);
+    void Dump();
+};
+
+class PContainerAutoFindFree : public PContainerWithHoles // No holes kept after EndUse, automatic find first free slots (no control on insertion slot)
+{
+  protected:
+    virtual bool GetFreeSlot(uint8_t* nSlotId);
+
+  public:
+    PContainerAutoFindFree(uint8_t nMaxSlots = 0) : PContainerWithHoles(nMaxSlots) {}
+    virtual ~PContainerAutoFindFree() {}
+};
+
+class PContainerAutoCompactOnClose : public PContainerAutoFindFree // No holes kept after EndUse, automatic find first free slots (no control on insertion slot)
+{
+  public:
+    PContainerAutoCompactOnClose(uint8_t nMaxSlots = 0) : PContainerAutoFindFree(nMaxSlots) {}
+    virtual ~PContainerAutoCompactOnClose() {}
+
+    virtual bool EndUse(uint32_t nExclusiveUseCharID = 0);
+};
index fa36ad3..9a9adae 100644 (file)
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PUdpMsgDecoder::Init(PMessage *nMessage, PClient *nClient)\r
-{\r
-    mDecodeData.mMessage = nMessage;\r
-    mDecodeData.mClient = nClient;\r
-    mDecodeData.mState = (nMessage && nClient) ? DECODE_MORE : DECODE_UNDEF;\r
-    mDecodeData.mUnknownType = 0;\r
-    mDecodeData.mHandling0x13Sub = false;\r
-    mDecodeData.Sub0x13Start = mDecodeData.Sub0x13StartNext = 0;\r
-    mPacketName.erase();\r
-    mDecodeData.mName.str(mPacketName);\r
-    mDecodeData.mErrorDetail.erase();\r
-    mDecodeData.mTraceKnownMsg = false;\r
-    mDecodeData.mTraceUnknownMsg = false;\r
-    mDecodeData.mTraceDump = false;\r
-    if (mCurrentAnalyser)\r
-    {\r
-        delete mCurrentAnalyser;\r
-        mCurrentAnalyser = nullptr;\r
-    }\r
-}\r
-\r
-PUdpMsgDecoder::PUdpMsgDecoder()\r
-{\r
-  mCurrentAnalyser = nullptr;\r
-  Reset();\r
-}\r
-\r
-PUdpMsgDecoder::PUdpMsgDecoder(PMessage *nMessage, PClient *nClient)\r
-{\r
-  mCurrentAnalyser = nullptr;\r
-  Init(nMessage, nClient);\r
-}\r
-\r
-PUdpMsgDecoder::~PUdpMsgDecoder()\r
-{\r
-  if (mCurrentAnalyser)\r
-  {\r
-    delete mCurrentAnalyser;\r
-  }\r
-}\r
-\r
-bool PUdpMsgDecoder::Analyse()\r
-{\r
-  PUdpMsgAnalyser* nextAnalyser;\r
-\r
-  if ((mDecodeData.mState & DECODE_MORE) || mDecodeData.mHandling0x13Sub)\r
-  {\r
-    if (mCurrentAnalyser)\r
-    {\r
-      delete mCurrentAnalyser;\r
-      mCurrentAnalyser = nullptr;\r
-    }\r
-    if (mDecodeData.mHandling0x13Sub)\r
-    {\r
-      mPacketName.erase();\r
-      mDecodeData.mName.str(mPacketName);\r
-      mCurrentAnalyser = new PUdp0x13(&mDecodeData);\r
-      mDecodeData.mState = DECODE_MORE;\r
-    }\r
-    else\r
-    {\r
-      mCurrentAnalyser = new PUdpMsgAnalyser(&mDecodeData);\r
-    }\r
-\r
-    while (mDecodeData.mState & DECODE_MORE)\r
-    {\r
-      nextAnalyser = mCurrentAnalyser->Analyse();\r
-      if (mCurrentAnalyser != nextAnalyser)\r
-      {\r
-        delete mCurrentAnalyser;\r
-        mCurrentAnalyser = nextAnalyser;\r
-      }\r
-    }\r
-  }\r
-  return (!(mDecodeData.mState & (DECODE_MORE | DECODE_ERROR | DECODE_UNKNOWN)));\r
-}\r
-\r
-bool PUdpMsgDecoder::Analyse(PMessage *nMessage, PClient *nClient)\r
-{\r
-  Init(nMessage, nClient);\r
-  return Analyse();\r
-}\r
-\r
-void PUdpMsgDecoder::Init(PMessage *nMessage, PClient *nClient, PGameState *nClientState)\r
-{\r
-    mDecodeData.mClientState = nClientState;\r
-    Init(nMessage, nClient);\r
-}\r
-\r
-uint8_t PUdpMsgDecoder::GetState()\r
-{\r
-    return mDecodeData.mState;\r
-}\r
-\r
-bool PUdpMsgDecoder::IsError()\r
-{\r
-    return (mDecodeData.mState & DECODE_ERROR);\r
-}\r
-\r
-bool PUdpMsgDecoder::IsKnown()\r
-{\r
-    return (!(mDecodeData.mState & DECODE_UNKNOWN));\r
-}\r
-\r
-bool PUdpMsgDecoder::MoreSubMsg()\r
-{\r
-    return mDecodeData.mHandling0x13Sub;\r
-}\r
-\r
-bool PUdpMsgDecoder::IsActionReady()\r
-{\r
-    return (mDecodeData.mState & DECODE_ACTION_READY);\r
-}\r
-\r
-bool PUdpMsgDecoder::IsActionDone()\r
-{\r
-    return (mDecodeData.mState & DECODE_ACTION_DONE);\r
-}\r
-\r
-bool PUdpMsgDecoder::IsTraceKnownMsg()\r
-{\r
-    return mDecodeData.mTraceKnownMsg;\r
-}\r
-\r
-bool PUdpMsgDecoder::IsTraceUnknownMsg()\r
-{\r
-    return mDecodeData.mTraceUnknownMsg;\r
-}\r
-\r
-bool PUdpMsgDecoder::IsTraceDump()\r
-{\r
-    return mDecodeData.mTraceDump;\r
-}\r
-\r
-void PUdpMsgDecoder::DumpMsg()\r
-{\r
-    if (mDecodeData.mMessage)\r
-        mDecodeData.mMessage->Dump();\r
-}\r
-\r
-std::string const &PUdpMsgDecoder::GetName()\r
-{\r
-    return (mTmpName = mDecodeData.mName.str());\r
-}\r
-\r
-std::string const &PUdpMsgDecoder::GetError()\r
-{\r
-    return mDecodeData.mErrorDetail;\r
-}\r
-\r
-bool PUdpMsgDecoder::DoAction()\r
-{\r
-  if (mDecodeData.mState & DECODE_ACTION_READY)\r
-  {\r
-    return mCurrentAnalyser->DoAction();\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-void PUdpMsgDecoder::Reset()\r
-{\r
-    Init(nullptr, nullptr);\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PUdpMsgDecoder::Init(PMessage *nMessage, PClient *nClient)
+{
+    mDecodeData.mMessage = nMessage;
+    mDecodeData.mClient = nClient;
+    mDecodeData.mState = (nMessage && nClient) ? DECODE_MORE : DECODE_UNDEF;
+    mDecodeData.mUnknownType = 0;
+    mDecodeData.mHandling0x13Sub = false;
+    mDecodeData.Sub0x13Start = mDecodeData.Sub0x13StartNext = 0;
+    mPacketName.erase();
+    mDecodeData.mName.str(mPacketName);
+    mDecodeData.mErrorDetail.erase();
+    mDecodeData.mTraceKnownMsg = false;
+    mDecodeData.mTraceUnknownMsg = false;
+    mDecodeData.mTraceDump = false;
+    if (mCurrentAnalyser)
+    {
+        delete mCurrentAnalyser;
+        mCurrentAnalyser = nullptr;
+    }
+}
+
+PUdpMsgDecoder::PUdpMsgDecoder()
+{
+  mCurrentAnalyser = nullptr;
+  Reset();
+}
+
+PUdpMsgDecoder::PUdpMsgDecoder(PMessage *nMessage, PClient *nClient)
+{
+  mCurrentAnalyser = nullptr;
+  Init(nMessage, nClient);
+}
+
+PUdpMsgDecoder::~PUdpMsgDecoder()
+{
+  if (mCurrentAnalyser)
+  {
+    delete mCurrentAnalyser;
+  }
+}
+
+bool PUdpMsgDecoder::Analyse()
+{
+  PUdpMsgAnalyser* nextAnalyser;
+
+  if ((mDecodeData.mState & DECODE_MORE) || mDecodeData.mHandling0x13Sub)
+  {
+    if (mCurrentAnalyser)
+    {
+      delete mCurrentAnalyser;
+      mCurrentAnalyser = nullptr;
+    }
+    if (mDecodeData.mHandling0x13Sub)
+    {
+      mPacketName.erase();
+      mDecodeData.mName.str(mPacketName);
+      mCurrentAnalyser = new PUdp0x13(&mDecodeData);
+      mDecodeData.mState = DECODE_MORE;
+    }
+    else
+    {
+      mCurrentAnalyser = new PUdpMsgAnalyser(&mDecodeData);
+    }
+
+    while (mDecodeData.mState & DECODE_MORE)
+    {
+      nextAnalyser = mCurrentAnalyser->Analyse();
+      if (mCurrentAnalyser != nextAnalyser)
+      {
+        delete mCurrentAnalyser;
+        mCurrentAnalyser = nextAnalyser;
+      }
+    }
+  }
+  return (!(mDecodeData.mState & (DECODE_MORE | DECODE_ERROR | DECODE_UNKNOWN)));
+}
+
+bool PUdpMsgDecoder::Analyse(PMessage *nMessage, PClient *nClient)
+{
+  Init(nMessage, nClient);
+  return Analyse();
+}
+
+void PUdpMsgDecoder::Init(PMessage *nMessage, PClient *nClient, PGameState *nClientState)
+{
+    mDecodeData.mClientState = nClientState;
+    Init(nMessage, nClient);
+}
+
+uint8_t PUdpMsgDecoder::GetState()
+{
+    return mDecodeData.mState;
+}
+
+bool PUdpMsgDecoder::IsError()
+{
+    return (mDecodeData.mState & DECODE_ERROR);
+}
+
+bool PUdpMsgDecoder::IsKnown()
+{
+    return (!(mDecodeData.mState & DECODE_UNKNOWN));
+}
+
+bool PUdpMsgDecoder::MoreSubMsg()
+{
+    return mDecodeData.mHandling0x13Sub;
+}
+
+bool PUdpMsgDecoder::IsActionReady()
+{
+    return (mDecodeData.mState & DECODE_ACTION_READY);
+}
+
+bool PUdpMsgDecoder::IsActionDone()
+{
+    return (mDecodeData.mState & DECODE_ACTION_DONE);
+}
+
+bool PUdpMsgDecoder::IsTraceKnownMsg()
+{
+    return mDecodeData.mTraceKnownMsg;
+}
+
+bool PUdpMsgDecoder::IsTraceUnknownMsg()
+{
+    return mDecodeData.mTraceUnknownMsg;
+}
+
+bool PUdpMsgDecoder::IsTraceDump()
+{
+    return mDecodeData.mTraceDump;
+}
+
+void PUdpMsgDecoder::DumpMsg()
+{
+    if (mDecodeData.mMessage)
+        mDecodeData.mMessage->Dump();
+}
+
+std::string const &PUdpMsgDecoder::GetName()
+{
+    return (mTmpName = mDecodeData.mName.str());
+}
+
+std::string const &PUdpMsgDecoder::GetError()
+{
+    return mDecodeData.mErrorDetail;
+}
+
+bool PUdpMsgDecoder::DoAction()
+{
+  if (mDecodeData.mState & DECODE_ACTION_READY)
+  {
+    return mCurrentAnalyser->DoAction();
+  }
+  else
+  {
+    return false;
+  }
+}
+
+void PUdpMsgDecoder::Reset()
+{
+    Init(nullptr, nullptr);
+}
index edf2a6b..efa5d76 100644 (file)
@@ -1,73 +1,73 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <sstream>\r
-#include <string>\r
-\r
-struct PGameState;\r
-class PClient;\r
-class PMessage;\r
-class PUdpMsgAnalyser;\r
-\r
-#define DECODE_UNDEF 0\r
-#define DECODE_ERROR 1 // one error occured on the current decoding step\r
-#define DECODE_UNKNOWN 2 // the current decoded (sub)message is unkown\r
-#define DECODE_MORE 4 // more decoding needed for the (sub)message\r
-#define DECODE_FINISHED 8 // decoding if finished for the whole message\r
-#define DECODE_ACTION_READY 16 // an action is ready to be done\r
-#define DECODE_ACTION_DONE 32 // the action triggered hasn't to be triggered again\r
-#define DECODE_ACTION_IGNORED 64 // the action wasn't performed for some (good) reason (to combine or not with DONE)\r
-#define DECODE_ACTION_FAILED 128 // the action failed totally or partially (to combine or not with DONE)\r
-\r
-struct PMsgDecodeData {\r
-    PMessage *mMessage;\r
-    PClient *mClient;\r
-    uint8_t mState;\r
-    uint8_t mUnknownType;\r
-    bool mHandling0x13Sub;\r
-    uint16_t Sub0x13Start;\r
-    uint16_t Sub0x13StartNext;\r
-    std::stringstream mName;\r
-    std::string mErrorDetail;\r
-    bool mTraceKnownMsg;\r
-    bool mTraceUnknownMsg;\r
-    bool mTraceDump;\r
-    PGameState *mClientState; // Temporary until State is put back in Client object\r
-};\r
-\r
-// UDP Message decoder\r
-// boolean methods return true if successful\r
-\r
-class PUdpMsgDecoder {\r
-private:\r
-    PMsgDecodeData mDecodeData;\r
-    PUdpMsgAnalyser *mCurrentAnalyser;\r
-    std::string mPacketName;\r
-    std::string mTmpName;\r
-\r
-    void Init(PMessage *nMessage, PClient *nClient);\r
-\r
-public:\r
-    PUdpMsgDecoder();\r
-    PUdpMsgDecoder(PMessage *nMessage, PClient *nClient);\r
-    ~PUdpMsgDecoder();\r
-\r
-    bool Analyse();\r
-    bool Analyse(PMessage *nMessage, PClient *nClient); // Can be used on non initialized or already used object\r
-    // Temporary form until State is put back in Client object\r
-    void Init(PMessage *nMessage, PClient *nClient, PGameState *nClientState);\r
-    uint8_t GetState();\r
-    bool IsError();\r
-    bool IsKnown();\r
-    bool MoreSubMsg();\r
-    bool IsActionReady();\r
-    bool IsActionDone();\r
-    bool IsTraceKnownMsg();\r
-    bool IsTraceUnknownMsg();\r
-    bool IsTraceDump();\r
-    void DumpMsg();\r
-    std::string const &GetName();\r
-    std::string const &GetError();\r
-    bool DoAction();\r
-    void Reset();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <sstream>
+#include <string>
+
+struct PGameState;
+class PClient;
+class PMessage;
+class PUdpMsgAnalyser;
+
+#define DECODE_UNDEF 0
+#define DECODE_ERROR 1 // one error occured on the current decoding step
+#define DECODE_UNKNOWN 2 // the current decoded (sub)message is unkown
+#define DECODE_MORE 4 // more decoding needed for the (sub)message
+#define DECODE_FINISHED 8 // decoding if finished for the whole message
+#define DECODE_ACTION_READY 16 // an action is ready to be done
+#define DECODE_ACTION_DONE 32 // the action triggered hasn't to be triggered again
+#define DECODE_ACTION_IGNORED 64 // the action wasn't performed for some (good) reason (to combine or not with DONE)
+#define DECODE_ACTION_FAILED 128 // the action failed totally or partially (to combine or not with DONE)
+
+struct PMsgDecodeData {
+    PMessage *mMessage;
+    PClient *mClient;
+    uint8_t mState;
+    uint8_t mUnknownType;
+    bool mHandling0x13Sub;
+    uint16_t Sub0x13Start;
+    uint16_t Sub0x13StartNext;
+    std::stringstream mName;
+    std::string mErrorDetail;
+    bool mTraceKnownMsg;
+    bool mTraceUnknownMsg;
+    bool mTraceDump;
+    PGameState *mClientState; // Temporary until State is put back in Client object
+};
+
+// UDP Message decoder
+// boolean methods return true if successful
+
+class PUdpMsgDecoder {
+private:
+    PMsgDecodeData mDecodeData;
+    PUdpMsgAnalyser *mCurrentAnalyser;
+    std::string mPacketName;
+    std::string mTmpName;
+
+    void Init(PMessage *nMessage, PClient *nClient);
+
+public:
+    PUdpMsgDecoder();
+    PUdpMsgDecoder(PMessage *nMessage, PClient *nClient);
+    ~PUdpMsgDecoder();
+
+    bool Analyse();
+    bool Analyse(PMessage *nMessage, PClient *nClient); // Can be used on non initialized or already used object
+    // Temporary form until State is put back in Client object
+    void Init(PMessage *nMessage, PClient *nClient, PGameState *nClientState);
+    uint8_t GetState();
+    bool IsError();
+    bool IsKnown();
+    bool MoreSubMsg();
+    bool IsActionReady();
+    bool IsActionDone();
+    bool IsTraceKnownMsg();
+    bool IsTraceUnknownMsg();
+    bool IsTraceDump();
+    void DumpMsg();
+    std::string const &GetName();
+    std::string const &GetError();
+    bool DoAction();
+    void Reset();
+};
index ab5424a..e92ec1d 100644 (file)
@@ -1,24 +1,24 @@
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-\r
-PUdp0x08::PUdp0x08(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  nDecodeData->mName << "/0x08";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdp0x08::Analyse()\r
-{\r
-    mDecodeData->mName << "=Client crash";\r
-    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-\r
-    return this;\r
-}\r
-\r
-bool PUdp0x08::DoAction()\r
-{\r
-    // Client crashed, close connection from our side\r
-    GameServer->ClientDisconnected(mDecodeData->mClient);\r
-    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-\r
-    return true;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+
+PUdp0x08::PUdp0x08(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  nDecodeData->mName << "/0x08";
+}
+
+PUdpMsgAnalyser* PUdp0x08::Analyse()
+{
+    mDecodeData->mName << "=Client crash";
+    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+
+    return this;
+}
+
+bool PUdp0x08::DoAction()
+{
+    // Client crashed, close connection from our side
+    GameServer->ClientDisconnected(mDecodeData->mClient);
+    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+
+    return true;
+}
index 81b9443..4d1c3f4 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdp0x08 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdp0x08(PMsgDecodeData *nDecodeData);\r
-    //~PUdp0x08();\r
-    PUdpMsgAnalyser* Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdp0x08 : public PUdpMsgAnalyser {
+public:
+    PUdp0x08(PMsgDecodeData *nDecodeData);
+    //~PUdp0x08();
+    PUdpMsgAnalyser* Analyse();
+    bool DoAction();
+};
index 7d93ffc..79c4768 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdp0x13 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdp0x13(PMsgDecodeData *nDecodeData);\r
-    //~PUdp0x13();\r
-    PUdpMsgAnalyser* Analyse();\r
-    //bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdp0x13 : public PUdpMsgAnalyser {
+public:
+    PUdp0x13(PMsgDecodeData *nDecodeData);
+    //~PUdp0x13();
+    PUdpMsgAnalyser* Analyse();
+    //bool DoAction();
+};
index d51857c..d9e6fda 100644 (file)
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdp0x1f ****/\r
-\r
-PUdp0x1f::PUdp0x1f( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x1f";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdp0x1f::Analyse()\r
-{\r
-  PUdpMsgAnalyser* nextAnalyser = NULL;\r
-  mDecodeData->mState = DECODE_MORE;\r
-  uint8_t MsgType = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 7 );\r
-  uint8_t MsgSubType = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 8 );\r
-\r
-  switch ( MsgType )\r
-  {\r
-    case 0x00:\r
-    {\r
-      nextAnalyser = new PUdpHeldItemBasicAction( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x01:\r
-    {\r
-      nextAnalyser = new PUdpHeldItemAimedAction( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x02:\r
-    {\r
-      nextAnalyser = new PUdpCharJump( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x17:\r
-    {\r
-      nextAnalyser = new PUdpUseObject( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x19: // NPC Dialog closed\r
-    {\r
-      nextAnalyser = new PUdpNPCDialogClose( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x1a: // NPC Dialog action/reply\r
-    {\r
-      nextAnalyser = new PUdpNPCDialogAction( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x1b:\r
-    {\r
-      nextAnalyser = new PUdpChatLocal( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x1e:  // item move QB<>INV<>GND\r
-    {\r
-      nextAnalyser = new PUdpItemMove( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x1f: // Slot use\r
-    {\r
-      nextAnalyser = new PUdpItemSlotUse( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x20: // Use item for hacking, launcher, "launcher" spell\r
-    {\r
-      nextAnalyser = new PUdpHeldItemLaunchingAction( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x22:\r
-    {\r
-      nextAnalyser = new PUdpCharExitChair( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x25:\r
-    {\r
-      mDecodeData->mName << "/0x25";\r
-      switch ( MsgSubType )\r
-      {\r
-        case 0x04: // Hack announcement?\r
-        {\r
-          nextAnalyser = new PUdpSubskillInc( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x0c: // addons activation\r
-        {\r
-          nextAnalyser = new PUdpItemAddonActivation( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x14: // Hack announcement?\r
-        {\r
-          nextAnalyser = new PUdpItemMoveBP( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x16: // ???? confirm reload anim start ???\r
-        {\r
-          mDecodeData->mUnknownType = MsgSubType;\r
-          mDecodeData->mTraceUnknownMsg = true;\r
-          break;\r
-        }\r
-        case 0x17: // Item drop on item\r
-        {\r
-          nextAnalyser = new PUdpItemDropOnItem( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x18:\r
-        {\r
-          mDecodeData->mName << "/0x18";\r
-          switch ( mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 9 ) )\r
-          {\r
-            case 0x01: // Use inventory item\r
-            {\r
-              nextAnalyser = new PUdpItemUse( mDecodeData );\r
-              break;\r
-            }\r
-            case 0x0e: // Request manual reload\r
-            {\r
-              nextAnalyser = new PUdpItemManualReload( mDecodeData );\r
-              break;\r
-            }\r
-            default:\r
-            {\r
-              mDecodeData->mUnknownType = MsgSubType;\r
-              mDecodeData->mTraceUnknownMsg = true;\r
-              break;\r
-            }\r
-          }\r
-          break;\r
-        }\r
-\r
-        case 0x1d: // ? before Packet0: 0b 03 01 00 1f 00 00 25 1d 00 00 01\r
-        case 0x1e: // ? before Packet0: 0d 03 02 00 1f 00 00 25 1e ff ff ff ff 00\r
-        default:\r
-        {\r
-          mDecodeData->mUnknownType = MsgSubType;\r
-          mDecodeData->mTraceUnknownMsg = true;\r
-          break;\r
-        }\r
-      }\r
-      break;\r
-    }\r
-    case 0x27:\r
-    {\r
-      nextAnalyser = new PUdpCloseItemContainer( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x29:\r
-    {\r
-      nextAnalyser = new PUdpHackSuccess( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x2c:\r
-    {\r
-      nextAnalyser = new PUdpHackFail( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x2e:\r
-    {\r
-      nextAnalyser = new PUdpOutfitter( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x2f:\r
-    {\r
-      nextAnalyser = new PUdpDeathRespawn( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x33:\r
-    {\r
-      nextAnalyser = new PUdpChatListAdd( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x38:\r
-    {\r
-      nextAnalyser = new PUdpAppartmentAccess( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x39:\r
-    {\r
-      nextAnalyser = new PUdpChatListRemove( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x3b:\r
-    {\r
-      nextAnalyser = new PUdpChatGlobal( mDecodeData );\r
-      break;\r
-    }\r
-    case 0x3d:\r
-    {\r
-      mDecodeData->mName << "/0x3d";\r
-      switch ( MsgSubType ) // In fact MsgSubType is U32, but only lower byte is used\r
-      {\r
-        case 0x02:\r
-        {\r
-          nextAnalyser = new PUdpAddGenrepToList( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x03:\r
-        {\r
-          nextAnalyser = new PUdpAptGRZoning( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x04:\r
-        {\r
-          nextAnalyser = new PUdpGenrepZoning( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x09:\r
-        {\r
-          nextAnalyser = new PUdpPopupResponse( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x0a:\r
-        {\r
-          nextAnalyser = new PUdpAptLocInfo( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x0f:\r
-        {\r
-          nextAnalyser = new PUdpVhcUse( mDecodeData );\r
-          break;\r
-        }\r
-        case 0x10:\r
-        {\r
-          nextAnalyser = new PUdpKillSelf( mDecodeData );\r
-          break;\r
-        }\r
-        default:\r
-        {\r
-          mDecodeData->mUnknownType = MsgSubType;\r
-          break;\r
-        }\r
-      }\r
-      break;\r
-    }\r
-    case 0x3e:\r
-    {\r
-        nextAnalyser = new PUdpPvPTrade( mDecodeData );\r
-        break;\r
-    }\r
-    case 0x4c:\r
-    {\r
-      nextAnalyser = new PUdpChatChannels( mDecodeData );\r
-      break;\r
-    }\r
-    default:\r
-    {\r
-      mDecodeData->mUnknownType = MsgType;\r
-      mDecodeData->mTraceUnknownMsg = true;\r
-      break;\r
-    }\r
-  }\r
-\r
-  if ( ! nextAnalyser )\r
-  {\r
-    nextAnalyser = new PUdpMsgUnknown( mDecodeData );\r
-  }\r
-\r
-  return nextAnalyser;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdp0x1f ****/
+
+PUdp0x1f::PUdp0x1f( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x1f";
+}
+
+PUdpMsgAnalyser* PUdp0x1f::Analyse()
+{
+  PUdpMsgAnalyser* nextAnalyser = NULL;
+  mDecodeData->mState = DECODE_MORE;
+  uint8_t MsgType = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 7 );
+  uint8_t MsgSubType = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 8 );
+
+  switch ( MsgType )
+  {
+    case 0x00:
+    {
+      nextAnalyser = new PUdpHeldItemBasicAction( mDecodeData );
+      break;
+    }
+    case 0x01:
+    {
+      nextAnalyser = new PUdpHeldItemAimedAction( mDecodeData );
+      break;
+    }
+    case 0x02:
+    {
+      nextAnalyser = new PUdpCharJump( mDecodeData );
+      break;
+    }
+    case 0x17:
+    {
+      nextAnalyser = new PUdpUseObject( mDecodeData );
+      break;
+    }
+    case 0x19: // NPC Dialog closed
+    {
+      nextAnalyser = new PUdpNPCDialogClose( mDecodeData );
+      break;
+    }
+    case 0x1a: // NPC Dialog action/reply
+    {
+      nextAnalyser = new PUdpNPCDialogAction( mDecodeData );
+      break;
+    }
+    case 0x1b:
+    {
+      nextAnalyser = new PUdpChatLocal( mDecodeData );
+      break;
+    }
+    case 0x1e:  // item move QB<>INV<>GND
+    {
+      nextAnalyser = new PUdpItemMove( mDecodeData );
+      break;
+    }
+    case 0x1f: // Slot use
+    {
+      nextAnalyser = new PUdpItemSlotUse( mDecodeData );
+      break;
+    }
+    case 0x20: // Use item for hacking, launcher, "launcher" spell
+    {
+      nextAnalyser = new PUdpHeldItemLaunchingAction( mDecodeData );
+      break;
+    }
+    case 0x22:
+    {
+      nextAnalyser = new PUdpCharExitChair( mDecodeData );
+      break;
+    }
+    case 0x25:
+    {
+      mDecodeData->mName << "/0x25";
+      switch ( MsgSubType )
+      {
+        case 0x04: // Hack announcement?
+        {
+          nextAnalyser = new PUdpSubskillInc( mDecodeData );
+          break;
+        }
+        case 0x0c: // addons activation
+        {
+          nextAnalyser = new PUdpItemAddonActivation( mDecodeData );
+          break;
+        }
+        case 0x14: // Hack announcement?
+        {
+          nextAnalyser = new PUdpItemMoveBP( mDecodeData );
+          break;
+        }
+        case 0x16: // ???? confirm reload anim start ???
+        {
+          mDecodeData->mUnknownType = MsgSubType;
+          mDecodeData->mTraceUnknownMsg = true;
+          break;
+        }
+        case 0x17: // Item drop on item
+        {
+          nextAnalyser = new PUdpItemDropOnItem( mDecodeData );
+          break;
+        }
+        case 0x18:
+        {
+          mDecodeData->mName << "/0x18";
+          switch ( mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 9 ) )
+          {
+            case 0x01: // Use inventory item
+            {
+              nextAnalyser = new PUdpItemUse( mDecodeData );
+              break;
+            }
+            case 0x0e: // Request manual reload
+            {
+              nextAnalyser = new PUdpItemManualReload( mDecodeData );
+              break;
+            }
+            default:
+            {
+              mDecodeData->mUnknownType = MsgSubType;
+              mDecodeData->mTraceUnknownMsg = true;
+              break;
+            }
+          }
+          break;
+        }
+
+        case 0x1d: // ? before Packet0: 0b 03 01 00 1f 00 00 25 1d 00 00 01
+        case 0x1e: // ? before Packet0: 0d 03 02 00 1f 00 00 25 1e ff ff ff ff 00
+        default:
+        {
+          mDecodeData->mUnknownType = MsgSubType;
+          mDecodeData->mTraceUnknownMsg = true;
+          break;
+        }
+      }
+      break;
+    }
+    case 0x27:
+    {
+      nextAnalyser = new PUdpCloseItemContainer( mDecodeData );
+      break;
+    }
+    case 0x29:
+    {
+      nextAnalyser = new PUdpHackSuccess( mDecodeData );
+      break;
+    }
+    case 0x2c:
+    {
+      nextAnalyser = new PUdpHackFail( mDecodeData );
+      break;
+    }
+    case 0x2e:
+    {
+      nextAnalyser = new PUdpOutfitter( mDecodeData );
+      break;
+    }
+    case 0x2f:
+    {
+      nextAnalyser = new PUdpDeathRespawn( mDecodeData );
+      break;
+    }
+    case 0x33:
+    {
+      nextAnalyser = new PUdpChatListAdd( mDecodeData );
+      break;
+    }
+    case 0x38:
+    {
+      nextAnalyser = new PUdpAppartmentAccess( mDecodeData );
+      break;
+    }
+    case 0x39:
+    {
+      nextAnalyser = new PUdpChatListRemove( mDecodeData );
+      break;
+    }
+    case 0x3b:
+    {
+      nextAnalyser = new PUdpChatGlobal( mDecodeData );
+      break;
+    }
+    case 0x3d:
+    {
+      mDecodeData->mName << "/0x3d";
+      switch ( MsgSubType ) // In fact MsgSubType is U32, but only lower byte is used
+      {
+        case 0x02:
+        {
+          nextAnalyser = new PUdpAddGenrepToList( mDecodeData );
+          break;
+        }
+        case 0x03:
+        {
+          nextAnalyser = new PUdpAptGRZoning( mDecodeData );
+          break;
+        }
+        case 0x04:
+        {
+          nextAnalyser = new PUdpGenrepZoning( mDecodeData );
+          break;
+        }
+        case 0x09:
+        {
+          nextAnalyser = new PUdpPopupResponse( mDecodeData );
+          break;
+        }
+        case 0x0a:
+        {
+          nextAnalyser = new PUdpAptLocInfo( mDecodeData );
+          break;
+        }
+        case 0x0f:
+        {
+          nextAnalyser = new PUdpVhcUse( mDecodeData );
+          break;
+        }
+        case 0x10:
+        {
+          nextAnalyser = new PUdpKillSelf( mDecodeData );
+          break;
+        }
+        default:
+        {
+          mDecodeData->mUnknownType = MsgSubType;
+          break;
+        }
+      }
+      break;
+    }
+    case 0x3e:
+    {
+        nextAnalyser = new PUdpPvPTrade( mDecodeData );
+        break;
+    }
+    case 0x4c:
+    {
+      nextAnalyser = new PUdpChatChannels( mDecodeData );
+      break;
+    }
+    default:
+    {
+      mDecodeData->mUnknownType = MsgType;
+      mDecodeData->mTraceUnknownMsg = true;
+      break;
+    }
+  }
+
+  if ( ! nextAnalyser )
+  {
+    nextAnalyser = new PUdpMsgUnknown( mDecodeData );
+  }
+
+  return nextAnalyser;
+}
index 0613a0c..48ba284 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdp0x1f : public PUdpMsgAnalyser {\r
-public:\r
-    PUdp0x1f(PMsgDecodeData *nDecodeData);\r
-    //~PUdp0x1f();\r
-    PUdpMsgAnalyser *Analyse();\r
-    //bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdp0x1f : public PUdpMsgAnalyser {
+public:
+    PUdp0x1f(PMsgDecodeData *nDecodeData);
+    //~PUdp0x1f();
+    PUdpMsgAnalyser *Analyse();
+    //bool DoAction();
+};
index 459666b..a2f54ee 100644 (file)
@@ -1,51 +1,51 @@
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdp0x22 ****/\r
-\r
-PUdp0x22::PUdp0x22(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  nDecodeData->mName << "/0x22";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdp0x22::Analyse()\r
-{\r
-  PUdpMsgAnalyser* nextAnalyser = NULL;\r
-  mDecodeData->mState = DECODE_MORE;\r
-  uint8_t MsgType = mDecodeData->mMessage->U8Data(mDecodeData->Sub0x13Start + 5);\r
-  switch(MsgType) // MsgType is probably uint16_t rather than uint8_t\r
-  {\r
-    case 0x03: // Zoning phase 2\r
-    {\r
-      nextAnalyser = new PUdpZoning2(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x06: // Char/Clan/Rank/Map Info request\r
-    {\r
-      nextAnalyser = new PUdpReqInfo(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x0b: // Entity position request\r
-    {\r
-      nextAnalyser = new PUdpEntityPosRequest(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x0d: // Zoning phase 1\r
-    {\r
-      nextAnalyser = new PUdpZoning1(mDecodeData);\r
-      break;\r
-    }\r
-    default:\r
-    {\r
-      mDecodeData->mUnknownType = MsgType;\r
-      break;\r
-    }\r
-  }\r
-\r
-  if (! nextAnalyser)\r
-  {\r
-    nextAnalyser = new PUdpMsgUnknown(mDecodeData);\r
-  }\r
-\r
-  return nextAnalyser;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdp0x22 ****/
+
+PUdp0x22::PUdp0x22(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  nDecodeData->mName << "/0x22";
+}
+
+PUdpMsgAnalyser* PUdp0x22::Analyse()
+{
+  PUdpMsgAnalyser* nextAnalyser = NULL;
+  mDecodeData->mState = DECODE_MORE;
+  uint8_t MsgType = mDecodeData->mMessage->U8Data(mDecodeData->Sub0x13Start + 5);
+  switch(MsgType) // MsgType is probably uint16_t rather than uint8_t
+  {
+    case 0x03: // Zoning phase 2
+    {
+      nextAnalyser = new PUdpZoning2(mDecodeData);
+      break;
+    }
+    case 0x06: // Char/Clan/Rank/Map Info request
+    {
+      nextAnalyser = new PUdpReqInfo(mDecodeData);
+      break;
+    }
+    case 0x0b: // Entity position request
+    {
+      nextAnalyser = new PUdpEntityPosRequest(mDecodeData);
+      break;
+    }
+    case 0x0d: // Zoning phase 1
+    {
+      nextAnalyser = new PUdpZoning1(mDecodeData);
+      break;
+    }
+    default:
+    {
+      mDecodeData->mUnknownType = MsgType;
+      break;
+    }
+  }
+
+  if (! nextAnalyser)
+  {
+    nextAnalyser = new PUdpMsgUnknown(mDecodeData);
+  }
+
+  return nextAnalyser;
+}
index aa946b3..7795b08 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdp0x22 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdp0x22(PMsgDecodeData *nDecodeData);\r
-    //~PUdp0x22();\r
-    PUdpMsgAnalyser *Analyse();\r
-    //bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdp0x22 : public PUdpMsgAnalyser {
+public:
+    PUdp0x22(PMsgDecodeData *nDecodeData);
+    //~PUdp0x22();
+    PUdpMsgAnalyser *Analyse();
+    //bool DoAction();
+};
index 28e9e5a..213629e 100644 (file)
@@ -1,57 +1,57 @@
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdp0x2b ****/\r
-\r
-PUdp0x2b::PUdp0x2b(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  nDecodeData->mName << "/0x2b";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdp0x2b::Analyse()\r
-{\r
-  PUdpMsgAnalyser* nextAnalyser = nullptr;\r
-  mDecodeData->mState = DECODE_MORE;\r
-  uint8_t MsgType = mDecodeData->mMessage->U8Data(mDecodeData->Sub0x13Start + 5);\r
-  switch(MsgType)\r
-  {\r
-    case 0x17: // ReceiveDB Terminal Command\r
-    {\r
-      nextAnalyser = new PUdpReceiveDB(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x18: // UpdateDB Terminal Command\r
-    {\r
-      nextAnalyser = new PUdpUpdateDB(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x19: // TryAccess Terminal Command\r
-    {\r
-      nextAnalyser = new PUdpTryAccessDB(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x1b: // DB Query and Command\r
-    {\r
-      nextAnalyser = new PUdpQueryDB(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x1f: // Citycom?\r
-    {\r
-      nextAnalyser = new PUdpTeminal0x1f(mDecodeData);\r
-      break;\r
-    }\r
-\r
-    default:\r
-    {\r
-      mDecodeData->mUnknownType = MsgType;\r
-      break;\r
-    }\r
-  }\r
-\r
-  if (! nextAnalyser)\r
-  {\r
-    nextAnalyser = new PUdpMsgUnknown(mDecodeData);\r
-  }\r
-\r
-  return nextAnalyser;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdp0x2b ****/
+
+PUdp0x2b::PUdp0x2b(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  nDecodeData->mName << "/0x2b";
+}
+
+PUdpMsgAnalyser* PUdp0x2b::Analyse()
+{
+  PUdpMsgAnalyser* nextAnalyser = nullptr;
+  mDecodeData->mState = DECODE_MORE;
+  uint8_t MsgType = mDecodeData->mMessage->U8Data(mDecodeData->Sub0x13Start + 5);
+  switch(MsgType)
+  {
+    case 0x17: // ReceiveDB Terminal Command
+    {
+      nextAnalyser = new PUdpReceiveDB(mDecodeData);
+      break;
+    }
+    case 0x18: // UpdateDB Terminal Command
+    {
+      nextAnalyser = new PUdpUpdateDB(mDecodeData);
+      break;
+    }
+    case 0x19: // TryAccess Terminal Command
+    {
+      nextAnalyser = new PUdpTryAccessDB(mDecodeData);
+      break;
+    }
+    case 0x1b: // DB Query and Command
+    {
+      nextAnalyser = new PUdpQueryDB(mDecodeData);
+      break;
+    }
+    case 0x1f: // Citycom?
+    {
+      nextAnalyser = new PUdpTeminal0x1f(mDecodeData);
+      break;
+    }
+
+    default:
+    {
+      mDecodeData->mUnknownType = MsgType;
+      break;
+    }
+  }
+
+  if (! nextAnalyser)
+  {
+    nextAnalyser = new PUdpMsgUnknown(mDecodeData);
+  }
+
+  return nextAnalyser;
+}
index e3baa60..1295f9d 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdp0x2b : public PUdpMsgAnalyser {\r
-public:\r
-    PUdp0x2b(PMsgDecodeData *nDecodeData);\r
-    //~PUdp0x2b();\r
-    PUdpMsgAnalyser *Analyse();\r
-    //bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdp0x2b : public PUdpMsgAnalyser {
+public:
+    PUdp0x2b(PMsgDecodeData *nDecodeData);
+    //~PUdp0x2b();
+    PUdpMsgAnalyser *Analyse();
+    //bool DoAction();
+};
index 24d2aa3..dbe6e37 100644 (file)
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdpMsgAnalyser ****/\r
-\r
-int PUdpMsgAnalyser::smAnaCount = 0; // temp for check\r
-\r
-PUdpMsgAnalyser::PUdpMsgAnalyser(PMsgDecodeData* nDecodeData)\r
-{\r
-  mDecodeData = nDecodeData;\r
-  if (++smAnaCount > 2) // temp for check\r
-    Console->Print(RED, BLACK, "Analyser instances count: %d", smAnaCount);  // temp for check\r
-}\r
-\r
-PUdpMsgAnalyser::~PUdpMsgAnalyser()\r
-{\r
-  --smAnaCount;\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpMsgAnalyser::Analyse()\r
-{\r
-  PUdpMsgAnalyser* nextAnalyser;\r
-  uint8_t MsgType;\r
-\r
-  mDecodeData->mState = DECODE_MORE;\r
-//mDecodeData->mTraceKnownMsg = true; // Don't want to trace all known messages\r
-mDecodeData->mTraceUnknownMsg = true; // Want to show all unknown messages\r
-\r
-  *(mDecodeData->mMessage) >> MsgType;\r
-  switch(MsgType)\r
-  {\r
-    case 0x01:\r
-    {\r
-      nextAnalyser = new PUdpSync0(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x03:\r
-    {\r
-      nextAnalyser = new PUdpSync1(mDecodeData);\r
-      break;\r
-    }\r
-    case 0x08:\r
-    {\r
-        nextAnalyser = new PUdp0x08(mDecodeData);\r
-        break;\r
-    }\r
-    case 0x13:\r
-    {\r
-      nextAnalyser = new PUdp0x13(mDecodeData);\r
-      break;\r
-    }\r
-    default:\r
-    {\r
-      mDecodeData->mUnknownType = MsgType;\r
-      nextAnalyser = new PUdpMsgUnknown(mDecodeData);\r
-      break;\r
-    }\r
-  }\r
- return nextAnalyser;\r
-}\r
-\r
-bool PUdpMsgAnalyser::DoAction()\r
-{\r
-  return false; // no action at this level\r
-}\r
-\r
-\r
-/**** Unkown UDP message ****/\r
-\r
-PUdpMsgUnknown::PUdpMsgUnknown(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  char hexstr[16];\r
-\r
-  nDecodeData->mState = DECODE_UNKNOWN;\r
-  snprintf(hexstr, 16, "/0x%02x", mDecodeData->mUnknownType);\r
-  mDecodeData->mName << hexstr;\r
-  nDecodeData->mName << "=Unknown";\r
-}\r
-\r
-/*PUdpMsgUnknown::~PUdpMsgUnknown()\r
-{\r
-}*/\r
-\r
-/*bool PUdpMsgUnknown::DoAction()\r
-{\r
-  return false;\r
-}*/\r
-\r
-/**** Ignore UDP message ****/\r
-\r
-PUdpMsgIgnore::PUdpMsgIgnore(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  char hexstr[16];\r
-\r
-  nDecodeData->mState = DECODE_FINISHED;\r
-  snprintf(hexstr, 16, "/0x%02x", mDecodeData->mUnknownType);\r
-  mDecodeData->mName << hexstr;\r
-  nDecodeData->mName << "=Ignore";\r
-}\r
-\r
-/*PUdpMsgUnknown::~PUdpMsgUnknown()\r
-{\r
-}*/\r
-\r
-/*bool PUdpMsgUnknown::DoAction()\r
-{\r
-  return false;\r
-}*/\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdpMsgAnalyser ****/
+
+int PUdpMsgAnalyser::smAnaCount = 0; // temp for check
+
+PUdpMsgAnalyser::PUdpMsgAnalyser(PMsgDecodeData* nDecodeData)
+{
+  mDecodeData = nDecodeData;
+  if (++smAnaCount > 2) // temp for check
+    Console->Print(RED, BLACK, "Analyser instances count: %d", smAnaCount);  // temp for check
+}
+
+PUdpMsgAnalyser::~PUdpMsgAnalyser()
+{
+  --smAnaCount;
+}
+
+PUdpMsgAnalyser* PUdpMsgAnalyser::Analyse()
+{
+  PUdpMsgAnalyser* nextAnalyser;
+  uint8_t MsgType;
+
+  mDecodeData->mState = DECODE_MORE;
+//mDecodeData->mTraceKnownMsg = true; // Don't want to trace all known messages
+mDecodeData->mTraceUnknownMsg = true; // Want to show all unknown messages
+
+  *(mDecodeData->mMessage) >> MsgType;
+  switch(MsgType)
+  {
+    case 0x01:
+    {
+      nextAnalyser = new PUdpSync0(mDecodeData);
+      break;
+    }
+    case 0x03:
+    {
+      nextAnalyser = new PUdpSync1(mDecodeData);
+      break;
+    }
+    case 0x08:
+    {
+        nextAnalyser = new PUdp0x08(mDecodeData);
+        break;
+    }
+    case 0x13:
+    {
+      nextAnalyser = new PUdp0x13(mDecodeData);
+      break;
+    }
+    default:
+    {
+      mDecodeData->mUnknownType = MsgType;
+      nextAnalyser = new PUdpMsgUnknown(mDecodeData);
+      break;
+    }
+  }
+ return nextAnalyser;
+}
+
+bool PUdpMsgAnalyser::DoAction()
+{
+  return false; // no action at this level
+}
+
+
+/**** Unkown UDP message ****/
+
+PUdpMsgUnknown::PUdpMsgUnknown(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  char hexstr[16];
+
+  nDecodeData->mState = DECODE_UNKNOWN;
+  snprintf(hexstr, 16, "/0x%02x", mDecodeData->mUnknownType);
+  mDecodeData->mName << hexstr;
+  nDecodeData->mName << "=Unknown";
+}
+
+/*PUdpMsgUnknown::~PUdpMsgUnknown()
+{
+}*/
+
+/*bool PUdpMsgUnknown::DoAction()
+{
+  return false;
+}*/
+
+/**** Ignore UDP message ****/
+
+PUdpMsgIgnore::PUdpMsgIgnore(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  char hexstr[16];
+
+  nDecodeData->mState = DECODE_FINISHED;
+  snprintf(hexstr, 16, "/0x%02x", mDecodeData->mUnknownType);
+  mDecodeData->mName << hexstr;
+  nDecodeData->mName << "=Ignore";
+}
+
+/*PUdpMsgUnknown::~PUdpMsgUnknown()
+{
+}*/
+
+/*bool PUdpMsgUnknown::DoAction()
+{
+  return false;
+}*/
index 9c98d48..a6fc151 100644 (file)
@@ -1,38 +1,38 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-struct PMsgDecodeData;\r
-\r
-class PUdpMsgAnalyser {\r
-    friend class PUdpMsgDecoder;\r
-\r
-protected:\r
-    PMsgDecodeData* mDecodeData;\r
-\r
-public:\r
-    PUdpMsgAnalyser(PMsgDecodeData *nDecodeData);\r
-    virtual ~PUdpMsgAnalyser();\r
-\r
-    virtual PUdpMsgAnalyser *Analyse();\r
-    virtual bool DoAction();\r
-\r
-    static int32_t smAnaCount; // temp for check\r
-\r
-};\r
-\r
-class PUdpMsgUnknown : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpMsgUnknown(PMsgDecodeData *nDecodeData);\r
-    //~PUdpMsgUnknown();\r
-\r
-    //bool DoAction();\r
-};\r
-\r
-class PUdpMsgIgnore : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpMsgIgnore(PMsgDecodeData *nDecodeData);\r
-    //~PUdpMsgUnknown();\r
-\r
-    //bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+struct PMsgDecodeData;
+
+class PUdpMsgAnalyser {
+    friend class PUdpMsgDecoder;
+
+protected:
+    PMsgDecodeData* mDecodeData;
+
+public:
+    PUdpMsgAnalyser(PMsgDecodeData *nDecodeData);
+    virtual ~PUdpMsgAnalyser();
+
+    virtual PUdpMsgAnalyser *Analyse();
+    virtual bool DoAction();
+
+    static int32_t smAnaCount; // temp for check
+
+};
+
+class PUdpMsgUnknown : public PUdpMsgAnalyser {
+public:
+    PUdpMsgUnknown(PMsgDecodeData *nDecodeData);
+    //~PUdpMsgUnknown();
+
+    //bool DoAction();
+};
+
+class PUdpMsgIgnore : public PUdpMsgAnalyser {
+public:
+    PUdpMsgIgnore(PMsgDecodeData *nDecodeData);
+    //~PUdpMsgUnknown();
+
+    //bool DoAction();
+};
index ca627bf..d1941c3 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpAptLocInfo : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpAptLocInfo(PMsgDecodeData *nDecodeData);\r
-    //~PUdpAptLocInfo();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpAptLocInfo : public PUdpMsgAnalyser {
+public:
+    PUdpAptLocInfo(PMsgDecodeData *nDecodeData);
+    //~PUdpAptLocInfo();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 7100914..1a318e6 100644 (file)
-#include <string>\r
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-#define JUMPHEIGHT 160\r
-\r
-/**** PUdpCharPosUpdate ****/\r
-\r
-PUdpCharPosUpdate::PUdpCharPosUpdate( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x20";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpCharPosUpdate::Analyse()\r
-{\r
-  mDecodeData->mName << "=Char position update";\r
-\r
-//mDecodeData->mTraceUnknownMsg = true; // temp stop being bugged with unknown move msg\r
-//mDecodeData->mTraceKnownMsg = true;\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 4 );\r
-\r
-  *nMsg >> mInfoBitfield;\r
-//bitfield [C?AL UXZY] packet read from LSB\r
-//          8.21 8421\r
-//Console->Print(YELLOW, BLACK, "[DEBUG] PUdpCharPosUpdate: Bitfield value %02x", mInfoBitfield);\r
-  if ( mInfoBitfield & 0x80 ) // Sitting on chair\r
-  {\r
-    if ( mInfoBitfield & 0x7f )\r
-    {\r
-      mDecodeData->mName << " + mixed bitfield (" << mInfoBitfield << ")";\r
-      mDecodeData->mState = DECODE_UNKNOWN | DECODE_FINISHED;\r
-      Console->Print( YELLOW, BLACK, "[DEBUG] PUdpCharPosUpdate: Client %d sent Mixed field value %x", mDecodeData->mClient->GetID(), mInfoBitfield );\r
-    }\r
-    else\r
-    {\r
-      mDecodeData->mName << " (Char sitting)";\r
-\r
-      *nMsg >> mChairItemID;\r
-      *nMsg >> mChairItemSeat;\r
-      mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-//mDecodeData->mTraceKnownMsg = true;\r
-//mDecodeData->mTraceDump = true;\r
-      if ( gDevDebug ) Console->Print( "%s Localid %d sitting on object %d (0x%08x) seat %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetLocalID(), mChairItemID, mChairItemID, mChairItemSeat );\r
-    }\r
-  }\r
-  else\r
-  {\r
-    if ( mInfoBitfield & 0x01 )\r
-    {\r
-      *nMsg >> mNewY;\r
-    }\r
-    if ( mInfoBitfield & 0x02 )\r
-    {\r
-      *nMsg >> mNewZ;\r
-    }\r
-    if ( mInfoBitfield & 0x04 )\r
-    {\r
-      *nMsg >> mNewX;\r
-    }\r
-    if ( mInfoBitfield & 0x08 )\r
-    {\r
-      *nMsg >> mNewUD;\r
-    }\r
-    if ( mInfoBitfield & 0x10 )\r
-    {\r
-      *nMsg >> mNewLR;\r
-    }\r
-    if ( mInfoBitfield & 0x20 )\r
-    {\r
-      *nMsg >> mNewAct;\r
-    }\r
-    if ( mInfoBitfield & 0x40 ) // purpose unknown\r
-    {\r
-      *nMsg >> mNewUnknown;\r
-      if ( gDevDebug && mNewUnknown )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[DEBUG] PUdpCharPosUpdate: Client %d sent field 0x40 (in %x) value %x", mDecodeData->mClient->GetID(), mInfoBitfield, mNewUnknown );\r
-      }\r
-    }\r
-\r
-    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  }\r
-\r
-  return this;\r
-}\r
-\r
-bool PUdpCharPosUpdate::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* nChar = nClient->GetChar();\r
-  PMessage* tmpMsg;\r
-\r
-  if ( ! (mInfoBitfield & 0x80) )\r
-  {\r
-    uint32_t nSeatableObjectId;\r
-    uint8_t nSeatId;\r
-    if( nChar->GetSeatInUse(&nSeatableObjectId, &nSeatId) == seat_vhc )\r
-    {\r
-      tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, nSeatableObjectId, nSeatId );\r
-      nClient->FillInUDP_ID(tmpMsg);\r
-      nClient->SendUDPMessage( tmpMsg );\r
-      mChairItemID = nSeatableObjectId;\r
-      mChairItemSeat = nSeatId;\r
-      mInfoBitfield = 0x80;\r
-    }\r
-  }\r
-\r
-  if ( mInfoBitfield & 0x80 ) // Sitting on chair\r
-  {\r
-    //tmpMsg = MsgBuilder->BuildCharSittingMsg(nClient, mChairItemID);\r
-    //tmpMsg = MsgBuilder->BuildCharSittingMsg(nClient);\r
-    //ClientManager->UDPBroadcast(tmpMsg, nClient, 5000); // TODO: Get the range from config\r
-    tmpMsg = MsgBuilder->BuildCharPosUpdateMsg( nClient );\r
-    ClientManager->UDPBroadcast( tmpMsg, nClient, 5000 ); // TODO: Get the range from config\r
-  }\r
-  else\r
-  {\r
-    bool IsRealMove = false;\r
-\r
-    if (( mInfoBitfield & 0x01 ) && ( nChar->Coords.mY != mNewY ) )\r
-    {\r
-      nChar->Coords.mY = mNewY;\r
-      IsRealMove = true;\r
-    }\r
-    if (( mInfoBitfield & 0x02 ) && ( nChar->Coords.mZ != mNewZ ) )\r
-    {\r
-      nChar->Coords.mZ = mNewZ;\r
-      IsRealMove = true;\r
-    }\r
-    if (( mInfoBitfield & 0x04 ) && ( nChar->Coords.mX != mNewX ) )\r
-    {\r
-      nChar->Coords.mX = mNewX;\r
-      IsRealMove = true;\r
-    }\r
-    if ( mInfoBitfield & 0x08 )\r
-    {\r
-      nChar->Coords.mUD = mNewUD;\r
-      //IsRealMove = true;\r
-    }\r
-    if (( mInfoBitfield & 0x10 ) && ( nChar->Coords.mLR != mNewLR ) )\r
-    {\r
-      nChar->Coords.mLR = mNewLR;\r
-      IsRealMove = true;\r
-    }\r
-    if ( mInfoBitfield & 0x20 )\r
-    {\r
-      nChar->Coords.mAct = mNewAct;\r
-    }\r
-    if ( mInfoBitfield & 0x20 )\r
-    {\r
-      nChar->Coords.mUnknown = mNewUnknown;\r
-    }\r
-    // movement action byte mask:\r
-    // 0x00 NC has no focus (player alt+tab'ed out)\r
-    // 0x02 kneeing\r
-    // 0x20 Walk mode (= not run mode)\r
-    // 0x08 left step\r
-    // 0x10 right step\r
-    // 0x40 forward\r
-    // 0x80 backward\r
-    // bits:  00000000\r
-    //        BFWRL.K.\r
-\r
-    if ( IsRealMove )\r
-    {\r
-      nChar->SetDirtyFlag();\r
-    }\r
-    /*if(IsRealMove)\r
-    if(mInfoBitfield == 0x7f)\r
-    {\r
-      tmpMsg = MsgBuilder->BuildCharPosUpdateMsg(nClient);\r
-      ClientManager->UDPBroadcast(tmpMsg, nClient, 5000); // TODO: Get the range from config\r
-    }*/\r
-\r
-    uint16_t nSaveZ = nChar->Coords.mZ;\r
-    if(nChar->Coords.mJumpingState)\r
-    {\r
-      mInfoBitfield |= 0x02; // Update Z and Act only\r
-      if(nChar->Coords.mJumpingState == 1)\r
-      {\r
-        if ( gDevDebug ) Console->Print( "%s Send moving jump", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-        (nChar->Coords.mZ) += JUMPHEIGHT;\r
-        nChar->Coords.mJumpingState = 2; // Jump done\r
-      }\r
-      else\r
-        nChar->Coords.mJumpingState = 0; // No pending jump\r
-    }\r
-\r
-    tmpMsg = MsgBuilder->BuildCharPosUpdate2Msg( nClient, mInfoBitfield );\r
-\r
-    if(nChar->Coords.mJumpingState)\r
-      nChar->Coords.mZ = nSaveZ;\r
-\r
-    ClientManager->UDPBroadcast( tmpMsg, nClient, 5000, true );\r
-\r
-    if ( IsRealMove && nClient->GetDebugMode( DBG_LOCATION ) )\r
-    {\r
-      char DbgMessage[128];\r
-      float f[3];\r
-//      uint32_t h[3];\r
-      f[0] = nChar->Coords.mY - 32000;\r
-      f[1] = nChar->Coords.mZ - 32000;\r
-      f[2] = nChar->Coords.mX - 32000;\r
-      snprintf( DbgMessage, 128, "position y:%0.1f z:%0.1f x:%0.1f lr:%d (Act=%x BF=%x)", f[0], f[1], f[2], nChar->Coords.mLR, nChar->Coords.mAct , mInfoBitfield );\r
-      Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-    }\r
-    /*{\r
-      uint16_t p[3];\r
-      p[0] = nChar->Coords.mY;\r
-      p[1] = nChar->Coords.mZ;\r
-      p[2] = nChar->Coords.mX;\r
-      for(int i = 0; i<3; i++)\r
-      {\r
-        if(p[i]< nChar->Coords.minPos[i])\r
-          nChar->Coords.minPos[i] = p[i];\r
-        if(p[i]> nChar->Coords.maxPos[i])\r
-          nChar->Coords.maxPos[i] = p[i];\r
-      }\r
-    }*/\r
-\r
-  if(gDevDebug && IsRealMove)\r
-    Console->Print("%s Char %d position : X(%d) Y(%d) Z(%d) U/D(%d) L/R(%d) Action(%02x)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetID(), nChar->Coords.mX, nChar->Coords.mY, nChar->Coords.mZ, nChar->Coords.mUD, nChar->Coords.mLR, nChar->Coords.mAct);\r
-  }\r
-  if ( mInfoBitfield >= 0x7f )\r
-  {\r
-    tmpMsg = MsgBuilder->BuildCharHealthUpdateMsg( nClient );\r
-    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-\r
-/**** PUdpCharExitChair ****/\r
-\r
-PUdpCharExitChair::PUdpCharExitChair( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x22";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpCharExitChair::Analyse()\r
-{\r
-  mDecodeData->mName << "=Char exiting chair";\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-\r
-  return this;\r
-}\r
-\r
-bool PUdpCharExitChair::DoAction()\r
-{\r
-  DoLeaveChair( mDecodeData->mClient->GetChar(), mDecodeData->mClient );\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-bool PUdpCharExitChair::DoLeaveChair( PChar* nChar, PClient* nClient, PSpawnedVehicle* nVhc, bool nForce )\r
-{\r
-  if ( ! nClient )\r
-    nClient = ClientManager->getClientByChar( nChar->GetID() );\r
-  if ( ! nClient )\r
-  {\r
-    Console->Print("%s PUdpCharExitChair::DoLeaveChair called without PClient* and client not available when searching by char.", Console->ColorText( RED, BLACK, "[ERROR]" ) );\r
-    return false;\r
-  }\r
-\r
-  PMessage* tmpMsg;\r
-  uint32_t cSeatObjectId;\r
-  uint8_t cSeatId;\r
-  PSeatType cSeatType = nChar->GetSeatInUse( &cSeatObjectId, &cSeatId );\r
-  uint32_t tNowTime = GameServer->GetGameTime();\r
-  bool ReadyToExit = false;\r
-\r
-  // This is only for investigation on subway timing\r
-  if ( nClient->GetDebugMode( DBG_SUBWAY ) && ( cSeatType == seat_subway ) )\r
-  {\r
-    char DbgMessage[80];\r
-    uint8_t tCabId;\r
-    Subway->GetInfoIndex( cSeatObjectId, &tCabId );\r
-    uint8_t tStationId = Subway->GetStation( cSeatObjectId, tNowTime );\r
-    std::string* StationName = Subway->GetStationName( tStationId );\r
-    std::string OpenState = ( Subway->IsDoorOpen( cSeatObjectId, tNowTime ) ? "open" : "closed" );\r
-\r
-    snprintf( DbgMessage, 80, "Cab %d (%d) is in station %s (%d). Door is %s (time: %d)", tCabId, cSeatObjectId, StationName->c_str(), tStationId, OpenState.c_str(), tNowTime );\r
-    DbgMessage[79] = 0;\r
-    Chat->send( nClient, CHAT_DIRECT, "System", DbgMessage );\r
-    delete StationName;\r
-  }\r
-  // end investigation\r
-\r
-  if ( cSeatType )\r
-  {\r
-    PWorld* tWorld = Worlds->GetWorld( nChar->GetLocation() );\r
-\r
-    if ( cSeatType == seat_chair )\r
-    {\r
-      tWorld->CharLeaveChair( nClient->GetLocalID(), cSeatObjectId );\r
-      nChar->SetSeatInUse( seat_none );\r
-      ReadyToExit = true;\r
-    }\r
-    else if ( cSeatType == seat_subway )\r
-    {\r
-      if ( Subway->IsDoorOpen( cSeatObjectId, tNowTime ) || nForce )\r
-      {\r
-        Subway->GetStationExitPosition( &( nChar->Coords ), Subway->GetStation( cSeatObjectId, tNowTime ), GetRandomFloat() );\r
-        Subway->UnsetSeatUser( cSeatObjectId, cSeatId, nChar->GetID() );\r
-        nChar->SetSeatInUse( seat_none );\r
-        ReadyToExit = true;\r
-      }\r
-      else\r
-      {\r
-        tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, cSeatObjectId ); // "Damn, locked"\r
-        nClient->SendUDPMessage( tmpMsg );\r
-      }\r
-    }\r
-    else if ( cSeatType == seat_vhc )\r
-    {\r
-      PSpawnedVehicle* tVhc = tWorld->GetSpawnedVehicles()->GetVehicle( cSeatObjectId );\r
-      if ( tVhc && (!nVhc || (tVhc == nVhc) || nForce) )\r
-      {\r
-        PVhcCoordinates tCoords = tVhc->GetPosition();\r
-        tVhc->UnsetSeatUser( cSeatId, nChar->GetID() );\r
-        nChar->SetSeatInUse( seat_none );\r
-        nChar->Coords.SetPosition( tCoords.GetY(), tCoords.GetZ(), tCoords.GetX() ); // to complete with LR\r
-        ReadyToExit = true;\r
-      }\r
-    }\r
-    else\r
-    {\r
-      Console->Print( "%s PUdpCharExitChair::DoLeaveChair : Invalid seat type %d", Console->ColorText( RED, BLACK, "[ERROR]" ), cSeatType );\r
-    }\r
-\r
-    if ( ReadyToExit )\r
-    {\r
-      nChar->SetSeatInUse( seat_none );\r
-\r
-      tmpMsg = MsgBuilder->BuildCharExitSeatMsg( nClient );\r
-      ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-\r
-      if ( gDevDebug ) Console->Print( "%s Localchar %d get up from chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nClient->GetLocalID(), cSeatObjectId );\r
-      return true;\r
-    }\r
-  }\r
-\r
-  return false;\r
-}\r
-\r
-/**** PUdpCharJump ****/\r
-\r
-PUdpCharJump::PUdpCharJump( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x02";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpCharJump::Analyse()\r
-{\r
-  mDecodeData->mName << "=Char jumping";\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-\r
-  return this;\r
-}\r
-\r
-bool PUdpCharJump::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* nChar = nClient->GetChar();\r
-\r
-  if( nChar->Coords.mAct & 0xd8 ) // if moving, don't jump now and wait next update\r
-  {\r
-    nChar->Coords.mJumpingState = 1; // Jump pending. Do at next pos update\r
-    if ( gDevDebug ) Console->Print( "%s Prepare moving jump", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-  }\r
-  else // If not moving, jump now\r
-  {\r
-    if ( gDevDebug ) Console->Print( "%s Send static jump", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    uint8_t mInfoBitfield = 0x22; // Update Z and Act only\r
-    uint16_t nSaveZ = nChar->Coords.mZ;\r
-    (nChar->Coords.mZ) += JUMPHEIGHT;\r
-    PMessage* tmpMsg = MsgBuilder->BuildCharPosUpdate2Msg( nClient, mInfoBitfield );\r
-    nChar->Coords.mZ = nSaveZ;\r
-    nChar->Coords.mJumpingState = 2; // Jump done\r
-    ClientManager->UDPBroadcast( tmpMsg, nClient, 5000, true );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-\r
-  return true;\r
-}\r
-\r
-\r
-/**** PUdpCharTargeting ****/\r
-\r
-PUdpCharTargeting::PUdpCharTargeting( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x2d";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpCharTargeting::Analyse()\r
-{\r
-  mDecodeData->mName << "=Targeting char";\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-\r
-  return this;\r
-}\r
-\r
-bool PUdpCharTargeting::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* tChar = nClient->GetChar();\r
-  uint16_t CharID = mDecodeData->mMessage->U16Data( mDecodeData->Sub0x13Start + 2 );\r
-  uint8_t strangeval1 = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 4 );\r
-  uint8_t strangeval2 = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 5 );\r
-  uint8_t strangeval3 = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 6 );\r
-\r
-  tChar->SetLookingAt( CharID );\r
-\r
-  if ( gDevDebug )\r
-    Console->Print( "%s Char %d targeting char %d. // %d %d %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetID(), CharID, strangeval1, strangeval2, strangeval3 );\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
+#include <string>
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+#define JUMPHEIGHT 160
+
+/**** PUdpCharPosUpdate ****/
+
+PUdpCharPosUpdate::PUdpCharPosUpdate( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x20";
+}
+
+PUdpMsgAnalyser* PUdpCharPosUpdate::Analyse()
+{
+  mDecodeData->mName << "=Char position update";
+
+//mDecodeData->mTraceUnknownMsg = true; // temp stop being bugged with unknown move msg
+//mDecodeData->mTraceKnownMsg = true;
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 4 );
+
+  *nMsg >> mInfoBitfield;
+//bitfield [C?AL UXZY] packet read from LSB
+//          8.21 8421
+//Console->Print(YELLOW, BLACK, "[DEBUG] PUdpCharPosUpdate: Bitfield value %02x", mInfoBitfield);
+  if ( mInfoBitfield & 0x80 ) // Sitting on chair
+  {
+    if ( mInfoBitfield & 0x7f )
+    {
+      mDecodeData->mName << " + mixed bitfield (" << mInfoBitfield << ")";
+      mDecodeData->mState = DECODE_UNKNOWN | DECODE_FINISHED;
+      Console->Print( YELLOW, BLACK, "[DEBUG] PUdpCharPosUpdate: Client %d sent Mixed field value %x", mDecodeData->mClient->GetID(), mInfoBitfield );
+    }
+    else
+    {
+      mDecodeData->mName << " (Char sitting)";
+
+      *nMsg >> mChairItemID;
+      *nMsg >> mChairItemSeat;
+      mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+//mDecodeData->mTraceKnownMsg = true;
+//mDecodeData->mTraceDump = true;
+      if ( gDevDebug ) Console->Print( "%s Localid %d sitting on object %d (0x%08x) seat %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetLocalID(), mChairItemID, mChairItemID, mChairItemSeat );
+    }
+  }
+  else
+  {
+    if ( mInfoBitfield & 0x01 )
+    {
+      *nMsg >> mNewY;
+    }
+    if ( mInfoBitfield & 0x02 )
+    {
+      *nMsg >> mNewZ;
+    }
+    if ( mInfoBitfield & 0x04 )
+    {
+      *nMsg >> mNewX;
+    }
+    if ( mInfoBitfield & 0x08 )
+    {
+      *nMsg >> mNewUD;
+    }
+    if ( mInfoBitfield & 0x10 )
+    {
+      *nMsg >> mNewLR;
+    }
+    if ( mInfoBitfield & 0x20 )
+    {
+      *nMsg >> mNewAct;
+    }
+    if ( mInfoBitfield & 0x40 ) // purpose unknown
+    {
+      *nMsg >> mNewUnknown;
+      if ( gDevDebug && mNewUnknown )
+      {
+        Console->Print( YELLOW, BLACK, "[DEBUG] PUdpCharPosUpdate: Client %d sent field 0x40 (in %x) value %x", mDecodeData->mClient->GetID(), mInfoBitfield, mNewUnknown );
+      }
+    }
+
+    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  }
+
+  return this;
+}
+
+bool PUdpCharPosUpdate::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* nChar = nClient->GetChar();
+  PMessage* tmpMsg;
+
+  if ( ! (mInfoBitfield & 0x80) )
+  {
+    uint32_t nSeatableObjectId;
+    uint8_t nSeatId;
+    if( nChar->GetSeatInUse(&nSeatableObjectId, &nSeatId) == seat_vhc )
+    {
+      tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, nSeatableObjectId, nSeatId );
+      nClient->FillInUDP_ID(tmpMsg);
+      nClient->SendUDPMessage( tmpMsg );
+      mChairItemID = nSeatableObjectId;
+      mChairItemSeat = nSeatId;
+      mInfoBitfield = 0x80;
+    }
+  }
+
+  if ( mInfoBitfield & 0x80 ) // Sitting on chair
+  {
+    //tmpMsg = MsgBuilder->BuildCharSittingMsg(nClient, mChairItemID);
+    //tmpMsg = MsgBuilder->BuildCharSittingMsg(nClient);
+    //ClientManager->UDPBroadcast(tmpMsg, nClient, 5000); // TODO: Get the range from config
+    tmpMsg = MsgBuilder->BuildCharPosUpdateMsg( nClient );
+    ClientManager->UDPBroadcast( tmpMsg, nClient, 5000 ); // TODO: Get the range from config
+  }
+  else
+  {
+    bool IsRealMove = false;
+
+    if (( mInfoBitfield & 0x01 ) && ( nChar->Coords.mY != mNewY ) )
+    {
+      nChar->Coords.mY = mNewY;
+      IsRealMove = true;
+    }
+    if (( mInfoBitfield & 0x02 ) && ( nChar->Coords.mZ != mNewZ ) )
+    {
+      nChar->Coords.mZ = mNewZ;
+      IsRealMove = true;
+    }
+    if (( mInfoBitfield & 0x04 ) && ( nChar->Coords.mX != mNewX ) )
+    {
+      nChar->Coords.mX = mNewX;
+      IsRealMove = true;
+    }
+    if ( mInfoBitfield & 0x08 )
+    {
+      nChar->Coords.mUD = mNewUD;
+      //IsRealMove = true;
+    }
+    if (( mInfoBitfield & 0x10 ) && ( nChar->Coords.mLR != mNewLR ) )
+    {
+      nChar->Coords.mLR = mNewLR;
+      IsRealMove = true;
+    }
+    if ( mInfoBitfield & 0x20 )
+    {
+      nChar->Coords.mAct = mNewAct;
+    }
+    if ( mInfoBitfield & 0x20 )
+    {
+      nChar->Coords.mUnknown = mNewUnknown;
+    }
+    // movement action byte mask:
+    // 0x00 NC has no focus (player alt+tab'ed out)
+    // 0x02 kneeing
+    // 0x20 Walk mode (= not run mode)
+    // 0x08 left step
+    // 0x10 right step
+    // 0x40 forward
+    // 0x80 backward
+    // bits:  00000000
+    //        BFWRL.K.
+
+    if ( IsRealMove )
+    {
+      nChar->SetDirtyFlag();
+    }
+    /*if(IsRealMove)
+    if(mInfoBitfield == 0x7f)
+    {
+      tmpMsg = MsgBuilder->BuildCharPosUpdateMsg(nClient);
+      ClientManager->UDPBroadcast(tmpMsg, nClient, 5000); // TODO: Get the range from config
+    }*/
+
+    uint16_t nSaveZ = nChar->Coords.mZ;
+    if(nChar->Coords.mJumpingState)
+    {
+      mInfoBitfield |= 0x02; // Update Z and Act only
+      if(nChar->Coords.mJumpingState == 1)
+      {
+        if ( gDevDebug ) Console->Print( "%s Send moving jump", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+        (nChar->Coords.mZ) += JUMPHEIGHT;
+        nChar->Coords.mJumpingState = 2; // Jump done
+      }
+      else
+        nChar->Coords.mJumpingState = 0; // No pending jump
+    }
+
+    tmpMsg = MsgBuilder->BuildCharPosUpdate2Msg( nClient, mInfoBitfield );
+
+    if(nChar->Coords.mJumpingState)
+      nChar->Coords.mZ = nSaveZ;
+
+    ClientManager->UDPBroadcast( tmpMsg, nClient, 5000, true );
+
+    if ( IsRealMove && nClient->GetDebugMode( DBG_LOCATION ) )
+    {
+      char DbgMessage[128];
+      float f[3];
+//      uint32_t h[3];
+      f[0] = nChar->Coords.mY - 32000;
+      f[1] = nChar->Coords.mZ - 32000;
+      f[2] = nChar->Coords.mX - 32000;
+      snprintf( DbgMessage, 128, "position y:%0.1f z:%0.1f x:%0.1f lr:%d (Act=%x BF=%x)", f[0], f[1], f[2], nChar->Coords.mLR, nChar->Coords.mAct , mInfoBitfield );
+      Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+    }
+    /*{
+      uint16_t p[3];
+      p[0] = nChar->Coords.mY;
+      p[1] = nChar->Coords.mZ;
+      p[2] = nChar->Coords.mX;
+      for(int i = 0; i<3; i++)
+      {
+        if(p[i]< nChar->Coords.minPos[i])
+          nChar->Coords.minPos[i] = p[i];
+        if(p[i]> nChar->Coords.maxPos[i])
+          nChar->Coords.maxPos[i] = p[i];
+      }
+    }*/
+
+  if(gDevDebug && IsRealMove)
+    Console->Print("%s Char %d position : X(%d) Y(%d) Z(%d) U/D(%d) L/R(%d) Action(%02x)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetID(), nChar->Coords.mX, nChar->Coords.mY, nChar->Coords.mZ, nChar->Coords.mUD, nChar->Coords.mLR, nChar->Coords.mAct);
+  }
+  if ( mInfoBitfield >= 0x7f )
+  {
+    tmpMsg = MsgBuilder->BuildCharHealthUpdateMsg( nClient );
+    ClientManager->UDPBroadcast( tmpMsg, nClient );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+
+/**** PUdpCharExitChair ****/
+
+PUdpCharExitChair::PUdpCharExitChair( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x22";
+}
+
+PUdpMsgAnalyser* PUdpCharExitChair::Analyse()
+{
+  mDecodeData->mName << "=Char exiting chair";
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+
+  return this;
+}
+
+bool PUdpCharExitChair::DoAction()
+{
+  DoLeaveChair( mDecodeData->mClient->GetChar(), mDecodeData->mClient );
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+bool PUdpCharExitChair::DoLeaveChair( PChar* nChar, PClient* nClient, PSpawnedVehicle* nVhc, bool nForce )
+{
+  if ( ! nClient )
+    nClient = ClientManager->getClientByChar( nChar->GetID() );
+  if ( ! nClient )
+  {
+    Console->Print("%s PUdpCharExitChair::DoLeaveChair called without PClient* and client not available when searching by char.", Console->ColorText( RED, BLACK, "[ERROR]" ) );
+    return false;
+  }
+
+  PMessage* tmpMsg;
+  uint32_t cSeatObjectId;
+  uint8_t cSeatId;
+  PSeatType cSeatType = nChar->GetSeatInUse( &cSeatObjectId, &cSeatId );
+  uint32_t tNowTime = GameServer->GetGameTime();
+  bool ReadyToExit = false;
+
+  // This is only for investigation on subway timing
+  if ( nClient->GetDebugMode( DBG_SUBWAY ) && ( cSeatType == seat_subway ) )
+  {
+    char DbgMessage[80];
+    uint8_t tCabId;
+    Subway->GetInfoIndex( cSeatObjectId, &tCabId );
+    uint8_t tStationId = Subway->GetStation( cSeatObjectId, tNowTime );
+    std::string* StationName = Subway->GetStationName( tStationId );
+    std::string OpenState = ( Subway->IsDoorOpen( cSeatObjectId, tNowTime ) ? "open" : "closed" );
+
+    snprintf( DbgMessage, 80, "Cab %d (%d) is in station %s (%d). Door is %s (time: %d)", tCabId, cSeatObjectId, StationName->c_str(), tStationId, OpenState.c_str(), tNowTime );
+    DbgMessage[79] = 0;
+    Chat->send( nClient, CHAT_DIRECT, "System", DbgMessage );
+    delete StationName;
+  }
+  // end investigation
+
+  if ( cSeatType )
+  {
+    PWorld* tWorld = Worlds->GetWorld( nChar->GetLocation() );
+
+    if ( cSeatType == seat_chair )
+    {
+      tWorld->CharLeaveChair( nClient->GetLocalID(), cSeatObjectId );
+      nChar->SetSeatInUse( seat_none );
+      ReadyToExit = true;
+    }
+    else if ( cSeatType == seat_subway )
+    {
+      if ( Subway->IsDoorOpen( cSeatObjectId, tNowTime ) || nForce )
+      {
+        Subway->GetStationExitPosition( &( nChar->Coords ), Subway->GetStation( cSeatObjectId, tNowTime ), GetRandomFloat() );
+        Subway->UnsetSeatUser( cSeatObjectId, cSeatId, nChar->GetID() );
+        nChar->SetSeatInUse( seat_none );
+        ReadyToExit = true;
+      }
+      else
+      {
+        tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, cSeatObjectId ); // "Damn, locked"
+        nClient->SendUDPMessage( tmpMsg );
+      }
+    }
+    else if ( cSeatType == seat_vhc )
+    {
+      PSpawnedVehicle* tVhc = tWorld->GetSpawnedVehicles()->GetVehicle( cSeatObjectId );
+      if ( tVhc && (!nVhc || (tVhc == nVhc) || nForce) )
+      {
+        PVhcCoordinates tCoords = tVhc->GetPosition();
+        tVhc->UnsetSeatUser( cSeatId, nChar->GetID() );
+        nChar->SetSeatInUse( seat_none );
+        nChar->Coords.SetPosition( tCoords.GetY(), tCoords.GetZ(), tCoords.GetX() ); // to complete with LR
+        ReadyToExit = true;
+      }
+    }
+    else
+    {
+      Console->Print( "%s PUdpCharExitChair::DoLeaveChair : Invalid seat type %d", Console->ColorText( RED, BLACK, "[ERROR]" ), cSeatType );
+    }
+
+    if ( ReadyToExit )
+    {
+      nChar->SetSeatInUse( seat_none );
+
+      tmpMsg = MsgBuilder->BuildCharExitSeatMsg( nClient );
+      ClientManager->UDPBroadcast( tmpMsg, nClient );
+
+      if ( gDevDebug ) Console->Print( "%s Localchar %d get up from chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nClient->GetLocalID(), cSeatObjectId );
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/**** PUdpCharJump ****/
+
+PUdpCharJump::PUdpCharJump( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x02";
+}
+
+PUdpMsgAnalyser* PUdpCharJump::Analyse()
+{
+  mDecodeData->mName << "=Char jumping";
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+
+  return this;
+}
+
+bool PUdpCharJump::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* nChar = nClient->GetChar();
+
+  if( nChar->Coords.mAct & 0xd8 ) // if moving, don't jump now and wait next update
+  {
+    nChar->Coords.mJumpingState = 1; // Jump pending. Do at next pos update
+    if ( gDevDebug ) Console->Print( "%s Prepare moving jump", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+  }
+  else // If not moving, jump now
+  {
+    if ( gDevDebug ) Console->Print( "%s Send static jump", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    uint8_t mInfoBitfield = 0x22; // Update Z and Act only
+    uint16_t nSaveZ = nChar->Coords.mZ;
+    (nChar->Coords.mZ) += JUMPHEIGHT;
+    PMessage* tmpMsg = MsgBuilder->BuildCharPosUpdate2Msg( nClient, mInfoBitfield );
+    nChar->Coords.mZ = nSaveZ;
+    nChar->Coords.mJumpingState = 2; // Jump done
+    ClientManager->UDPBroadcast( tmpMsg, nClient, 5000, true );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+
+  return true;
+}
+
+
+/**** PUdpCharTargeting ****/
+
+PUdpCharTargeting::PUdpCharTargeting( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x2d";
+}
+
+PUdpMsgAnalyser* PUdpCharTargeting::Analyse()
+{
+  mDecodeData->mName << "=Targeting char";
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+
+  return this;
+}
+
+bool PUdpCharTargeting::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* tChar = nClient->GetChar();
+  uint16_t CharID = mDecodeData->mMessage->U16Data( mDecodeData->Sub0x13Start + 2 );
+  uint8_t strangeval1 = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 4 );
+  uint8_t strangeval2 = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 5 );
+  uint8_t strangeval3 = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 6 );
+
+  tChar->SetLookingAt( CharID );
+
+  if ( gDevDebug )
+    Console->Print( "%s Char %d targeting char %d. // %d %d %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetID(), CharID, strangeval1, strangeval2, strangeval3 );
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
index e0cc96e..c849af6 100644 (file)
@@ -1,56 +1,56 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PChar;\r
-class PClient;\r
-class PSpawnedVehicle;\r
-\r
-class PUdpCharPosUpdate : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mInfoBitfield;\r
-    uint16_t mNewY;\r
-    uint16_t mNewZ;\r
-    uint16_t mNewX;\r
-    uint8_t mNewUD;\r
-    uint8_t mNewLR;\r
-    uint8_t mNewAct;\r
-    uint8_t mNewUnknown;\r
-    uint32_t mChairItemID; // uint16_t or uint32_t ???\r
-    uint8_t mChairItemSeat;\r
-\r
-public:\r
-    PUdpCharPosUpdate(PMsgDecodeData *nDecodeData);\r
-    //~PUdpCharMoves();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpCharExitChair : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpCharExitChair(PMsgDecodeData *nDecodeData);\r
-    //~PUdpCharExitChair();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-\r
-    //nClient is optionnal, nVhc is to limit to that vhc, nForce to force exit event when cab door closed\r
-    static bool DoLeaveChair(PChar *nChar, PClient *nClient = nullptr, PSpawnedVehicle *nVhc = nullptr,\r
-                             bool nForce = false);\r
-};\r
-\r
-class PUdpCharJump : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpCharJump(PMsgDecodeData *nDecodeData);\r
-    //~PUdpCharJump();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpCharTargeting : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpCharTargeting(PMsgDecodeData *nDecodeData);\r
-    //~PUdpCharTargeting();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PChar;
+class PClient;
+class PSpawnedVehicle;
+
+class PUdpCharPosUpdate : public PUdpMsgAnalyser {
+private:
+    uint8_t mInfoBitfield;
+    uint16_t mNewY;
+    uint16_t mNewZ;
+    uint16_t mNewX;
+    uint8_t mNewUD;
+    uint8_t mNewLR;
+    uint8_t mNewAct;
+    uint8_t mNewUnknown;
+    uint32_t mChairItemID; // uint16_t or uint32_t ???
+    uint8_t mChairItemSeat;
+
+public:
+    PUdpCharPosUpdate(PMsgDecodeData *nDecodeData);
+    //~PUdpCharMoves();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpCharExitChair : public PUdpMsgAnalyser {
+public:
+    PUdpCharExitChair(PMsgDecodeData *nDecodeData);
+    //~PUdpCharExitChair();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+
+    //nClient is optionnal, nVhc is to limit to that vhc, nForce to force exit event when cab door closed
+    static bool DoLeaveChair(PChar *nChar, PClient *nClient = nullptr, PSpawnedVehicle *nVhc = nullptr,
+                             bool nForce = false);
+};
+
+class PUdpCharJump : public PUdpMsgAnalyser {
+public:
+    PUdpCharJump(PMsgDecodeData *nDecodeData);
+    //~PUdpCharJump();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpCharTargeting : public PUdpMsgAnalyser {
+public:
+    PUdpCharTargeting(PMsgDecodeData *nDecodeData);
+    //~PUdpCharTargeting();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 5abf6d8..f16bd01 100644 (file)
@@ -1,55 +1,55 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpChatLocal : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpChatLocal(PMsgDecodeData *nDecodeData);\r
-    //~PUdpChatLocal();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpChatGlobal : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpChatGlobal(PMsgDecodeData *nDecodeData);\r
-    //~PUdpChatGlobal();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpChatListAdd : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mChatList; // 1 = Direct, 2 = Buddy List\r
-    char *mAddedCharname;\r
-\r
-public:\r
-    PUdpChatListAdd(PMsgDecodeData *nDecodeData);\r
-    //~PUdpChatListAdd();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpChatListRemove : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mChatList;\r
-    uint32_t mRemovedCharID;\r
-\r
-public:\r
-    PUdpChatListRemove(PMsgDecodeData *nDecodeData);\r
-    //~PUdpChatListRemove();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpChatChannels : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mChannelFlags; // 1 bit per custom channel, starting from LSB, in same order as in chat i/f\r
-\r
-public:\r
-    PUdpChatChannels(PMsgDecodeData *nDecodeData);\r
-    //~PUdpChatChannels();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpChatLocal : public PUdpMsgAnalyser {
+public:
+    PUdpChatLocal(PMsgDecodeData *nDecodeData);
+    //~PUdpChatLocal();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpChatGlobal : public PUdpMsgAnalyser {
+public:
+    PUdpChatGlobal(PMsgDecodeData *nDecodeData);
+    //~PUdpChatGlobal();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpChatListAdd : public PUdpMsgAnalyser {
+private:
+    uint8_t mChatList; // 1 = Direct, 2 = Buddy List
+    char *mAddedCharname;
+
+public:
+    PUdpChatListAdd(PMsgDecodeData *nDecodeData);
+    //~PUdpChatListAdd();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpChatListRemove : public PUdpMsgAnalyser {
+private:
+    uint8_t mChatList;
+    uint32_t mRemovedCharID;
+
+public:
+    PUdpChatListRemove(PMsgDecodeData *nDecodeData);
+    //~PUdpChatListRemove();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpChatChannels : public PUdpMsgAnalyser {
+private:
+    uint32_t mChannelFlags; // 1 bit per custom channel, starting from LSB, in same order as in chat i/f
+
+public:
+    PUdpChatChannels(PMsgDecodeData *nDecodeData);
+    //~PUdpChatChannels();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 4c17db7..5e2c629 100644 (file)
@@ -1,76 +1,76 @@
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PUdpEntityPosRequest::PUdpEntityPosRequest(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  nDecodeData->mName << "/0x0b";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpEntityPosRequest::Analyse()\r
-{\r
-  mDecodeData->mName << "=Entity position request";\r
-\r
-//mDecodeData->mTraceUnknownMsg = true; // temp stop being bugged with unknown move msg\r
-//mDecodeData->mTraceKnownMsg = true;\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset(mDecodeData->Sub0x13Start + 7);\r
-\r
-  *nMsg >> mEntityID; //(uint16_t ... or uint32_t ???)\r
-\r
-  if(mEntityID >= WORLDDATATEMPLATE_MAXPOSITEMS)\r
-  {\r
-    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-    mDecodeData->mErrorDetail = Ssprintf("Invalid position entity ID (%d)", mEntityID);\r
-    Console->Print("%s Client[%d] sent invalid position entity Id[%d]", Console->ColorText(YELLOW, BLACK, "[Notice]"), mDecodeData->mClient->GetID(), mEntityID);\r
-    mDecodeData->mTraceDump = true;\r
-  }\r
-  else\r
-  {\r
-    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  }\r
-\r
-  return this;\r
-}\r
-\r
-bool PUdpEntityPosRequest::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* nChar = nClient->GetChar();\r
-  PWorld* currentWorld = Worlds->GetWorld(nChar->GetLocation());\r
-  float fpX, fpY, fpZ;\r
-  uint16_t pX, pY, pZ;\r
-\r
-  if(currentWorld)\r
-  {\r
-    if((mEntityID < WORLDDATATEMPLATE_MAXPOSITEMS) && currentWorld->getPositionItemPosition(mEntityID, &fpX, &fpY, &fpZ))\r
-    {\r
-      pX = (uint16_t) (fpX + 32000);\r
-      pY = (uint16_t) (fpY + 32000);\r
-      pZ = (uint16_t) (fpZ + 32000);\r
-\r
-if(gDevDebug) Console->Print(GREEN, BLACK, "Client %d - Sending pos for entity %d : X=%d Y=%d Z=%d", mDecodeData->mClient->GetID(), mEntityID, pX, pY, pZ);\r
-    }\r
-    else if(!nClient->GetCharAwaitingWarpto(&pX, &pY, &pZ))\r
-    {\r
-      pX = pY = pZ = 0;\r
-      Console->Print("%s Client[%d] requested invalid position entity %d. Position reset.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mDecodeData->mClient->GetID(), mEntityID);\r
-    }\r
-\r
-    PMessage* tmpMsg;\r
-    tmpMsg = MsgBuilder->BuildEntityPositionMsg(nClient, pX, pY, pZ);\r
-    nClient->SendUDPMessage(tmpMsg);\r
-    (nChar->Coords).mY=pY;\r
-    (nChar->Coords).mZ=pZ;\r
-    (nChar->Coords).mX=pX;\r
-  }\r
-  else\r
-  {\r
-    Console->Print(RED, BLACK, "[Warning] PUdpEntityPosRequest - Invalid world (%d)", nChar->GetLocation());\r
-  }\r
-//    if(IsRealMove && nClient->GetDebugMode(DBG_LOCATION))\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PUdpEntityPosRequest::PUdpEntityPosRequest(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  nDecodeData->mName << "/0x0b";
+}
+
+PUdpMsgAnalyser* PUdpEntityPosRequest::Analyse()
+{
+  mDecodeData->mName << "=Entity position request";
+
+//mDecodeData->mTraceUnknownMsg = true; // temp stop being bugged with unknown move msg
+//mDecodeData->mTraceKnownMsg = true;
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset(mDecodeData->Sub0x13Start + 7);
+
+  *nMsg >> mEntityID; //(uint16_t ... or uint32_t ???)
+
+  if(mEntityID >= WORLDDATATEMPLATE_MAXPOSITEMS)
+  {
+    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+    mDecodeData->mErrorDetail = Ssprintf("Invalid position entity ID (%d)", mEntityID);
+    Console->Print("%s Client[%d] sent invalid position entity Id[%d]", Console->ColorText(YELLOW, BLACK, "[Notice]"), mDecodeData->mClient->GetID(), mEntityID);
+    mDecodeData->mTraceDump = true;
+  }
+  else
+  {
+    mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  }
+
+  return this;
+}
+
+bool PUdpEntityPosRequest::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* nChar = nClient->GetChar();
+  PWorld* currentWorld = Worlds->GetWorld(nChar->GetLocation());
+  float fpX, fpY, fpZ;
+  uint16_t pX, pY, pZ;
+
+  if(currentWorld)
+  {
+    if((mEntityID < WORLDDATATEMPLATE_MAXPOSITEMS) && currentWorld->getPositionItemPosition(mEntityID, &fpX, &fpY, &fpZ))
+    {
+      pX = (uint16_t) (fpX + 32000);
+      pY = (uint16_t) (fpY + 32000);
+      pZ = (uint16_t) (fpZ + 32000);
+
+if(gDevDebug) Console->Print(GREEN, BLACK, "Client %d - Sending pos for entity %d : X=%d Y=%d Z=%d", mDecodeData->mClient->GetID(), mEntityID, pX, pY, pZ);
+    }
+    else if(!nClient->GetCharAwaitingWarpto(&pX, &pY, &pZ))
+    {
+      pX = pY = pZ = 0;
+      Console->Print("%s Client[%d] requested invalid position entity %d. Position reset.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mDecodeData->mClient->GetID(), mEntityID);
+    }
+
+    PMessage* tmpMsg;
+    tmpMsg = MsgBuilder->BuildEntityPositionMsg(nClient, pX, pY, pZ);
+    nClient->SendUDPMessage(tmpMsg);
+    (nChar->Coords).mY=pY;
+    (nChar->Coords).mZ=pZ;
+    (nChar->Coords).mX=pX;
+  }
+  else
+  {
+    Console->Print(RED, BLACK, "[Warning] PUdpEntityPosRequest - Invalid world (%d)", nChar->GetLocation());
+  }
+//    if(IsRealMove && nClient->GetDebugMode(DBG_LOCATION))
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
index a483d36..7a50a76 100644 (file)
@@ -1,15 +1,15 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpEntityPosRequest : public PUdpMsgAnalyser {\r
-private:\r
-    uint16_t mEntityID; // u16 or u32 ???\r
-\r
-public:\r
-    PUdpEntityPosRequest(PMsgDecodeData *nDecodeData);\r
-    //~PUdpEntityPosRequest();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpEntityPosRequest : public PUdpMsgAnalyser {
+private:
+    uint16_t mEntityID; // u16 or u32 ???
+
+public:
+    PUdpEntityPosRequest(PMsgDecodeData *nDecodeData);
+    //~PUdpEntityPosRequest();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index bf8eccb..0d79ee3 100644 (file)
@@ -1,19 +1,19 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpHackFail : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpHackFail(PMsgDecodeData *nDecodeData);\r
-    //~PUdpHackFail();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpHackSuccess : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpHackSuccess(PMsgDecodeData *nDecodeData);\r
-    //~PUdpHackSuccess();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpHackFail : public PUdpMsgAnalyser {
+public:
+    PUdpHackFail(PMsgDecodeData *nDecodeData);
+    //~PUdpHackFail();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpHackSuccess : public PUdpMsgAnalyser {
+public:
+    PUdpHackSuccess(PMsgDecodeData *nDecodeData);
+    //~PUdpHackSuccess();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index bd868ad..4ef1208 100644 (file)
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdpItemMove ****/\r
-\r
-#define PUdpItemMove_NO_BOX_TAKE_ALL\r
-\r
-PUdpItemMove::PUdpItemMove( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x1e";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpItemMove::Analyse()\r
-{\r
-  mDecodeData->mName << "=Moving item";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 8 );\r
-\r
-  *nMsg >> mSrcLoc;\r
-  *nMsg >> mSrcX;\r
-  *nMsg >> mSrcY;\r
-  *nMsg >> mDstLoc;\r
-  *nMsg >> mDstX;\r
-  *nMsg >> mDstY;\r
-  *nMsg >> mItemCnt;\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpItemMove::DoAction()\r
-{\r
-//mDecodeData->mTraceDump = true;\r
-  PMessage* tmpMsg;\r
-  bool MoveSucceded = false;\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* tChar = nClient->GetChar();\r
-  uint8_t origDstX = mDstX;\r
-  uint8_t origDstY = mDstY;\r
-  PContainerEntry* tEntry;\r
-\r
-  PItem* tItem = NULL;\r
-\r
-  PContainer* SrcContainer = GetContainerByLoc( tChar, mSrcLoc );\r
-  if ( SrcContainer )\r
-  {\r
-    tEntry = SrcContainer->GetEntry( mSrcX );\r
-    tItem = SrcContainer->GetItem( mSrcX );\r
-    if ( mSrcLoc != mDstLoc )\r
-    {\r
-      PContainer* DstContainer = GetContainerByLoc( tChar, mDstLoc );\r
-      if ( mSrcY )\r
-        Console->Print( "%s PUdpItemMove: intramove: src Y != 0", Console->ColorText( YELLOW, BLACK, "[WARNING]" ) );\r
-#ifdef PUdpItemMove_NO_BOX_TAKE_ALL\r
-      if (( mSrcLoc != INV_LOC_BOX ) || ( mDstX != 255 ) || ( mDstY != 255 ) )\r
-      {\r
-#endif\r
-        if ( DstContainer )\r
-        {\r
-          //PContainerEntry* tEntry = SrcContainer->GetEntry(mSrcX);\r
-          MoveSucceded = SrcContainer->MoveItem( mSrcX, mItemCnt, DstContainer, mDstX, mDstX, mDstY );\r
-          /*if(tEntry)\r
-            tEntry->Get2DPos(&mDstX, &mDstY);*/\r
-        }\r
-#ifdef PUdpItemMove_NO_BOX_TAKE_ALL\r
-      }\r
-#endif\r
-    }\r
-    else\r
-    {\r
-      if ( mSrcY || mDstY )\r
-        Console->Print( "%s PUdpItemMove: intramove: src Y or dst Y != 0", Console->ColorText( YELLOW, BLACK, "[WARNING]" ) );\r
-      MoveSucceded = SrcContainer->MoveItem( mSrcX, mItemCnt, mDstX );\r
-    }\r
-  }\r
-\r
-  if ( MoveSucceded )\r
-  {\r
-    if (( mDstX == 255 ) && ( mDstY == 255 ) && ( mSrcLoc == INV_LOC_BOX ) )\r
-    {\r
-      tmpMsg = MsgBuilder->BuildUndefineduseMsg( nClient, 0x2c );\r
-      nClient->SendUDPMessage( tmpMsg );\r
-      tmpMsg = MsgBuilder->BuildBoxItemMoveMsg( nClient, tEntry, mSrcX, mSrcY, mDstLoc, mDstX, mDstY, mItemCnt );\r
-    }\r
-    else\r
-    {\r
-      tmpMsg = MsgBuilder->BuildItemMoveMsg( nClient, mSrcLoc, mSrcX, mSrcY, mDstLoc, mDstX, mDstY, mItemCnt );\r
-    }\r
-    nClient->SendUDPMessage( tmpMsg );\r
-\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Success : Item move %u:%u-%u => %u:%u-%u : %u %s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mSrcLoc, mSrcX, mSrcY, mDstLoc, origDstX, origDstY, mItemCnt, tItem ? tItem->GetName().c_str() : "" );\r
-    /*Console->Print(YELLOW, BLACK, "--- Worn Inventory ---");\r
-    tChar->GetInventory()->GetContainer(INV_LOC_WORN)->Dump();\r
-    Console->Print(YELLOW, BLACK, "--- Backpack Inventory ---");\r
-    tChar->GetInventory()->GetContainer(INV_LOC_BACKPACK)->Dump();\r
-    Console->Print(YELLOW, BLACK, "--- Gogo Inventory ---");\r
-    tChar->GetInventory()->GetContainer(INV_LOC_GOGO)->Dump();\r
-    if (tChar->GetInventory()->IsDirty())\r
-      Console->Print(YELLOW, BLACK, "Inventory DIRTY"); */\r
-\r
-// => TO CHECK: deactivate item in-hand if active slot now emtpy ???\r
-  }\r
-  else\r
-  {\r
-#ifdef PUdpItemMove_NO_BOX_TAKE_ALL\r
-    if (( mSrcLoc != INV_LOC_BOX ) || ( mDstX != 255 ) || ( mDstY != 255 ) )\r
-    {\r
-#endif\r
-      if ( mDstLoc == INV_LOC_GROUND )\r
-        Chat->send( nClient, CHAT_DIRECT, "System", "Can't throw items to the ground yet." );\r
-      else\r
-        Console->Print( "%s Item move failed %u:%u-%u => %u:%u-%u : %u %s", Console->ColorText( YELLOW, BLACK, "[WARNING]" ), mSrcLoc, mSrcX, mSrcY, mDstLoc, origDstX, origDstY, mItemCnt, tItem ? tItem->GetName().c_str() : "" );\r
-      // Send 'null move'\r
-      //tmpMsg = MsgBuilder->BuildItemMoveMsg(nClient, mSrcLoc, mSrcX, mSrcY, mSrcLoc, mSrcX, mSrcY, mItemCnt);\r
-      //nClient->SendUDPMessage(tmpMsg);\r
-#ifdef PUdpItemMove_NO_BOX_TAKE_ALL\r
-    }\r
-    else\r
-    {\r
-      Chat->send( nClient, CHAT_DIRECT, "System", "'TAKE ALL' can't be used yet." );\r
-    }\r
-#endif\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-PContainer* PUdpItemMove::GetContainerByLoc( PChar* nChar, uint8_t nLoc )\r
-{\r
-  PContainer* tContainer = NULL;\r
-\r
-  switch ( nLoc )\r
-  {\r
-    case INV_LOC_WORN:\r
-    case INV_LOC_BACKPACK:\r
-    case INV_LOC_GOGO:\r
-      {\r
-        tContainer = nChar->GetInventory()->GetContainer( nLoc );\r
-        break;\r
-      }\r
-\r
-    case INV_LOC_BOX:\r
-      {\r
-        tContainer = nChar->GetContainerInExclusiveUse();\r
-        break;\r
-      }\r
-    case INV_LOC_GROUND:\r
-    case INV_LOC_NPCTRADE:\r
-    default:\r
-      break;\r
-  }\r
-\r
-  return tContainer;\r
-}\r
-\r
-\r
-/**** PUdpItemMoveBP ****/\r
-\r
-PUdpItemMoveBP::PUdpItemMoveBP( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x14";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpItemMoveBP::Analyse()\r
-{\r
-  mDecodeData->mName << "=Moving item";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 9 );\r
-\r
-  *nMsg >> mSrcSlotId;\r
-  *nMsg >> mDumb;\r
-  *nMsg >> mDstX;\r
-  *nMsg >> mDstY;\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpItemMoveBP::DoAction()\r
-{\r
-//mDecodeData->mTraceDump = true;\r
-//  PMessage* tmpMsg;\r
-  bool MoveSucceded = false;\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* tChar = nClient->GetChar();\r
-\r
-  PContainer2DWorkaround* SrcContainer = tChar->GetInventory()->GetBackpackContainer();\r
-  if ( SrcContainer )\r
-  {\r
-    if ( mDumb )\r
-      Console->Print( "%s PUdpItemMoveBP: Dumb != 0 (%d)", Console->ColorText( YELLOW, BLACK, "[WARNING]" ), mDumb );\r
-    if ( gDevDebug )\r
-      Console->Print( "%s PUdpItemMoveBP: Tyring Item move: slot %u => %u-%u", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mSrcSlotId, mDstX, mDstY );\r
-    PContainerEntry* tEntry = SrcContainer->GetEntry( mSrcSlotId );\r
-    if ( tEntry )\r
-    {\r
-      SrcContainer->SetUsed( tEntry, false );\r
-      SrcContainer->SetEntryPosXY( tEntry, mSrcSlotId, mDstX, mDstY );\r
-      SrcContainer->SetUsed( tEntry );\r
-      SrcContainer->SetDirty();\r
-      MoveSucceded = true;\r
-    }\r
-    else\r
-      Console->Print( "%s PUdpItemMoveBP: trying to use invalid slot %d", Console->ColorText( RED, BLACK, "[WARNING]" ), mSrcSlotId );\r
-  }\r
-  else\r
-  {\r
-    Console->Print( "%s trying to use invalid Backpack container", Console->ColorText( RED, BLACK, "[WARNING]" ) );\r
-  }\r
-//Console->Print(YELLOW, BLACK, "--- Backpack Inventory ---");\r
-//SrcContainer->Dump();\r
-\r
-// No answer to confirm ?\r
-//tmpMsg = NULL;\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-/**** PUdpItemDropOnItem ****/\r
-\r
-PUdpItemDropOnItem::PUdpItemDropOnItem( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x17";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpItemDropOnItem::Analyse()\r
-{\r
-  mDecodeData->mName << "=Dropping item on item";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 9 );\r
-\r
-  *nMsg >> mSrcLoc;\r
-  *nMsg >> mSrcX; // Linear Idx\r
-  *nMsg >> mSrcY; // 0\r
-  *nMsg >> mDstLoc;\r
-  *nMsg >> mDstX; // Linear Idx\r
-  *nMsg >> mDstY; // 0\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpItemDropOnItem::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* tChar = nClient->GetChar();\r
-  if ( gDevDebug )\r
-    Console->Print( "%s PUdpItemDropOnItem: %u:%u-%u => %u:%u-%u", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mSrcLoc, mSrcX, mSrcY, mDstLoc, mDstX, mDstY );\r
-  PContainer* SrcContainer = PUdpItemMove::GetContainerByLoc( tChar, mSrcLoc );\r
-  PContainer* DstContainer = PUdpItemMove::GetContainerByLoc( tChar, mDstLoc );\r
-  if ( SrcContainer && DstContainer )\r
-  {\r
-    PItem* sItem = SrcContainer->GetItem( mSrcX );\r
-    PItem* dItem = DstContainer->GetItem( mDstX );\r
-\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Drop item %s on %s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), sItem ? sItem->GetName().c_str() : "???", dItem ? dItem->GetName().c_str() : "???" );\r
-  }\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdpItemMove ****/
+
+#define PUdpItemMove_NO_BOX_TAKE_ALL
+
+PUdpItemMove::PUdpItemMove( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x1e";
+}
+
+PUdpMsgAnalyser* PUdpItemMove::Analyse()
+{
+  mDecodeData->mName << "=Moving item";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 8 );
+
+  *nMsg >> mSrcLoc;
+  *nMsg >> mSrcX;
+  *nMsg >> mSrcY;
+  *nMsg >> mDstLoc;
+  *nMsg >> mDstX;
+  *nMsg >> mDstY;
+  *nMsg >> mItemCnt;
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpItemMove::DoAction()
+{
+//mDecodeData->mTraceDump = true;
+  PMessage* tmpMsg;
+  bool MoveSucceded = false;
+  PClient* nClient = mDecodeData->mClient;
+  PChar* tChar = nClient->GetChar();
+  uint8_t origDstX = mDstX;
+  uint8_t origDstY = mDstY;
+  PContainerEntry* tEntry;
+
+  PItem* tItem = NULL;
+
+  PContainer* SrcContainer = GetContainerByLoc( tChar, mSrcLoc );
+  if ( SrcContainer )
+  {
+    tEntry = SrcContainer->GetEntry( mSrcX );
+    tItem = SrcContainer->GetItem( mSrcX );
+    if ( mSrcLoc != mDstLoc )
+    {
+      PContainer* DstContainer = GetContainerByLoc( tChar, mDstLoc );
+      if ( mSrcY )
+        Console->Print( "%s PUdpItemMove: intramove: src Y != 0", Console->ColorText( YELLOW, BLACK, "[WARNING]" ) );
+#ifdef PUdpItemMove_NO_BOX_TAKE_ALL
+      if (( mSrcLoc != INV_LOC_BOX ) || ( mDstX != 255 ) || ( mDstY != 255 ) )
+      {
+#endif
+        if ( DstContainer )
+        {
+          //PContainerEntry* tEntry = SrcContainer->GetEntry(mSrcX);
+          MoveSucceded = SrcContainer->MoveItem( mSrcX, mItemCnt, DstContainer, mDstX, mDstX, mDstY );
+          /*if(tEntry)
+            tEntry->Get2DPos(&mDstX, &mDstY);*/
+        }
+#ifdef PUdpItemMove_NO_BOX_TAKE_ALL
+      }
+#endif
+    }
+    else
+    {
+      if ( mSrcY || mDstY )
+        Console->Print( "%s PUdpItemMove: intramove: src Y or dst Y != 0", Console->ColorText( YELLOW, BLACK, "[WARNING]" ) );
+      MoveSucceded = SrcContainer->MoveItem( mSrcX, mItemCnt, mDstX );
+    }
+  }
+
+  if ( MoveSucceded )
+  {
+    if (( mDstX == 255 ) && ( mDstY == 255 ) && ( mSrcLoc == INV_LOC_BOX ) )
+    {
+      tmpMsg = MsgBuilder->BuildUndefineduseMsg( nClient, 0x2c );
+      nClient->SendUDPMessage( tmpMsg );
+      tmpMsg = MsgBuilder->BuildBoxItemMoveMsg( nClient, tEntry, mSrcX, mSrcY, mDstLoc, mDstX, mDstY, mItemCnt );
+    }
+    else
+    {
+      tmpMsg = MsgBuilder->BuildItemMoveMsg( nClient, mSrcLoc, mSrcX, mSrcY, mDstLoc, mDstX, mDstY, mItemCnt );
+    }
+    nClient->SendUDPMessage( tmpMsg );
+
+    if ( gDevDebug )
+      Console->Print( "%s Success : Item move %u:%u-%u => %u:%u-%u : %u %s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mSrcLoc, mSrcX, mSrcY, mDstLoc, origDstX, origDstY, mItemCnt, tItem ? tItem->GetName().c_str() : "" );
+    /*Console->Print(YELLOW, BLACK, "--- Worn Inventory ---");
+    tChar->GetInventory()->GetContainer(INV_LOC_WORN)->Dump();
+    Console->Print(YELLOW, BLACK, "--- Backpack Inventory ---");
+    tChar->GetInventory()->GetContainer(INV_LOC_BACKPACK)->Dump();
+    Console->Print(YELLOW, BLACK, "--- Gogo Inventory ---");
+    tChar->GetInventory()->GetContainer(INV_LOC_GOGO)->Dump();
+    if (tChar->GetInventory()->IsDirty())
+      Console->Print(YELLOW, BLACK, "Inventory DIRTY"); */
+
+// => TO CHECK: deactivate item in-hand if active slot now emtpy ???
+  }
+  else
+  {
+#ifdef PUdpItemMove_NO_BOX_TAKE_ALL
+    if (( mSrcLoc != INV_LOC_BOX ) || ( mDstX != 255 ) || ( mDstY != 255 ) )
+    {
+#endif
+      if ( mDstLoc == INV_LOC_GROUND )
+        Chat->send( nClient, CHAT_DIRECT, "System", "Can't throw items to the ground yet." );
+      else
+        Console->Print( "%s Item move failed %u:%u-%u => %u:%u-%u : %u %s", Console->ColorText( YELLOW, BLACK, "[WARNING]" ), mSrcLoc, mSrcX, mSrcY, mDstLoc, origDstX, origDstY, mItemCnt, tItem ? tItem->GetName().c_str() : "" );
+      // Send 'null move'
+      //tmpMsg = MsgBuilder->BuildItemMoveMsg(nClient, mSrcLoc, mSrcX, mSrcY, mSrcLoc, mSrcX, mSrcY, mItemCnt);
+      //nClient->SendUDPMessage(tmpMsg);
+#ifdef PUdpItemMove_NO_BOX_TAKE_ALL
+    }
+    else
+    {
+      Chat->send( nClient, CHAT_DIRECT, "System", "'TAKE ALL' can't be used yet." );
+    }
+#endif
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+PContainer* PUdpItemMove::GetContainerByLoc( PChar* nChar, uint8_t nLoc )
+{
+  PContainer* tContainer = NULL;
+
+  switch ( nLoc )
+  {
+    case INV_LOC_WORN:
+    case INV_LOC_BACKPACK:
+    case INV_LOC_GOGO:
+      {
+        tContainer = nChar->GetInventory()->GetContainer( nLoc );
+        break;
+      }
+
+    case INV_LOC_BOX:
+      {
+        tContainer = nChar->GetContainerInExclusiveUse();
+        break;
+      }
+    case INV_LOC_GROUND:
+    case INV_LOC_NPCTRADE:
+    default:
+      break;
+  }
+
+  return tContainer;
+}
+
+
+/**** PUdpItemMoveBP ****/
+
+PUdpItemMoveBP::PUdpItemMoveBP( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x14";
+}
+
+PUdpMsgAnalyser* PUdpItemMoveBP::Analyse()
+{
+  mDecodeData->mName << "=Moving item";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 9 );
+
+  *nMsg >> mSrcSlotId;
+  *nMsg >> mDumb;
+  *nMsg >> mDstX;
+  *nMsg >> mDstY;
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpItemMoveBP::DoAction()
+{
+//mDecodeData->mTraceDump = true;
+//  PMessage* tmpMsg;
+  bool MoveSucceded = false;
+  PClient* nClient = mDecodeData->mClient;
+  PChar* tChar = nClient->GetChar();
+
+  PContainer2DWorkaround* SrcContainer = tChar->GetInventory()->GetBackpackContainer();
+  if ( SrcContainer )
+  {
+    if ( mDumb )
+      Console->Print( "%s PUdpItemMoveBP: Dumb != 0 (%d)", Console->ColorText( YELLOW, BLACK, "[WARNING]" ), mDumb );
+    if ( gDevDebug )
+      Console->Print( "%s PUdpItemMoveBP: Tyring Item move: slot %u => %u-%u", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mSrcSlotId, mDstX, mDstY );
+    PContainerEntry* tEntry = SrcContainer->GetEntry( mSrcSlotId );
+    if ( tEntry )
+    {
+      SrcContainer->SetUsed( tEntry, false );
+      SrcContainer->SetEntryPosXY( tEntry, mSrcSlotId, mDstX, mDstY );
+      SrcContainer->SetUsed( tEntry );
+      SrcContainer->SetDirty();
+      MoveSucceded = true;
+    }
+    else
+      Console->Print( "%s PUdpItemMoveBP: trying to use invalid slot %d", Console->ColorText( RED, BLACK, "[WARNING]" ), mSrcSlotId );
+  }
+  else
+  {
+    Console->Print( "%s trying to use invalid Backpack container", Console->ColorText( RED, BLACK, "[WARNING]" ) );
+  }
+//Console->Print(YELLOW, BLACK, "--- Backpack Inventory ---");
+//SrcContainer->Dump();
+
+// No answer to confirm ?
+//tmpMsg = NULL;
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+/**** PUdpItemDropOnItem ****/
+
+PUdpItemDropOnItem::PUdpItemDropOnItem( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x17";
+}
+
+PUdpMsgAnalyser* PUdpItemDropOnItem::Analyse()
+{
+  mDecodeData->mName << "=Dropping item on item";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 9 );
+
+  *nMsg >> mSrcLoc;
+  *nMsg >> mSrcX; // Linear Idx
+  *nMsg >> mSrcY; // 0
+  *nMsg >> mDstLoc;
+  *nMsg >> mDstX; // Linear Idx
+  *nMsg >> mDstY; // 0
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpItemDropOnItem::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* tChar = nClient->GetChar();
+  if ( gDevDebug )
+    Console->Print( "%s PUdpItemDropOnItem: %u:%u-%u => %u:%u-%u", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mSrcLoc, mSrcX, mSrcY, mDstLoc, mDstX, mDstY );
+  PContainer* SrcContainer = PUdpItemMove::GetContainerByLoc( tChar, mSrcLoc );
+  PContainer* DstContainer = PUdpItemMove::GetContainerByLoc( tChar, mDstLoc );
+  if ( SrcContainer && DstContainer )
+  {
+    PItem* sItem = SrcContainer->GetItem( mSrcX );
+    PItem* dItem = DstContainer->GetItem( mDstX );
+
+    if ( gDevDebug )
+      Console->Print( "%s Drop item %s on %s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), sItem ? sItem->GetName().c_str() : "???", dItem ? dItem->GetName().c_str() : "???" );
+  }
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
index 4cbd9cf..e19adab 100644 (file)
@@ -1,55 +1,55 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PContainer;\r
-\r
-class PUdpItemMove : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mSrcLoc;\r
-    uint8_t mSrcX;\r
-    uint8_t mSrcY;\r
-    uint8_t mDstLoc;\r
-    uint8_t mDstX;\r
-    uint8_t mDstY;\r
-    uint8_t mItemCnt;\r
-\r
-public:\r
-      PUdpItemMove(PMsgDecodeData *nDecodeData);\r
-      //~PUdpItemMove();\r
-      PUdpMsgAnalyser *Analyse();\r
-      bool DoAction();\r
-\r
-      static PContainer *GetContainerByLoc(PChar *nChar, uint8_t nLoc);\r
-};\r
-\r
-class PUdpItemMoveBP : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mSrcSlotId;\r
-    uint8_t mDumb;\r
-    uint8_t mDstX;\r
-    uint8_t mDstY;\r
-\r
-public:\r
-      PUdpItemMoveBP(PMsgDecodeData *nDecodeData);\r
-      //~PUdpItemMove();\r
-      PUdpMsgAnalyser *Analyse();\r
-      bool DoAction();\r
-};\r
-\r
-class PUdpItemDropOnItem : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mSrcLoc;\r
-    uint8_t mSrcX;\r
-    uint8_t mSrcY;\r
-    uint8_t mDstLoc;\r
-    uint8_t mDstX;\r
-    uint8_t mDstY;\r
-\r
-public:\r
-    PUdpItemDropOnItem(PMsgDecodeData *nDecodeData);\r
-    //~PUdpItemDropOnItem();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PContainer;
+
+class PUdpItemMove : public PUdpMsgAnalyser {
+private:
+    uint8_t mSrcLoc;
+    uint8_t mSrcX;
+    uint8_t mSrcY;
+    uint8_t mDstLoc;
+    uint8_t mDstX;
+    uint8_t mDstY;
+    uint8_t mItemCnt;
+
+public:
+      PUdpItemMove(PMsgDecodeData *nDecodeData);
+      //~PUdpItemMove();
+      PUdpMsgAnalyser *Analyse();
+      bool DoAction();
+
+      static PContainer *GetContainerByLoc(PChar *nChar, uint8_t nLoc);
+};
+
+class PUdpItemMoveBP : public PUdpMsgAnalyser {
+private:
+    uint8_t mSrcSlotId;
+    uint8_t mDumb;
+    uint8_t mDstX;
+    uint8_t mDstY;
+
+public:
+      PUdpItemMoveBP(PMsgDecodeData *nDecodeData);
+      //~PUdpItemMove();
+      PUdpMsgAnalyser *Analyse();
+      bool DoAction();
+};
+
+class PUdpItemDropOnItem : public PUdpMsgAnalyser {
+private:
+    uint8_t mSrcLoc;
+    uint8_t mSrcX;
+    uint8_t mSrcY;
+    uint8_t mDstLoc;
+    uint8_t mDstX;
+    uint8_t mDstY;
+
+public:
+    PUdpItemDropOnItem(PMsgDecodeData *nDecodeData);
+    //~PUdpItemDropOnItem();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 5be7d73..7012fc5 100644 (file)
@@ -1,29 +1,29 @@
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdpOOO ****/\r
-\r
-PUdpOOO::PUdpOOO(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)\r
-{\r
-  nDecodeData->mName << "/0x01";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpOOO::Analyse()\r
-{\r
-  mDecodeData->mName << "=Out Of Order";\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-\r
-  return this;\r
-}\r
-\r
-bool PUdpOOO::DoAction()\r
-{\r
-    uint16_t MissingUDP_ID = mDecodeData->mMessage->U16Data(mDecodeData->Sub0x13Start+5);\r
-\r
-    mDecodeData->mClient->getUDPConn()->ReSendUDPMessage(MissingUDP_ID);\r
-    //Console->Print("%s Out of Order packet received ! (Client is missing UDPID %d) ***not managed yet***", Console->ColorText(YELLOW, BLACK, "[Notice]"), MissingUDP_ID);\r
-\r
-    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-    return true;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdpOOO ****/
+
+PUdpOOO::PUdpOOO(PMsgDecodeData* nDecodeData) : PUdpMsgAnalyser(nDecodeData)
+{
+  nDecodeData->mName << "/0x01";
+}
+
+PUdpMsgAnalyser* PUdpOOO::Analyse()
+{
+  mDecodeData->mName << "=Out Of Order";
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+
+  return this;
+}
+
+bool PUdpOOO::DoAction()
+{
+    uint16_t MissingUDP_ID = mDecodeData->mMessage->U16Data(mDecodeData->Sub0x13Start+5);
+
+    mDecodeData->mClient->getUDPConn()->ReSendUDPMessage(MissingUDP_ID);
+    //Console->Print("%s Out of Order packet received ! (Client is missing UDPID %d) ***not managed yet***", Console->ColorText(YELLOW, BLACK, "[Notice]"), MissingUDP_ID);
+
+    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+    return true;
+}
index 89c759c..edf0b02 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpOOO : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpOOO(PMsgDecodeData *nDecodeData);\r
-    //~PUdpPing();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpOOO : public PUdpMsgAnalyser {
+public:
+    PUdpOOO(PMsgDecodeData *nDecodeData);
+    //~PUdpPing();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 688815a..b21a36d 100644 (file)
@@ -1,11 +1,11 @@
-#pragma once\r
-\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpPacket0 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpPacket0(PMsgDecodeData *nDecodeData);\r
-    //~PUdpPacket0();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpPacket0 : public PUdpMsgAnalyser {
+public:
+    PUdpPacket0(PMsgDecodeData *nDecodeData);
+    //~PUdpPacket0();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index fdea776..3427baf 100644 (file)
@@ -1,14 +1,14 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpPing : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mClientTime;\r
-\r
-public:\r
-    PUdpPing(PMsgDecodeData *nDecodeData);\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpPing : public PUdpMsgAnalyser {
+private:
+    uint32_t mClientTime;
+
+public:
+    PUdpPing(PMsgDecodeData *nDecodeData);
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 0f47787..dc389d1 100644 (file)
@@ -1,15 +1,15 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpItemSlotUse : public PUdpMsgAnalyser {\r
-private:\r
-    uint8_t mTargetSlot;\r
-\r
-public:\r
-    PUdpItemSlotUse(PMsgDecodeData *nDecodeData);\r
-    //~PUdpItemSlotUse();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpItemSlotUse : public PUdpMsgAnalyser {
+private:
+    uint8_t mTargetSlot;
+
+public:
+    PUdpItemSlotUse(PMsgDecodeData *nDecodeData);
+    //~PUdpItemSlotUse();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 5e3163f..3218035 100644 (file)
@@ -1,16 +1,16 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpReqInfo : public PUdpMsgAnalyser {\r
-private:\r
-    uint16_t mRequestType;\r
-    uint32_t mInfoId;\r
-\r
-public:\r
-    PUdpReqInfo(PMsgDecodeData *nDecodeData);\r
-    //~PUdpCharInfo();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpReqInfo : public PUdpMsgAnalyser {
+private:
+    uint16_t mRequestType;
+    uint32_t mInfoId;
+
+public:
+    PUdpReqInfo(PMsgDecodeData *nDecodeData);
+    //~PUdpCharInfo();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 4d1e394..eb4b28e 100644 (file)
@@ -1,15 +1,15 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpSubskillInc : public PUdpMsgAnalyser {\r
-private:\r
-    uint16_t SubskillID;\r
-\r
-public:\r
-    PUdpSubskillInc(PMsgDecodeData *nDecodeData);\r
-    //~PUdpSubskillInc();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpSubskillInc : public PUdpMsgAnalyser {
+private:
+    uint16_t SubskillID;
+
+public:
+    PUdpSubskillInc(PMsgDecodeData *nDecodeData);
+    //~PUdpSubskillInc();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 8841d52..1ef9a85 100644 (file)
@@ -1,33 +1,33 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpSync0 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpSync0(PMsgDecodeData *nDecodeData);\r
-    //~PUdpSync0();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-\r
-    static void GetToSync1(PMsgDecodeData *nDecodeData);\r
-};\r
-\r
-class PUdpSync1 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpSync1(PMsgDecodeData *nDecodeData);\r
-    //~PUdpSync1();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpSync2 : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mClientTime;\r
-\r
-public:\r
-    PUdpSync2(PMsgDecodeData *nDecodeData);\r
-    //~PUdpSync2();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpSync0 : public PUdpMsgAnalyser {
+public:
+    PUdpSync0(PMsgDecodeData *nDecodeData);
+    //~PUdpSync0();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+
+    static void GetToSync1(PMsgDecodeData *nDecodeData);
+};
+
+class PUdpSync1 : public PUdpMsgAnalyser {
+public:
+    PUdpSync1(PMsgDecodeData *nDecodeData);
+    //~PUdpSync1();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpSync2 : public PUdpMsgAnalyser {
+private:
+    uint32_t mClientTime;
+
+public:
+    PUdpSync2(PMsgDecodeData *nDecodeData);
+    //~PUdpSync2();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 486c63a..004f7ba 100644 (file)
-#include <cmath>\r
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/*******************************************************************************************/\r
-/**** PUdpReceiveDB ****/\r
-/*******************************************************************************************/\r
-PUdpReceiveDB::PUdpReceiveDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x17";\r
-  mOptionsCount = 0;\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpReceiveDB::Analyse()\r
-{\r
-  PMessage* TmpMsg = mDecodeData->mMessage;\r
-  uint16_t Unknown3, OptionSize;\r
-\r
-  mDecodeData->mName << "=ReceiveDB request from client";\r
-\r
-  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );\r
-  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 17 );\r
-  ( *TmpMsg ) >> mUnknown2; // Some unknown var maxx used. No idea what that is\r
-  ( *TmpMsg ) >> mUnknown1; // command name size\r
-  ( *TmpMsg ) >> mDBId; // variable, increments => DB ID. Look in several terminal .tsc files, ENV(DBID) it is!\r
-  ( *TmpMsg ) >> Unknown3; // constant ? => Size of Options!\r
-  ( *TmpMsg ) >> mCommandName; // null terminated string\r
-\r
-\r
-  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )\r
-  {\r
-    ( *TmpMsg ) >> OptionSize;\r
-    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )\r
-    {\r
-      ( *TmpMsg ) >> mOptions[mOptionsCount++];\r
-      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!\r
-    }\r
-    else\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpReceiveDB::DoAction()\r
-{\r
-  //PMessage* tmpMsg;\r
-  //PClient* tClient = mDecodeData->mClient;\r
-  //PChar* tChar = tClient->GetChar();\r
-  bool Result = false;\r
-\r
-  if ( gDevDebug )\r
-  {\r
-    Console->Print( "%s ReceiveDB request from client", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    Console->Print( "%s Open Terminal - Terminal session %04x (?) - Unknown1 %04x - DBId %04x - Unknown2 %02x", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId, mUnknown1, mDBId, mUnknown2 );\r
-    Console->Print( "%s Command: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mCommandName.c_str() );\r
-    for ( uint8_t i = 0; i < mOptionsCount; ++i )\r
-      Console->Print( "%s Option %d: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), i, mOptions[i].c_str() );\r
-  }\r
-\r
-  if ( mCommandName == "VehicleListing" )\r
-  {\r
-    Result = ActionVehicleListing();\r
-  }\r
-  else if ( mCommandName == "VehicleControl" )\r
-  {\r
-    Result = ActionVehicleControl();\r
-  }\r
-  else\r
-  {\r
-      // Let Terminal try before error\r
-      Result = Terminal->HandleReceiveDB(mDecodeData->mClient, mTerminalSessionId, &mCommandName, mOptions, mOptionsCount, mDBId, mUnknown2);\r
-  }\r
-\r
-  if ( !Result )\r
-  {\r
-    Console->Print( "%s PUdpReceiveDB - Error or unknown command %s", Console->ColorText( RED, BLACK, "[WARNING]" ), mCommandName.c_str() );\r
-    for ( uint8_t i = 0; i < mOptionsCount; ++i )\r
-      Console->Print( "%s Option %d: '%s'", Console->ColorText( RED, BLACK, "[NOTICE]" ), i, mOptions[i].c_str() );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return Result;\r
-}\r
-\r
-bool PUdpReceiveDB::ActionVehicleListing()\r
-{\r
-  PMessage* tmpMsg;\r
-  PClient* tClient = mDecodeData->mClient;\r
-  PChar* tChar = tClient->GetChar();\r
-\r
-  if ( mOptionsCount == 3 ) // CharId, StartVhcEntry, MaxVhcEntries\r
-  {\r
-    if ((( uint32_t )atol( mOptions[0].c_str() ) ) != tChar->GetID() )\r
-    {\r
-      // Err: invalid CharId. Can alert, But we don't care :-) (except if used for other terminal function)\r
-    }\r
-    // !!! some more check/regex on values to do before using !!!\r
-    uint16_t StartIndex = atoi( mOptions[1].c_str() );\r
-    uint16_t MaxEntries = atoi( mOptions[2].c_str() );\r
-\r
-    uint8_t nStatus = 1;\r
-    uint16_t nErrcode = 0;\r
-\r
-    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );\r
-    tClient->SendUDPMessage( tmpMsg );\r
-\r
-    PVhcInfoList* VhcList = Vehicles->GetCharVehicles( tChar->GetID(), MaxEntries, StartIndex );\r
-    if ( ! VhcList->empty() )\r
-    {\r
-      uint16_t NumEntries = VhcList->size();\r
-      std::string* Answer = new std::string[4 * NumEntries];\r
-      uint16_t Index = 0;\r
-      PVehicleInformation* EntryInfo;\r
-//Console->Print("VHc entries : %d", NumEntries);\r
-\r
-      while ( ! VhcList->empty() )\r
-      {\r
-        EntryInfo = VhcList->front();\r
-        VhcList->pop();\r
-        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetVehicleId() ); //vhcId\r
-        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetVehicleType() ); //vhcType\r
-        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetStatus() ); //vhcStatus 0:parking, 1:in_service, 2:destroyed\r
-        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetHealth() ); //vhcHealth%\r
-//Console->Print("Entry: %s/%s/%s/%s", Answer[Index-4].c_str(), Answer[Index-3].c_str(), Answer[Index-2].c_str(), Answer[Index-1].c_str());\r
-        delete EntryInfo;\r
-      }\r
-\r
-      tmpMsg = MsgBuilder->BuildDBAnswerMsg( tClient, &mCommandName, Answer, NumEntries, 4 );\r
-      tClient->SendUDPMessage( tmpMsg );\r
-      delete [] Answer;\r
-    }\r
-    delete VhcList;\r
-\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-  /*\r
-  // Option1=CharId, Option2=resultEntryStart, Option3=maxResultEntries\r
-  S=> 03/2b/1a <uint16_t size incl 0><uint8_t bool succes ?><uint16_t err code ?>VehicleListing+0\r
-  13 2a 00 7c be 19\r
-  03 2a 00 2b 1a 0f 00 01 00 00 56 65 68 69 63 6c  .*.+......Vehicl\r
-  65 4c 69 73 74 69 6e 67 00  eListing.\r
-  S=> 03/2b/17 0f 00 08 00 04 00 <0f 00><uint16_t entries nb><04 00>\r
-  VehicleListing+0\r
-  <id_size incl 0><id_string +0>\r
-  <type_size><type_id_string? +0>\r
-  <status_size><status_string +0> (val: 0=stored)\r
-  <health_size><health_string +0> (val: 0-255)\r
-  ==\r
-  03/2b/17 0f 00 01 00 04 00 <0f 00><uint16_t entries nb><04 00>\r
-  31\r
-  03 54 00 2b 17 0f 00 01 00 04 00 56 65 68 69 63 6c 65 4c 69 73 74  .....VehicleList\r
-  69 6e 67 00 06 00 32 35 32 37 37 00 03 00 36 30  ing...25277...60\r
-  00 02 00 30 00 04 00 32 35 35 00  ...0...255.\r
-  */\r
-}\r
-\r
-bool PUdpReceiveDB::ActionVehicleControl()\r
-{\r
-  PMessage* tmpMsg;\r
-  PClient* tClient = mDecodeData->mClient;\r
-\r
-  if ( mOptionsCount == 2 ) // VhcId, CharId\r
-  {\r
-    // !!! validate values !!!\r
-    uint8_t nStatus = 1;\r
-    uint16_t nErrcode = 0;\r
-\r
-    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );\r
-    tClient->SendUDPMessage( tmpMsg );\r
-\r
-    uint32_t VhcId = ( uint32_t )atol( mOptions[0].c_str() );\r
-    PVehicleInformation EntryInfo;\r
-    if ( Vehicles->GetVehicleInfo( VhcId, &EntryInfo ) )\r
-    {\r
-      std::string* Answer = new std::string[4];\r
-      Answer[0] = Ssprintf( "%u", EntryInfo.GetVehicleType() ); //vhcType\r
-      Answer[1] = Ssprintf( "%u", EntryInfo.GetStatus() ); //vhcStatus\r
-      Answer[2] = Ssprintf( "%u", EntryInfo.GetHealth() ); //vhcHealth%\r
-      Answer[3] = Ssprintf( "%u", ( 255 - EntryInfo.GetHealth() ) * 1000 * EntryInfo.GetVehicleType() / 255 ); //Repair cost\r
-      if ( gDevDebug )\r
-        Console->Print( "%s Entry: %s/%s/%s/%s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), Answer[0].c_str(), Answer[1].c_str(), Answer[2].c_str(), Answer[3].c_str() );\r
-      tmpMsg = MsgBuilder->BuildDBAnswerMsg( tClient, &mCommandName, Answer, 1, 4 );\r
-      tClient->SendUDPMessage( tmpMsg );\r
-      delete [] Answer;\r
-    }\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-  /*\r
-  // Option1=VhcId, Option2=CharId\r
-  S=> 03/2b/1a VehicleControl\r
-  13 77 00 c9 be 19\r
-  03 76 00 2b 1a 0f 00 01 00 00 56 65 68 69 63 6c  .v.+......Vehicl\r
-  65 43 6f 6e 74 72 6f 6c 00  eControl.\r
-  S=> 03/2b/17 0f 00 01 00 04 00 VehicleControl  4 0 255 4255(\r
-  2f\r
-  03 77 00 2b 17 0f 00 01 00 04 00 56 65 68 69 63 6c 65 43 6f 6e 74  .....VehicleCont\r
-  72 6f 6c 00 02 00 34 00 02 00 30 00 04 00 32 35  rol...4...0...25\r
-  35 00 05 00 34 32 35 35 00                       5...4255.\r
-  */\r
-}\r
-\r
-/*******************************************************************************************/\r
-/**** PUdpUpdateDB ****/\r
-/*******************************************************************************************/\r
-PUdpUpdateDB::PUdpUpdateDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x18";\r
-  mOptionsCount = 0;\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpUpdateDB::Analyse()\r
-{\r
-  PMessage* TmpMsg = mDecodeData->mMessage;\r
-  uint16_t Unknown3, OptionSize;\r
-\r
-  mDecodeData->mName << "=UpdateDB request from client";\r
-\r
-  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );\r
-  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 17 );\r
-  ( *TmpMsg ) >> mUnknown2; // Some unknown var maxx used. No idea what that is\r
-  ( *TmpMsg ) >> mUnknown1; // command name size\r
-  ( *TmpMsg ) >> mDBId; // variable, increments => DB ID. Look in several terminal .tsc files, ENV(DBID) it is!\r
-  ( *TmpMsg ) >> Unknown3; // constant ? => Size of Options!\r
-  ( *TmpMsg ) >> mCommandName; // null terminated string\r
-\r
-\r
-  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )\r
-  {\r
-    ( *TmpMsg ) >> OptionSize;\r
-    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )\r
-    {\r
-      ( *TmpMsg ) >> mOptions[mOptionsCount++];\r
-      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!\r
-    }\r
-    else\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpUpdateDB::DoAction()\r
-{\r
-  if ( gDevDebug )\r
-  {\r
-    Console->Print( "%s UpdateDB request from client", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    Console->Print( "%s Open Terminal - Terminal session %04x (?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId );\r
-    Console->Print( "%s Command: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mCommandName.c_str() );\r
-    for ( uint8_t i = 0; i < mOptionsCount; ++i )\r
-      Console->Print( "%s Option %d: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), i, mOptions[i].c_str() );\r
-  }\r
-   bool Result = false;\r
-    Result = Terminal->HandleUpdateDB(mDecodeData->mClient, mTerminalSessionId, &mCommandName, mOptions, mOptionsCount, mDBId, mUnknown2);\r
-\r
- if ( !Result )\r
-  {\r
-    Console->Print( "%s PUdpUpdateDB - Error or unknown command %s", Console->ColorText( RED, BLACK, "[WARNING]" ), mCommandName.c_str() );\r
-    for ( uint8_t i = 0; i < mOptionsCount; ++i )\r
-      Console->Print( "%s Option %d: '%s'", Console->ColorText( RED, BLACK, "[NOTICE]" ), i, mOptions[i].c_str() );\r
-  }\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-/*******************************************************************************************/\r
-/**** PUdpTryAccessDB ****/\r
-/*******************************************************************************************/\r
-PUdpTryAccessDB::PUdpTryAccessDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x19";\r
-  mOptionsCount = 0;\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpTryAccessDB::Analyse()\r
-{\r
-  PMessage* TmpMsg = mDecodeData->mMessage;\r
-  uint16_t Unknown3, OptionSize;\r
-\r
-  mDecodeData->mName << "=TryAccess request from client";\r
-\r
-  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );\r
-  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 17 );\r
-  ( *TmpMsg ) >> mUnknown2; // Some unknown var maxx used. No idea what that is\r
-  ( *TmpMsg ) >> mUnknown1; // command name size\r
-  ( *TmpMsg ) >> mDBId; // variable, increments => DB ID. Look in several terminal .tsc files, ENV(DBID) it is!\r
-  ( *TmpMsg ) >> Unknown3; // constant ? => Size of Options!\r
-  ( *TmpMsg ) >> mCommandName; // null terminated string\r
-\r
-  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )\r
-  {\r
-    ( *TmpMsg ) >> OptionSize;\r
-    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )\r
-    {\r
-      ( *TmpMsg ) >> mOptions[mOptionsCount++];\r
-      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!\r
-    }\r
-    else\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpTryAccessDB::DoAction()\r
-{\r
-    // Let the terminal class handle the request\r
-    Terminal->HandleTryAccess(mDecodeData->mClient, mTerminalSessionId, &mCommandName, mOptions, mOptionsCount, mDBId, mUnknown2);\r
-\r
-    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-    return true;\r
-}\r
-/*******************************************************************************************/\r
-/**** PUdpQueryDB ****/\r
-/*******************************************************************************************/\r
-PUdpQueryDB::PUdpQueryDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x1b";\r
-  mOptionsCount = 0;\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpQueryDB::Analyse()\r
-{\r
-  PMessage* TmpMsg = mDecodeData->mMessage;\r
-  uint16_t OptionSize;\r
-\r
-  mDecodeData->mName << "=QueryDB request from client";\r
-\r
-  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );\r
-  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 18 );\r
-  ( *TmpMsg ) >> OptionSize; // Size of data\r
-  ( *TmpMsg ) >> OptionSize; // Size of DB Command Name\r
-  if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )\r
-  {\r
-    ( *TmpMsg ) >> mDBCommandName;\r
-  }\r
-  ( *TmpMsg ) >> OptionSize; // Size of Command Name\r
-  if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )\r
-  {\r
-    ( *TmpMsg ) >> mCommandName; // null terminated string\r
-  }\r
-\r
-  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )\r
-  {\r
-    ( *TmpMsg ) >> OptionSize;\r
-    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )\r
-    {\r
-      ( *TmpMsg ) >> mOptions[mOptionsCount++];\r
-      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!\r
-    }\r
-    else\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpQueryDB::DoAction()\r
-{\r
-  //PMessage* tmpMsg;\r
-  //PClient* tClient = mDecodeData->mClient;\r
-  bool Result = false;\r
-\r
-  if ( gDevDebug )\r
-  {\r
-    Console->Print( "%s QueryDB request from client", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    Console->Print( "%s Open Terminal - Terminal session %04x (?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId );\r
-    Console->Print( "%s DBCommand: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDBCommandName.c_str() );\r
-    Console->Print( "%s Command: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mCommandName.c_str() );\r
-    for ( uint8_t i = 0; i < mOptionsCount; ++i )\r
-      Console->Print( "%s Option %d: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), i, mOptions[i].c_str() );\r
-  }\r
-\r
-  if ( mDBCommandName == "SPAWNVEHICLE" )\r
-  {\r
-    Result = ActionSpawnVehicle();\r
-  }\r
-  else if ( mDBCommandName == "REPAIRVEHICLE" )\r
-  {\r
-    Result = ActionRepairVehicle();\r
-  }\r
-  else if ( mDBCommandName == "DISMISSVEHICLE" )\r
-  {\r
-    Result = ActionDismissVehicle();\r
-  }\r
-  else\r
-  {\r
-      // Let Terminal try before error\r
-      Result = Terminal->HandleQueryDB(mDecodeData->mClient, &mDBCommandName, &mCommandName, mOptions, mOptionsCount);\r
-  }\r
-\r
-  if ( !Result )\r
-  {\r
-    Console->Print( "%s PUdpQueryDB - Error or unknown command %s", Console->ColorText( RED, BLACK, "[WARNING]" ), mDBCommandName.c_str() );\r
-    for ( uint8_t i = 0; i < mOptionsCount; ++i )\r
-      Console->Print( "%s Option %d: '%s'", Console->ColorText( RED, BLACK, "[NOTICE]" ), i, mOptions[i].c_str() );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return Result;\r
-}\r
-\r
-bool PUdpQueryDB::ActionSpawnVehicle()\r
-{\r
-  PMessage* tmpMsg;\r
-  PClient* tClient = mDecodeData->mClient;\r
-  PChar* tChar = tClient->GetChar();\r
-\r
-  if ( mOptionsCount == 3 ) // 0, VhcId, CharId\r
-  {\r
-    uint32_t VhcId = ( uint32_t )atol( mOptions[1].c_str() );\r
-    //uint32_t CharId = (uint32_t)atol(mOptions[2].c_str());\r
-    // !!! validate values !!!\r
-    // !!! + check CharId = current char && CharId is owner of VhcId\r
-    uint8_t nStatus = 1; // 1=OK, 0=Err\r
-    uint16_t nErrcode = 16; // 0=n/a 16=Already Spawned // MsdId = 2500+nErrcode [MISC]\r
-\r
-    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );\r
-    tClient->SendUDPMessage( tmpMsg );\r
-\r
-    PVhcCoordinates NewPosition;\r
-    PWorld* CurrentWorld = Worlds->GetWorld( tChar->GetLocation() );\r
-    bool relativePos = false;\r
-    if ( tChar->GetLastUsedObject() && !WorldActors->IsDynamicActor( tChar->GetLastUsedObject() ) && CurrentWorld )\r
-    {\r
-      const PFurnitureItemTemplate* tFurnitureTemplate = CurrentWorld->GetFurnitureItemTemplate( tChar->GetLastUsedObject() / 1024 - 1 );\r
-      if ( tFurnitureTemplate && ( tFurnitureTemplate->GetFunctionType() == 28 ) ) // vhc term\r
-      {\r
-        float decal = 1000; // distance at which to spawn the vhc\r
-        float nPosX, nPosY, nPosZ;\r
-        tFurnitureTemplate->GetPos( &nPosX, &nPosY, &nPosZ );\r
-        nPosX += 32000;\r
-        nPosY += 32000;\r
-        float dX = ( tChar->Coords.mX - nPosX );\r
-        float dY = ( tChar->Coords.mY - nPosY );\r
-        float d = decal / sqrt( dX * dX + dY * dY );\r
-        NewPosition.SetPosition( static_cast<uint16_t>( nPosY + d * dY ), ( tChar->Coords ).mZ + 100, static_cast<uint16_t>( nPosX + d * dX ), ( tChar->Coords ).mUD, 34683, 32403 );\r
-        relativePos = true;\r
-      }\r
-    }\r
-\r
-    if( ! relativePos )\r
-      NewPosition.SetPosition(( tChar->Coords ).mY, ( tChar->Coords ).mZ + 150, ( tChar->Coords ).mX, ( tChar->Coords ).mUD, 34683, 32403 );\r
-\r
-    PSpawnedVehicle* NewVhc = Vehicles->SpawnVehicle( VhcId, tChar->GetLocation(), &NewPosition );\r
-    if ( NewVhc )\r
-    {\r
-      tmpMsg = MsgBuilder->BuildVhcPosUpdateMsg( NewVhc );\r
-      ClientManager->UDPBroadcast( tmpMsg, tChar->GetLocation() );\r
-    }\r
-\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-bool PUdpQueryDB::ActionRepairVehicle()\r
-{\r
-  PMessage* tmpMsg;\r
-  PClient* tClient = mDecodeData->mClient;\r
-\r
-  if ( mOptionsCount == 3 ) // 0, VhcId, CharId\r
-  {\r
-    //uint32_t VhcId = (uint32_t)atol(mOptions[1].c_str());\r
-    //uint32_t CharId = (uint32_t)atol(mOptions[2].c_str());\r
-    // !!! validate values !!!\r
-\r
-    uint8_t nStatus = 1; // 1=OK, 0=Err\r
-    uint16_t nErrcode = 18; // 0=n/a 18=Still Spawned, 19=Not enough money\r
-\r
-    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );\r
-    tClient->SendUDPMessage( tmpMsg );\r
-\r
-    // Action here\r
-\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-bool PUdpQueryDB::ActionDismissVehicle()\r
-{\r
-  PMessage* tmpMsg;\r
-  PClient* tClient = mDecodeData->mClient;\r
-  //PChar* tChar = tClient->GetChar();\r
-  bool Result = false;\r
-\r
-  if ( mOptionsCount == 3 ) // 0, VhcId, CharId\r
-  {\r
-    uint32_t VhcId = ( uint32_t )atol( mOptions[1].c_str() );\r
-    //uint32_t CharId = (uint32_t)atol(mOptions[2].c_str());\r
-    // !!! validate values !!!\r
-    // !!! + check CharId = current char && CharId is owner of VjhcId\r
-    // !!! Check vhc empty\r
-    uint8_t nStatus = 0; // 1=OK, 0=Err\r
-    uint16_t nErrcode = 17; // 0=n/a 17=Not Spawned\r
-    PVehicleInformation nInfo;\r
-    uint32_t tLocalId = 0;\r
-    uint32_t tLocation = 0;\r
-\r
-    PSpawnedVehicle* tVhc = Vehicles->GetSpawnedVehicle( VhcId );\r
-    if ( tVhc )\r
-    {\r
-      tLocalId = tVhc->GetLocalId();\r
-      tLocation = tVhc->GetLocation();\r
-      uint32_t tCharId;\r
-      PChar* tChar;\r
-      for ( uint8_t i = 0; i < tVhc->GetNumSeats(); ++i )\r
-      {\r
-        if (( tCharId = tVhc->GetSeatUser( i ) ) )\r
-        {\r
-          if (( tChar = Chars->GetChar( tCharId ) ) )\r
-          {\r
-            PUdpCharExitChair::DoLeaveChair( tChar, NULL, tVhc );\r
-          }\r
-        }\r
-      }\r
-      Result = Vehicles->UnspawnVehicle( VhcId );\r
-    }\r
-\r
-    if ( Result )\r
-    {\r
-      nStatus = 1;\r
-      nErrcode = 0;\r
-    }\r
-    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );\r
-    tClient->SendUDPMessage( tmpMsg );\r
-\r
-    if ( Result )\r
-    {\r
-      tmpMsg = MsgBuilder->BuildRemoveWorldObjectMsg( tLocalId );\r
-      ClientManager->UDPBroadcast( tmpMsg, tLocation );\r
-    }\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-/*******************************************************************************************/\r
-/**** PUdpTeminal0x1f ****/\r
-/*******************************************************************************************/\r
-PUdpTeminal0x1f::PUdpTeminal0x1f( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x1f";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpTeminal0x1f::Analyse()\r
-{\r
-  mDecodeData->mName << "=Open Terminal";\r
-  mTerminalSessionId = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 6 );\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpTeminal0x1f::DoAction()\r
-{\r
-  if ( gDevDebug )\r
-    Console->Print( "%s Open Terminal - Terminal session %04x (?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId );\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
+#include <cmath>
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/*******************************************************************************************/
+/**** PUdpReceiveDB ****/
+/*******************************************************************************************/
+PUdpReceiveDB::PUdpReceiveDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x17";
+  mOptionsCount = 0;
+}
+
+PUdpMsgAnalyser* PUdpReceiveDB::Analyse()
+{
+  PMessage* TmpMsg = mDecodeData->mMessage;
+  uint16_t Unknown3, OptionSize;
+
+  mDecodeData->mName << "=ReceiveDB request from client";
+
+  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );
+  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 17 );
+  ( *TmpMsg ) >> mUnknown2; // Some unknown var maxx used. No idea what that is
+  ( *TmpMsg ) >> mUnknown1; // command name size
+  ( *TmpMsg ) >> mDBId; // variable, increments => DB ID. Look in several terminal .tsc files, ENV(DBID) it is!
+  ( *TmpMsg ) >> Unknown3; // constant ? => Size of Options!
+  ( *TmpMsg ) >> mCommandName; // null terminated string
+
+
+  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )
+  {
+    ( *TmpMsg ) >> OptionSize;
+    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )
+    {
+      ( *TmpMsg ) >> mOptions[mOptionsCount++];
+      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!
+    }
+    else
+    {
+      break;
+    }
+  }
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpReceiveDB::DoAction()
+{
+  //PMessage* tmpMsg;
+  //PClient* tClient = mDecodeData->mClient;
+  //PChar* tChar = tClient->GetChar();
+  bool Result = false;
+
+  if ( gDevDebug )
+  {
+    Console->Print( "%s ReceiveDB request from client", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    Console->Print( "%s Open Terminal - Terminal session %04x (?) - Unknown1 %04x - DBId %04x - Unknown2 %02x", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId, mUnknown1, mDBId, mUnknown2 );
+    Console->Print( "%s Command: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mCommandName.c_str() );
+    for ( uint8_t i = 0; i < mOptionsCount; ++i )
+      Console->Print( "%s Option %d: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), i, mOptions[i].c_str() );
+  }
+
+  if ( mCommandName == "VehicleListing" )
+  {
+    Result = ActionVehicleListing();
+  }
+  else if ( mCommandName == "VehicleControl" )
+  {
+    Result = ActionVehicleControl();
+  }
+  else
+  {
+      // Let Terminal try before error
+      Result = Terminal->HandleReceiveDB(mDecodeData->mClient, mTerminalSessionId, &mCommandName, mOptions, mOptionsCount, mDBId, mUnknown2);
+  }
+
+  if ( !Result )
+  {
+    Console->Print( "%s PUdpReceiveDB - Error or unknown command %s", Console->ColorText( RED, BLACK, "[WARNING]" ), mCommandName.c_str() );
+    for ( uint8_t i = 0; i < mOptionsCount; ++i )
+      Console->Print( "%s Option %d: '%s'", Console->ColorText( RED, BLACK, "[NOTICE]" ), i, mOptions[i].c_str() );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return Result;
+}
+
+bool PUdpReceiveDB::ActionVehicleListing()
+{
+  PMessage* tmpMsg;
+  PClient* tClient = mDecodeData->mClient;
+  PChar* tChar = tClient->GetChar();
+
+  if ( mOptionsCount == 3 ) // CharId, StartVhcEntry, MaxVhcEntries
+  {
+    if ((( uint32_t )atol( mOptions[0].c_str() ) ) != tChar->GetID() )
+    {
+      // Err: invalid CharId. Can alert, But we don't care :-) (except if used for other terminal function)
+    }
+    // !!! some more check/regex on values to do before using !!!
+    uint16_t StartIndex = atoi( mOptions[1].c_str() );
+    uint16_t MaxEntries = atoi( mOptions[2].c_str() );
+
+    uint8_t nStatus = 1;
+    uint16_t nErrcode = 0;
+
+    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );
+    tClient->SendUDPMessage( tmpMsg );
+
+    PVhcInfoList* VhcList = Vehicles->GetCharVehicles( tChar->GetID(), MaxEntries, StartIndex );
+    if ( ! VhcList->empty() )
+    {
+      uint16_t NumEntries = VhcList->size();
+      std::string* Answer = new std::string[4 * NumEntries];
+      uint16_t Index = 0;
+      PVehicleInformation* EntryInfo;
+//Console->Print("VHc entries : %d", NumEntries);
+
+      while ( ! VhcList->empty() )
+      {
+        EntryInfo = VhcList->front();
+        VhcList->pop();
+        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetVehicleId() ); //vhcId
+        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetVehicleType() ); //vhcType
+        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetStatus() ); //vhcStatus 0:parking, 1:in_service, 2:destroyed
+        Answer[Index++] = Ssprintf( "%u", EntryInfo->GetHealth() ); //vhcHealth%
+//Console->Print("Entry: %s/%s/%s/%s", Answer[Index-4].c_str(), Answer[Index-3].c_str(), Answer[Index-2].c_str(), Answer[Index-1].c_str());
+        delete EntryInfo;
+      }
+
+      tmpMsg = MsgBuilder->BuildDBAnswerMsg( tClient, &mCommandName, Answer, NumEntries, 4 );
+      tClient->SendUDPMessage( tmpMsg );
+      delete [] Answer;
+    }
+    delete VhcList;
+
+    return true;
+  }
+  else
+    return false;
+  /*
+  // Option1=CharId, Option2=resultEntryStart, Option3=maxResultEntries
+  S=> 03/2b/1a <uint16_t size incl 0><uint8_t bool succes ?><uint16_t err code ?>VehicleListing+0
+  13 2a 00 7c be 19
+  03 2a 00 2b 1a 0f 00 01 00 00 56 65 68 69 63 6c  .*.+......Vehicl
+  65 4c 69 73 74 69 6e 67 00  eListing.
+  S=> 03/2b/17 0f 00 08 00 04 00 <0f 00><uint16_t entries nb><04 00>
+  VehicleListing+0
+  <id_size incl 0><id_string +0>
+  <type_size><type_id_string? +0>
+  <status_size><status_string +0> (val: 0=stored)
+  <health_size><health_string +0> (val: 0-255)
+  ==
+  03/2b/17 0f 00 01 00 04 00 <0f 00><uint16_t entries nb><04 00>
+  31
+  03 54 00 2b 17 0f 00 01 00 04 00 56 65 68 69 63 6c 65 4c 69 73 74  .....VehicleList
+  69 6e 67 00 06 00 32 35 32 37 37 00 03 00 36 30  ing...25277...60
+  00 02 00 30 00 04 00 32 35 35 00  ...0...255.
+  */
+}
+
+bool PUdpReceiveDB::ActionVehicleControl()
+{
+  PMessage* tmpMsg;
+  PClient* tClient = mDecodeData->mClient;
+
+  if ( mOptionsCount == 2 ) // VhcId, CharId
+  {
+    // !!! validate values !!!
+    uint8_t nStatus = 1;
+    uint16_t nErrcode = 0;
+
+    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );
+    tClient->SendUDPMessage( tmpMsg );
+
+    uint32_t VhcId = ( uint32_t )atol( mOptions[0].c_str() );
+    PVehicleInformation EntryInfo;
+    if ( Vehicles->GetVehicleInfo( VhcId, &EntryInfo ) )
+    {
+      std::string* Answer = new std::string[4];
+      Answer[0] = Ssprintf( "%u", EntryInfo.GetVehicleType() ); //vhcType
+      Answer[1] = Ssprintf( "%u", EntryInfo.GetStatus() ); //vhcStatus
+      Answer[2] = Ssprintf( "%u", EntryInfo.GetHealth() ); //vhcHealth%
+      Answer[3] = Ssprintf( "%u", ( 255 - EntryInfo.GetHealth() ) * 1000 * EntryInfo.GetVehicleType() / 255 ); //Repair cost
+      if ( gDevDebug )
+        Console->Print( "%s Entry: %s/%s/%s/%s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), Answer[0].c_str(), Answer[1].c_str(), Answer[2].c_str(), Answer[3].c_str() );
+      tmpMsg = MsgBuilder->BuildDBAnswerMsg( tClient, &mCommandName, Answer, 1, 4 );
+      tClient->SendUDPMessage( tmpMsg );
+      delete [] Answer;
+    }
+    return true;
+  }
+  else
+    return false;
+  /*
+  // Option1=VhcId, Option2=CharId
+  S=> 03/2b/1a VehicleControl
+  13 77 00 c9 be 19
+  03 76 00 2b 1a 0f 00 01 00 00 56 65 68 69 63 6c  .v.+......Vehicl
+  65 43 6f 6e 74 72 6f 6c 00  eControl.
+  S=> 03/2b/17 0f 00 01 00 04 00 VehicleControl  4 0 255 4255(
+  2f
+  03 77 00 2b 17 0f 00 01 00 04 00 56 65 68 69 63 6c 65 43 6f 6e 74  .....VehicleCont
+  72 6f 6c 00 02 00 34 00 02 00 30 00 04 00 32 35  rol...4...0...25
+  35 00 05 00 34 32 35 35 00                       5...4255.
+  */
+}
+
+/*******************************************************************************************/
+/**** PUdpUpdateDB ****/
+/*******************************************************************************************/
+PUdpUpdateDB::PUdpUpdateDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x18";
+  mOptionsCount = 0;
+}
+
+PUdpMsgAnalyser* PUdpUpdateDB::Analyse()
+{
+  PMessage* TmpMsg = mDecodeData->mMessage;
+  uint16_t Unknown3, OptionSize;
+
+  mDecodeData->mName << "=UpdateDB request from client";
+
+  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );
+  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 17 );
+  ( *TmpMsg ) >> mUnknown2; // Some unknown var maxx used. No idea what that is
+  ( *TmpMsg ) >> mUnknown1; // command name size
+  ( *TmpMsg ) >> mDBId; // variable, increments => DB ID. Look in several terminal .tsc files, ENV(DBID) it is!
+  ( *TmpMsg ) >> Unknown3; // constant ? => Size of Options!
+  ( *TmpMsg ) >> mCommandName; // null terminated string
+
+
+  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )
+  {
+    ( *TmpMsg ) >> OptionSize;
+    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )
+    {
+      ( *TmpMsg ) >> mOptions[mOptionsCount++];
+      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!
+    }
+    else
+    {
+      break;
+    }
+  }
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpUpdateDB::DoAction()
+{
+  if ( gDevDebug )
+  {
+    Console->Print( "%s UpdateDB request from client", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    Console->Print( "%s Open Terminal - Terminal session %04x (?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId );
+    Console->Print( "%s Command: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mCommandName.c_str() );
+    for ( uint8_t i = 0; i < mOptionsCount; ++i )
+      Console->Print( "%s Option %d: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), i, mOptions[i].c_str() );
+  }
+   bool Result = false;
+    Result = Terminal->HandleUpdateDB(mDecodeData->mClient, mTerminalSessionId, &mCommandName, mOptions, mOptionsCount, mDBId, mUnknown2);
+
+ if ( !Result )
+  {
+    Console->Print( "%s PUdpUpdateDB - Error or unknown command %s", Console->ColorText( RED, BLACK, "[WARNING]" ), mCommandName.c_str() );
+    for ( uint8_t i = 0; i < mOptionsCount; ++i )
+      Console->Print( "%s Option %d: '%s'", Console->ColorText( RED, BLACK, "[NOTICE]" ), i, mOptions[i].c_str() );
+  }
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+/*******************************************************************************************/
+/**** PUdpTryAccessDB ****/
+/*******************************************************************************************/
+PUdpTryAccessDB::PUdpTryAccessDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x19";
+  mOptionsCount = 0;
+}
+
+PUdpMsgAnalyser* PUdpTryAccessDB::Analyse()
+{
+  PMessage* TmpMsg = mDecodeData->mMessage;
+  uint16_t Unknown3, OptionSize;
+
+  mDecodeData->mName << "=TryAccess request from client";
+
+  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );
+  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 17 );
+  ( *TmpMsg ) >> mUnknown2; // Some unknown var maxx used. No idea what that is
+  ( *TmpMsg ) >> mUnknown1; // command name size
+  ( *TmpMsg ) >> mDBId; // variable, increments => DB ID. Look in several terminal .tsc files, ENV(DBID) it is!
+  ( *TmpMsg ) >> Unknown3; // constant ? => Size of Options!
+  ( *TmpMsg ) >> mCommandName; // null terminated string
+
+  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )
+  {
+    ( *TmpMsg ) >> OptionSize;
+    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )
+    {
+      ( *TmpMsg ) >> mOptions[mOptionsCount++];
+      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!
+    }
+    else
+    {
+      break;
+    }
+  }
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpTryAccessDB::DoAction()
+{
+    // Let the terminal class handle the request
+    Terminal->HandleTryAccess(mDecodeData->mClient, mTerminalSessionId, &mCommandName, mOptions, mOptionsCount, mDBId, mUnknown2);
+
+    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+    return true;
+}
+/*******************************************************************************************/
+/**** PUdpQueryDB ****/
+/*******************************************************************************************/
+PUdpQueryDB::PUdpQueryDB( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x1b";
+  mOptionsCount = 0;
+}
+
+PUdpMsgAnalyser* PUdpQueryDB::Analyse()
+{
+  PMessage* TmpMsg = mDecodeData->mMessage;
+  uint16_t OptionSize;
+
+  mDecodeData->mName << "=QueryDB request from client";
+
+  mTerminalSessionId = TmpMsg->U8Data( mDecodeData->Sub0x13Start + 6 );
+  TmpMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 18 );
+  ( *TmpMsg ) >> OptionSize; // Size of data
+  ( *TmpMsg ) >> OptionSize; // Size of DB Command Name
+  if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )
+  {
+    ( *TmpMsg ) >> mDBCommandName;
+  }
+  ( *TmpMsg ) >> OptionSize; // Size of Command Name
+  if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )
+  {
+    ( *TmpMsg ) >> mCommandName; // null terminated string
+  }
+
+  while (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && ( mOptionsCount < mMaxOptions ) )
+  {
+    ( *TmpMsg ) >> OptionSize;
+    if (( TmpMsg->GetNextByteOffset() < mDecodeData->Sub0x13StartNext ) && OptionSize )
+    {
+      ( *TmpMsg ) >> mOptions[mOptionsCount++];
+      //if(mOptions[mOptionsCount-1].size() != (OptionSize-1)) Warning (but no pb)!
+    }
+    else
+    {
+      break;
+    }
+  }
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpQueryDB::DoAction()
+{
+  //PMessage* tmpMsg;
+  //PClient* tClient = mDecodeData->mClient;
+  bool Result = false;
+
+  if ( gDevDebug )
+  {
+    Console->Print( "%s QueryDB request from client", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    Console->Print( "%s Open Terminal - Terminal session %04x (?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId );
+    Console->Print( "%s DBCommand: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDBCommandName.c_str() );
+    Console->Print( "%s Command: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mCommandName.c_str() );
+    for ( uint8_t i = 0; i < mOptionsCount; ++i )
+      Console->Print( "%s Option %d: '%s'", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), i, mOptions[i].c_str() );
+  }
+
+  if ( mDBCommandName == "SPAWNVEHICLE" )
+  {
+    Result = ActionSpawnVehicle();
+  }
+  else if ( mDBCommandName == "REPAIRVEHICLE" )
+  {
+    Result = ActionRepairVehicle();
+  }
+  else if ( mDBCommandName == "DISMISSVEHICLE" )
+  {
+    Result = ActionDismissVehicle();
+  }
+  else
+  {
+      // Let Terminal try before error
+      Result = Terminal->HandleQueryDB(mDecodeData->mClient, &mDBCommandName, &mCommandName, mOptions, mOptionsCount);
+  }
+
+  if ( !Result )
+  {
+    Console->Print( "%s PUdpQueryDB - Error or unknown command %s", Console->ColorText( RED, BLACK, "[WARNING]" ), mDBCommandName.c_str() );
+    for ( uint8_t i = 0; i < mOptionsCount; ++i )
+      Console->Print( "%s Option %d: '%s'", Console->ColorText( RED, BLACK, "[NOTICE]" ), i, mOptions[i].c_str() );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return Result;
+}
+
+bool PUdpQueryDB::ActionSpawnVehicle()
+{
+  PMessage* tmpMsg;
+  PClient* tClient = mDecodeData->mClient;
+  PChar* tChar = tClient->GetChar();
+
+  if ( mOptionsCount == 3 ) // 0, VhcId, CharId
+  {
+    uint32_t VhcId = ( uint32_t )atol( mOptions[1].c_str() );
+    //uint32_t CharId = (uint32_t)atol(mOptions[2].c_str());
+    // !!! validate values !!!
+    // !!! + check CharId = current char && CharId is owner of VhcId
+    uint8_t nStatus = 1; // 1=OK, 0=Err
+    uint16_t nErrcode = 16; // 0=n/a 16=Already Spawned // MsdId = 2500+nErrcode [MISC]
+
+    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );
+    tClient->SendUDPMessage( tmpMsg );
+
+    PVhcCoordinates NewPosition;
+    PWorld* CurrentWorld = Worlds->GetWorld( tChar->GetLocation() );
+    bool relativePos = false;
+    if ( tChar->GetLastUsedObject() && !WorldActors->IsDynamicActor( tChar->GetLastUsedObject() ) && CurrentWorld )
+    {
+      const PFurnitureItemTemplate* tFurnitureTemplate = CurrentWorld->GetFurnitureItemTemplate( tChar->GetLastUsedObject() / 1024 - 1 );
+      if ( tFurnitureTemplate && ( tFurnitureTemplate->GetFunctionType() == 28 ) ) // vhc term
+      {
+        float decal = 1000; // distance at which to spawn the vhc
+        float nPosX, nPosY, nPosZ;
+        tFurnitureTemplate->GetPos( &nPosX, &nPosY, &nPosZ );
+        nPosX += 32000;
+        nPosY += 32000;
+        float dX = ( tChar->Coords.mX - nPosX );
+        float dY = ( tChar->Coords.mY - nPosY );
+        float d = decal / sqrt( dX * dX + dY * dY );
+        NewPosition.SetPosition( static_cast<uint16_t>( nPosY + d * dY ), ( tChar->Coords ).mZ + 100, static_cast<uint16_t>( nPosX + d * dX ), ( tChar->Coords ).mUD, 34683, 32403 );
+        relativePos = true;
+      }
+    }
+
+    if( ! relativePos )
+      NewPosition.SetPosition(( tChar->Coords ).mY, ( tChar->Coords ).mZ + 150, ( tChar->Coords ).mX, ( tChar->Coords ).mUD, 34683, 32403 );
+
+    PSpawnedVehicle* NewVhc = Vehicles->SpawnVehicle( VhcId, tChar->GetLocation(), &NewPosition );
+    if ( NewVhc )
+    {
+      tmpMsg = MsgBuilder->BuildVhcPosUpdateMsg( NewVhc );
+      ClientManager->UDPBroadcast( tmpMsg, tChar->GetLocation() );
+    }
+
+    return true;
+  }
+  else
+    return false;
+}
+
+bool PUdpQueryDB::ActionRepairVehicle()
+{
+  PMessage* tmpMsg;
+  PClient* tClient = mDecodeData->mClient;
+
+  if ( mOptionsCount == 3 ) // 0, VhcId, CharId
+  {
+    //uint32_t VhcId = (uint32_t)atol(mOptions[1].c_str());
+    //uint32_t CharId = (uint32_t)atol(mOptions[2].c_str());
+    // !!! validate values !!!
+
+    uint8_t nStatus = 1; // 1=OK, 0=Err
+    uint16_t nErrcode = 18; // 0=n/a 18=Still Spawned, 19=Not enough money
+
+    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );
+    tClient->SendUDPMessage( tmpMsg );
+
+    // Action here
+
+    return true;
+  }
+  else
+    return false;
+}
+
+bool PUdpQueryDB::ActionDismissVehicle()
+{
+  PMessage* tmpMsg;
+  PClient* tClient = mDecodeData->mClient;
+  //PChar* tChar = tClient->GetChar();
+  bool Result = false;
+
+  if ( mOptionsCount == 3 ) // 0, VhcId, CharId
+  {
+    uint32_t VhcId = ( uint32_t )atol( mOptions[1].c_str() );
+    //uint32_t CharId = (uint32_t)atol(mOptions[2].c_str());
+    // !!! validate values !!!
+    // !!! + check CharId = current char && CharId is owner of VjhcId
+    // !!! Check vhc empty
+    uint8_t nStatus = 0; // 1=OK, 0=Err
+    uint16_t nErrcode = 17; // 0=n/a 17=Not Spawned
+    PVehicleInformation nInfo;
+    uint32_t tLocalId = 0;
+    uint32_t tLocation = 0;
+
+    PSpawnedVehicle* tVhc = Vehicles->GetSpawnedVehicle( VhcId );
+    if ( tVhc )
+    {
+      tLocalId = tVhc->GetLocalId();
+      tLocation = tVhc->GetLocation();
+      uint32_t tCharId;
+      PChar* tChar;
+      for ( uint8_t i = 0; i < tVhc->GetNumSeats(); ++i )
+      {
+        if (( tCharId = tVhc->GetSeatUser( i ) ) )
+        {
+          if (( tChar = Chars->GetChar( tCharId ) ) )
+          {
+            PUdpCharExitChair::DoLeaveChair( tChar, NULL, tVhc );
+          }
+        }
+      }
+      Result = Vehicles->UnspawnVehicle( VhcId );
+    }
+
+    if ( Result )
+    {
+      nStatus = 1;
+      nErrcode = 0;
+    }
+    tmpMsg = MsgBuilder->BuildDBRequestStatusMsg( tClient, &mCommandName, nStatus, nErrcode );
+    tClient->SendUDPMessage( tmpMsg );
+
+    if ( Result )
+    {
+      tmpMsg = MsgBuilder->BuildRemoveWorldObjectMsg( tLocalId );
+      ClientManager->UDPBroadcast( tmpMsg, tLocation );
+    }
+    return true;
+  }
+  else
+    return false;
+}
+
+/*******************************************************************************************/
+/**** PUdpTeminal0x1f ****/
+/*******************************************************************************************/
+PUdpTeminal0x1f::PUdpTeminal0x1f( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x1f";
+}
+
+PUdpMsgAnalyser* PUdpTeminal0x1f::Analyse()
+{
+  mDecodeData->mName << "=Open Terminal";
+  mTerminalSessionId = mDecodeData->mMessage->U8Data( mDecodeData->Sub0x13Start + 6 );
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpTeminal0x1f::DoAction()
+{
+  if ( gDevDebug )
+    Console->Print( "%s Open Terminal - Terminal session %04x (?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mTerminalSessionId );
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
index 2cabd91..be25bf1 100644 (file)
@@ -1,97 +1,97 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpReceiveDB : public PUdpMsgAnalyser {\r
-private:\r
-    static const uint8_t mMaxOptions = 9; // Largest: forum\forenlist.tsc(21, 114,...)\r
-    uint16_t mTerminalSessionId;\r
-    std::string mCommandName;\r
-    std::string mOptions[mMaxOptions];\r
-    uint8_t mOptionsCount;\r
-\r
-    uint16_t mUnknown1;\r
-    uint8_t mUnknown2;\r
-    uint16_t mDBId;\r
-\r
-    bool ActionVehicleListing();\r
-    bool ActionVehicleControl();\r
-\r
-public:\r
-    PUdpReceiveDB(PMsgDecodeData *nDecodeData);\r
-    //~PUdpReceiveDB();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpUpdateDB : public PUdpMsgAnalyser {\r
-private:\r
-    static const uint8_t mMaxOptions = 7; // Largest: forum\bbcnewthread.tsc(66):\r
-    uint16_t mTerminalSessionId;\r
-    std::string mCommandName;\r
-    std::string mOptions[mMaxOptions];\r
-    uint8_t mOptionsCount;\r
-\r
-    uint16_t mUnknown1;\r
-    uint8_t mUnknown2;\r
-    uint16_t mDBId;\r
-\r
-public:\r
-    PUdpUpdateDB(PMsgDecodeData *nDecodeData);\r
-    //~PUdpUpdateDB();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpTryAccessDB : public PUdpMsgAnalyser {\r
-private:\r
-    static const uint8_t mMaxOptions = 9; // Largest: stockx\depot.tsc(227):\r
-    uint16_t mTerminalSessionId;\r
-    std::string mCommandName;\r
-    std::string mOptions[mMaxOptions];\r
-    uint8_t mOptionsCount;\r
-\r
-    uint16_t mUnknown1;\r
-    uint8_t mUnknown2;\r
-    uint16_t mDBId;\r
-\r
-public:\r
-    PUdpTryAccessDB(PMsgDecodeData *nDecodeData);\r
-    //~PUdpTryAccessDB();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpQueryDB : public PUdpMsgAnalyser { // Also called "ServerMessage" in .tsc scripts!\r
-private:\r
-    static const uint8_t mMaxOptions = 5; // Largest: politics\transcomment.tsc(36):\r
-    uint16_t mTerminalSessionId;\r
-    uint16_t mDBId;\r
-    std::string mDBCommandName;\r
-    std::string mCommandName;\r
-    std::string mOptions[mMaxOptions];\r
-    uint8_t mOptionsCount;\r
-\r
-    bool ActionSpawnVehicle();\r
-    bool ActionRepairVehicle();\r
-    bool ActionDismissVehicle();\r
-\r
-public:\r
-    PUdpQueryDB(PMsgDecodeData *nDecodeData);\r
-    //~PUdpQueryDB();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpTeminal0x1f : public PUdpMsgAnalyser {\r
-private:\r
-    uint16_t mTerminalSessionId;\r
-\r
-public:\r
-    PUdpTeminal0x1f(PMsgDecodeData *nDecodeData);\r
-    //~PUdpTeminal0x1f();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpReceiveDB : public PUdpMsgAnalyser {
+private:
+    static const uint8_t mMaxOptions = 9; // Largest: forum\forenlist.tsc(21, 114,...)
+    uint16_t mTerminalSessionId;
+    std::string mCommandName;
+    std::string mOptions[mMaxOptions];
+    uint8_t mOptionsCount;
+
+    uint16_t mUnknown1;
+    uint8_t mUnknown2;
+    uint16_t mDBId;
+
+    bool ActionVehicleListing();
+    bool ActionVehicleControl();
+
+public:
+    PUdpReceiveDB(PMsgDecodeData *nDecodeData);
+    //~PUdpReceiveDB();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpUpdateDB : public PUdpMsgAnalyser {
+private:
+    static const uint8_t mMaxOptions = 7; // Largest: forum\bbcnewthread.tsc(66):
+    uint16_t mTerminalSessionId;
+    std::string mCommandName;
+    std::string mOptions[mMaxOptions];
+    uint8_t mOptionsCount;
+
+    uint16_t mUnknown1;
+    uint8_t mUnknown2;
+    uint16_t mDBId;
+
+public:
+    PUdpUpdateDB(PMsgDecodeData *nDecodeData);
+    //~PUdpUpdateDB();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpTryAccessDB : public PUdpMsgAnalyser {
+private:
+    static const uint8_t mMaxOptions = 9; // Largest: stockx\depot.tsc(227):
+    uint16_t mTerminalSessionId;
+    std::string mCommandName;
+    std::string mOptions[mMaxOptions];
+    uint8_t mOptionsCount;
+
+    uint16_t mUnknown1;
+    uint8_t mUnknown2;
+    uint16_t mDBId;
+
+public:
+    PUdpTryAccessDB(PMsgDecodeData *nDecodeData);
+    //~PUdpTryAccessDB();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpQueryDB : public PUdpMsgAnalyser { // Also called "ServerMessage" in .tsc scripts!
+private:
+    static const uint8_t mMaxOptions = 5; // Largest: politics\transcomment.tsc(36):
+    uint16_t mTerminalSessionId;
+    uint16_t mDBId;
+    std::string mDBCommandName;
+    std::string mCommandName;
+    std::string mOptions[mMaxOptions];
+    uint8_t mOptionsCount;
+
+    bool ActionSpawnVehicle();
+    bool ActionRepairVehicle();
+    bool ActionDismissVehicle();
+
+public:
+    PUdpQueryDB(PMsgDecodeData *nDecodeData);
+    //~PUdpQueryDB();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpTeminal0x1f : public PUdpMsgAnalyser {
+private:
+    uint16_t mTerminalSessionId;
+
+public:
+    PUdpTeminal0x1f(PMsgDecodeData *nDecodeData);
+    //~PUdpTeminal0x1f();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index c063aa9..b73f0fd 100644 (file)
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-uint32_t gVhcId = 0x3ff;\r
-\r
-/**** PUdpVhcMove ****/\r
-\r
-PUdpUseObject::PUdpUseObject( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x17";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpUseObject::Analyse()\r
-{\r
-  mDecodeData->mName << "=Object use";\r
-\r
-  mRawItemID = mDecodeData->mMessage->U32Data( mDecodeData->Sub0x13Start + 8 );\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpUseObject::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* nChar = nClient->GetChar();\r
-  uint32_t ItemID;\r
-  char DbgMessage[128];\r
-  PMessage* tmpMsg;\r
-\r
-  bool tHandleDynamicActor = false;\r
-\r
-  /*PMessage* cMsg = mDecodeData->mMessage;\r
-  uint32_t ClientTime = cMsg->U32Data(mDecodeData->Sub0x13Start+2);\r
-\r
-  tmpMsg = MsgBuilder->BuildPingMsg(mDecodeData->mClient, ClientTime);\r
-  mDecodeData->mClient->SendUDPMessage(tmpMsg);*/\r
-\r
-  nChar->SetLastUsedObject( mRawItemID );\r
-\r
-  if ( nClient->IsInRemoveActorMode() == true )\r
-  {\r
-    if ( WorldActors->IsDynamicActor( mRawItemID ) == true )\r
-    {\r
-      WorldActors->DelWorldActor( nClient, mRawItemID );\r
-      mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-      return true;\r
-    }\r
-    else\r
-      Chat->send( nClient, CHAT_DIRECT, "System", "This is not an dynamic worldactor. To remove it please type @remove <rawID>" );\r
-  }\r
-\r
-  if ( gDevDebug )\r
-  {\r
-    Console->Print( "Char at y=%f (0x%04x) z=%f (0x%04x) x=%f (0x%04x)", ( float )( nChar->Coords.mY - 32000 ), nChar->Coords.mY, ( float )( nChar->Coords.mZ - 32000 ), nChar->Coords.mZ, ( float )( nChar->Coords.mX - 32000 ), nChar->Coords.mX );\r
-    if ( mRawItemID & 1023 )\r
-      Console->Print( "using item %d (0x%08x)", mRawItemID, mRawItemID );\r
-    else\r
-      Console->Print( "using item %d (0x%08x) [dat entry %d (0x%08x)]", mRawItemID, mRawItemID, mRawItemID / 1024 - 1, mRawItemID / 1024 - 1 );\r
-  }\r
-\r
-  if ( nClient->GetDebugMode( DBG_ITEMID ) )\r
-  {\r
-    if ( mRawItemID & 1023 )\r
-      snprintf( DbgMessage, 128, "using item [raw: %d (0x%08x)]", mRawItemID, mRawItemID );\r
-    else\r
-      snprintf( DbgMessage, 128, "using item %d (0x%08x) [raw: %d (0x%08x)]", mRawItemID / 1024 - 1, mRawItemID / 1024 - 1, mRawItemID, mRawItemID );\r
-    Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-  }\r
-\r
-  PWorld* CurrentWorld = Worlds->GetWorld( nChar->GetLocation() );\r
-  if ( CurrentWorld )\r
-  {\r
-    if ( WorldActors->IsDynamicActor( mRawItemID ) == true )\r
-    {\r
-      tHandleDynamicActor = true;\r
-      if ( gDevDebug )\r
-        Console->Print( "%s Dynamic actor found, processing...", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    }\r
-\r
-    if ( mRawItemID & 1023 && tHandleDynamicActor == false ) // non-furniture objects\r
-    {\r
-      if ( mRawItemID > 0x80 ) // maybe door\r
-      {\r
-        if ( nClient->GetDebugMode( DBG_ITEMID ) )\r
-        {\r
-          snprintf( DbgMessage, 128, "Door : %d", mRawItemID - 0x80 );\r
-          Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-        }\r
-        const PDoorTemplate* tDoor = CurrentWorld->GetDoor( mRawItemID - 0x80 );\r
-        if ( tDoor )\r
-        {\r
-          if ( tDoor->IsTriggeredDoor() )\r
-          {\r
-            tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, mRawItemID );\r
-            nClient->SendUDPMessage( tmpMsg );\r
-          }\r
-          else\r
-          {\r
-            if ( gDevDebug )\r
-              Console->Print( "%s Opening %s door %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), ( tDoor->IsDoubleDoor() ? "double" : "simple" ), mRawItemID - 0x80 );\r
-            tmpMsg = MsgBuilder->BuildDoorOpenMsg( mRawItemID, tDoor->IsDoubleDoor() );\r
-            ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-          }\r
-          mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-        }\r
-      }\r
-      if ( !( mDecodeData->mState & DECODE_ACTION_DONE ) ) // else might be PC, NPC, VHC\r
-      {\r
-        if ( gDevDebug )\r
-          Console->Print( "%s Clicking on char, npc or vhc %d (%x) - time = %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID, mRawItemID, GameServer->GetGameTime() );\r
-\r
-        if ( PSpawnedVehicles::IsPotentialSpawnedVehicle( mRawItemID ) )\r
-        {\r
-          bool vhcFound = false;\r
-\r
-          if ( nChar->GetSeatInUse() == seat_none ) // Refuse if Char is already sitting somewhere\r
-          {\r
-            PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mRawItemID );\r
-            if ( tVhc )\r
-            {\r
-              if ( gDevDebug )\r
-                Console->Print( "%s Using vhc %d (0x%04x)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID, mRawItemID );\r
-              vhcFound = true;\r
-\r
-              if ( tVhc->GetInformation().GetOwnerCharId() ==  nChar->GetID() ) // Requester is the owner\r
-              {\r
-                PUdpVhcUse::DoFreeSitting( nClient,  tVhc, mRawItemID );\r
-              }\r
-              else // Requester is not the owner\r
-              {\r
-                if ( tVhc->GetNumSeats() == 1 ) // single seat vhc\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 17, mRawItemID ); // "Not your vhc" msg\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                } // multi seats vhc\r
-                else if ( ! tVhc->IsCharInside( tVhc->GetInformation().GetOwnerCharId() ) )\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 18, mRawItemID ); // "Owner not on board" msg\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-                else if ( tVhc->GetNbFreeSeats() == 0 )\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 5, mRawItemID ); // "No free seat" msg\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-                else\r
-                {\r
-                  // Send request to owner\r
-                  PClient* ownerClient = ClientManager->getClientByChar( tVhc->GetInformation().GetOwnerCharId() );\r
-                  if ( ownerClient )\r
-                  {\r
-                    PChar* ownerChar = ownerClient->GetChar();\r
-                    // We could check for valid allowed access before adding a new one\r
-                    uint32_t newReqId = ownerChar->GetVhcAccessRequestList()->Add( nChar->GetID(), tVhc->GetInformation().GetVehicleId() );\r
-                    if ( newReqId )\r
-                    {\r
-                      tmpMsg = MsgBuilder->BuildVhcAccessRequestMsg( ownerClient, newReqId, nChar->GetID(), nClient->GetID(), tVhc->GetInformation().GetVehicleId() );\r
-                      ownerClient->SendUDPMessage( tmpMsg );\r
-                      tmpMsg = MsgBuilder->BuildText100Msg( nClient, 19, mRawItemID ); // "req transmitted" msg\r
-                      nClient->SendUDPMessage( tmpMsg );\r
-                    }\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID ); // Undefined failure / Owner not available\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-                }\r
-              }\r
-              //////// Msg100 id\r
-              //22 can't use that seat\r
-            }\r
-            else if (( nChar->GetLocation() == PWorlds::mNcSubwayWorldId ) && Subway->IsValidSubwayCab( mRawItemID ) && ( nChar->GetSeatInUse() == seat_none ) ) // Entering subway\r
-            {\r
-              vhcFound = true;\r
-              if ( Subway->IsDoorOpen( mRawItemID, GameServer->GetGameTime() ) )\r
-              {\r
-                uint8_t freeSeat = Subway->GetFreeSeat( mRawItemID );\r
-                if ( freeSeat && Subway->SetSeatUser( mRawItemID, freeSeat, nChar->GetID() ) )\r
-                {\r
-                  nChar->SetSeatInUse( seat_subway, mRawItemID, freeSeat );\r
-                  tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, mRawItemID, freeSeat );\r
-                  ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-              else\r
-              {\r
-                tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, mRawItemID );\r
-                nClient->SendUDPMessage( tmpMsg );\r
-              }\r
-            }\r
-            // else error: invalid vhc\r
-          } // else char alreay sitting\r
-          if ( vhcFound )\r
-            mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-        }\r
-\r
-        if ( !( mDecodeData->mState & DECODE_ACTION_DONE ) ) // not a vhc\r
-        {\r
-          // Is it a PC ?\r
-          PClient* tClient;\r
-          if (( tClient = CurrentWorld->GetClientByCharLocalId( mRawItemID ) ) )\r
-          {\r
-            /*if(gDevDebug)*/\r
-            Console->Print( "%s clicking on PC %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID );\r
-            tmpMsg = MsgBuilder->BuildCharInteractionMenuMsg( nClient, mRawItemID );\r
-            nClient->SendUDPMessage( tmpMsg );\r
-            mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-          }\r
-        }\r
-\r
-        if ( !( mDecodeData->mState & DECODE_ACTION_DONE ) ) // not a vhc nor a pc\r
-        {\r
-          //Console->Print(">>> Searching world");\r
-          // Is it a NPC ?\r
-          PNPC* targetNPC = 0;\r
-          PNPCWorld* currentNPCWorld = NPCManager->GetWorld( nChar->GetLocation() );\r
-          if ( currentNPCWorld )\r
-          {\r
-              //Console->Print(">>> Searching NPC (SQL Version)");\r
-            targetNPC = currentNPCWorld->GetNPC( mRawItemID );\r
-            if(!targetNPC)\r
-            {\r
-                //Console->Print(">>> Searching NPC (DEF Version)");\r
-                // Note to myself: This is UGLY!!!! and BAD!!! but it works for now. CHANGE THIS!\r
-                targetNPC = currentNPCWorld->GetNPC( mRawItemID - 255 );\r
-            }\r
-          }\r
-          if ( targetNPC )\r
-          {\r
-            /*if(gDevDebug)*/\r
-            Console->Print( "%s Player talks to NPC %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID );\r
-            //if(gDevDebug) tContainer->Dump();\r
-\r
-            // Well its not "start a conversation" its more "User clicked NPC, do anything with it (Trade, script,...)\r
-            targetNPC->StartConversation(nClient);\r
-\r
-            //tmpMsg = MsgBuilder->BuildTraderItemListMsg( nClient, mRawItemID );\r
-            //tmpMsg->Dump();\r
-            //nClient->FragmentAndSendUDPMessage( tmpMsg, 0xac );\r
-          }\r
-        }\r
-\r
-        mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-      }\r
-    }\r
-    else // furniture objects\r
-    {\r
-      const PFurnitureItemTemplate* tFurnitureTemplate = NULL;\r
-      const PDefWorldModel* tFurnitureModel = NULL;\r
-      if ( tHandleDynamicActor == false )\r
-      {\r
-        // We have an STATIC ACTOR, which means we DONT KNOW the FUNCTION VALUE from pak_worldmodel.def yet\r
-        // (the setentry one). So we need to get it over the .dat file:\r
-\r
-        // Dat files have smaller IDs\r
-        ItemID = mRawItemID / 1024 - 1;\r
-\r
-        // Now grab the template from .dat file\r
-        tFurnitureTemplate = CurrentWorld->GetFurnitureItemTemplate( ItemID );\r
-\r
-        // Then get the FUNCTION VALUE as furniture model so we can access its subvalues etc\r
-        tFurnitureModel = CurrentWorld->GetFurnitureItemModel( ItemID );\r
-      }\r
-      else\r
-      {\r
-        // We have an DYNAMIC ACTOR, which means we DO KNOW the FUNCTION VALUE (stored in SQL).\r
-\r
-        // First, assign the RawID to the "real" itemID, which is used for several objects to identify them clientside\r
-        ItemID = mRawItemID;\r
-\r
-        // Now get the get the function value:\r
-        int tFunctionVal = WorldActors->GetWorldActorFunctionID( mRawItemID );\r
-\r
-        // Then get the FUNCTION VALUE as furniture model so we can access its subvalues etc\r
-        tFurnitureModel = GameDefs->WorldModels()->GetDef( tFunctionVal );\r
-\r
-        if ( gDevDebug )\r
-          Console->Print( "%s Processing dynmic actor %d with Functionvalue %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID, tFunctionVal );\r
-      }\r
-\r
-      if ( tFurnitureModel ) // valid active furniture (else invalid or passive furniture)\r
-      {\r
-        if ( nClient->GetDebugMode( DBG_ITEMID ) )\r
-        {\r
-          snprintf( DbgMessage, 128, "Item : %s", tFurnitureModel->GetName().c_str() );\r
-          Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-        }\r
-\r
-        if ( tFurnitureModel->GetUseFlags() & ufChair )\r
-        {\r
-          uint32_t cSeatObjectId;\r
-          PSeatType cSeatType = nChar->GetSeatInUse( &cSeatObjectId );\r
-          if (( cSeatType == seat_none ) || ( cSeatType == seat_chair ) )\r
-          {\r
-            if ( CurrentWorld->CharUseChair( nClient->GetLocalID(), ItemID ) )\r
-            {\r
-              if ( gDevDebug )\r
-                Console->Print( "%s Localchar %d was previously using chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nClient->GetLocalID(), cSeatObjectId );\r
-              if (( cSeatType ) && ( cSeatObjectId != ItemID ) )\r
-              {\r
-                CurrentWorld->CharLeaveChair( nClient->GetLocalID(), cSeatObjectId );\r
-              }\r
-              nChar->SetSeatInUse( seat_chair, ItemID );\r
-              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )\r
-              {\r
-                tFurnitureTemplate->GetFrontPos( &( nChar->Coords.mX ), &( nChar->Coords.mY ), &( nChar->Coords.mZ ) );\r
-                //(nChar->Coords).mLR = tFurnitureTemplate->GetFrontLR();\r
-              }\r
-              else\r
-              {\r
-                WorldActors->GetFrontPos( mRawItemID, &( nChar->Coords.mX ), &( nChar->Coords.mY ), &( nChar->Coords.mZ ) );\r
-                //(nChar->Coords).mLR = WorldActors->GetFrontLR();\r
-              }\r
-\r
-              tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, mRawItemID );\r
-              ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-            }\r
-            else\r
-            {\r
-              tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, mRawItemID ); // "Already in use" msg\r
-              nClient->SendUDPMessage( tmpMsg );\r
-            }\r
-          }\r
-\r
-          mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-        }\r
-        else\r
-        {\r
-          if ( gDevDebug )\r
-            Console->Print( "%s Item function type: %d value: %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), tFurnitureModel->GetFunctionType(), tFurnitureModel->GetFunctionValue() );\r
-\r
-          DbgMessage[0] = 0;\r
-          switch ( tFurnitureModel->GetFunctionType() )\r
-          {\r
-            case 6: //Respawn Station (GenRep)\r
-            {\r
-              uint32_t nLocation = nChar->GetLocation();\r
-              uint16_t nEntity;\r
-              if ( Worlds->IsPotentialAppartement( nLocation ) )\r
-              {\r
-                nLocation = 0xffffffff; // (uint32_t)-1;\r
-                nEntity = 0xffff; //(uint16_t)-1;\r
-              }\r
-              else\r
-              {\r
-                //nEntity = MySQL->GetWorldItemOption(mRawItemID/256, nLocation, 1);\r
-                // This is a kind of nearly-not-hardcoded-hack ...\r
-                int nEntityInt = 0;\r
-                if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )\r
-                {\r
-                  nEntityInt = GameDefs->Respawns()->GetRespawnEntity( nChar->GetLocation(), tFurnitureTemplate->GetLinkedObjectID() );\r
-                }\r
-                else\r
-                {\r
-                  nEntityInt = GameDefs->Respawns()->GetRespawnEntity( nChar->GetLocation(), WorldActors->GetLinkedObjectID( mRawItemID ) );\r
-                }\r
-\r
-                nEntity = ( nEntityInt < 0 ? 0xffff : ( uint16_t )nEntityInt );\r
-              }\r
-\r
-              tmpMsg = MsgBuilder->BuildCharUseGenrepMsg( nClient, mRawItemID, nLocation, nEntity );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 7: //GoGuardian\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseGogoMsg( nClient );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 9: //Appartement Eingang\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseLiftMsg( nClient, mRawItemID, tFurnitureModel->GetFunctionValue() );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 10: //Appartement Ein/Ausgang\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseLiftMsg( nClient, mRawItemID, 0 );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 15: //HOLOMATCH EXIT\r
-            {\r
-              // temp hack + wrong entity... guess it works same as function 20\r
-              uint32_t HoloNum = nChar->GetLocation() - 90000; // value 1 to 16, to transalte to 540..547 550..557 for worldmodel.def\r
-\r
-              const PDefWorldModel* tHoloExitModel = GameDefs->WorldModels()->GetDef( 539 + HoloNum + ( HoloNum > 8 ? 2 : 0 ) );\r
-              if ( tHoloExitModel && ( tHoloExitModel->GetFunctionType() == 14 ) ) // we use the Holomatch entry. Takes care of bad zone id\r
-              {\r
-                const PDefAppPlace* nAppPlace = GameDefs->AppPlaces()->GetDef( tHoloExitModel->GetFunctionValue() );\r
-                if ( nAppPlace )\r
-                {\r
-                  uint32_t Location = nAppPlace->GetExitWorldID();\r
-                  uint16_t Entity = nAppPlace->GetExitWorldEntity();\r
-                  uint8_t SewerLevel = 0;\r
-\r
-                  tmpMsg = MsgBuilder->BuildChangeLocationMsg( nClient, Location, Entity, SewerLevel, 0 ); //mRawItemID\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                  if ( gDevDebug )\r
-                    Console->Print( "%s Holoexit: Client[%d] Char[%s] moving to zone %d (%s)", Console->ColorText( GREEN, BLACK, "[Debug]" ), nClient->GetID(), nChar->GetName().c_str(), Location, nAppPlace->GetName().c_str() );\r
-                  if ( gDevDebug )\r
-                    Console->Print( "%s Location=%d Entity=%d Level=%d", Console->ColorText( CYAN, BLACK, "[Debug]" ), Location, Entity, SewerLevel );\r
-                }\r
-                else\r
-                {\r
-                  Console->Print( "%s Client[%d] Char[%s] invalid destination %d (appplaces.def)", Console->ColorText( RED, BLACK, "[Warning]" ), nClient->GetID(), nChar->GetName().c_str(), tFurnitureModel->GetFunctionValue() );\r
-                }\r
-              }\r
-              else\r
-              {\r
-                Console->Print( "%s Client[%d] Char[%s] invalid holoentry used %d", Console->ColorText( RED, BLACK, "[Warning]" ), nClient->GetID(), nChar->GetName().c_str(), tFurnitureModel->GetFunctionValue() );\r
-              }\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 18: // "WORLDCHANGEACTOR"\r
-            case 20: // "DATFILE WORLDCHANGE ACTOR"\r
-            case 29: //Underground Exit\r
-            {\r
-              const PDefAppPlace* nAppPlace;\r
-              if ( tFurnitureModel->GetFunctionType() == 29 )\r
-              {\r
-                nAppPlace = GameDefs->AppPlaces()->GetDef( nChar->GetLocation() ); // special for UG exit\r
-              }\r
-              else\r
-              {\r
-                nAppPlace = GameDefs->AppPlaces()->GetDef( tFurnitureModel->GetFunctionValue() );\r
-              }\r
-              if ( nAppPlace )\r
-              {\r
-                uint32_t Location = nAppPlace->GetExitWorldID();\r
-                uint16_t Entity = nAppPlace->GetExitWorldEntity();\r
-                uint8_t SewerLevel = 0;\r
-                //if(((tFurnitureModel->GetFunctionType() == 20) && nAppPlace->GetSewerLevel()) || (tFurnitureModel->GetFunctionType() == 29))\r
-                if (( tFurnitureModel->GetFunctionType() == 20 ) || ( tFurnitureModel->GetFunctionType() == 29 ) )\r
-                {\r
-                  SewerLevel = 1;\r
-                }\r
-\r
-                tmpMsg = MsgBuilder->BuildChangeLocationMsg( nClient, Location, Entity, SewerLevel, mRawItemID ); //mRawItemID\r
-                nClient->SendUDPMessage( tmpMsg );\r
-                if ( gDevDebug )\r
-                {\r
-                  Console->Print( "%s Dungeon in/out: Client[%d] Char[%s] moving to zone %d, %s", Console->ColorText( GREEN, BLACK, "[Debug]" ), nClient->GetID(), nChar->GetName().c_str(), Location, nAppPlace->GetName().c_str() );\r
-                  Console->Print( "%s Location=%d Entity=%d Level=%d", Console->ColorText( CYAN, BLACK, "[Debug]" ), Location, Entity, SewerLevel );\r
-                  Console->Print( "%s Function: %d, Value: %d - Sewer level in appplaces.def for this point: %d", Console->ColorText( CYAN, BLACK, "[Debug]" ), tFurnitureModel->GetFunctionType(), tFurnitureModel->GetFunctionValue(), nAppPlace->GetSewerLevel() );\r
-                  Console->Print( "%s Worldmodel id: %d", Console->ColorText( CYAN, BLACK, "[Debug]" ), tFurnitureModel->GetID() );\r
-                }\r
-              }\r
-              else\r
-              {\r
-                Console->Print( "%s Client[%d] Char[%s] invalid destination %d (appplaces.def)", Console->ColorText( RED, BLACK, "[Warning]" ), nClient->GetID(), nChar->GetName().c_str(), tFurnitureModel->GetFunctionValue() );\r
-                // send a "refused" msg ?\r
-              }\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              //nextAnalyser = new PUdpCharJump(mDecodeData);\r
-              break;\r
-            }\r
-\r
-            case 2: //Terminal\r
-            case 3: //Outfitter\r
-            case 16: //HOLOMATCH REFRESH\r
-            case 17: //HOLOMATCH HEAL & Recreation units\r
-            case 26: //Outpost Switch\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 31: //Venture Warp Station\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseVentureWarpMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 28: //Fahrzeug Depot Interface\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseVhcTerminalMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 11: //Appartement Klingel/�ffner\r
-            {\r
-              if ( Appartements->CanFreelyEnter( nChar, nChar->GetLocation() ) )\r
-              {\r
-                if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )\r
-                {\r
-                  if ( tFurnitureTemplate->GetLinkedObjectID() )\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );\r
-                    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-                }\r
-                else\r
-                {\r
-                  if ( WorldActors->GetLinkedObjectID( mRawItemID ) )\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + WorldActors->GetLinkedObjectID( mRawItemID ), CurrentWorld->GetDoor( WorldActors->GetLinkedObjectID( mRawItemID ) )->IsDoubleDoor() );\r
-                    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-                }\r
-              }\r
-              else\r
-              {\r
-                tmpMsg = MsgBuilder->BuildFurnitureActivateMsg( nClient, mRawItemID, 5 ); // Ring\r
-                ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-              }\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 12: //Standard Button\r
-            {\r
-              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )\r
-              {\r
-                if ( tFurnitureTemplate->GetLinkedObjectID() )\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );\r
-                  ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-              else\r
-              {\r
-                if ( WorldActors->GetLinkedObjectID( mRawItemID ) )\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + WorldActors->GetLinkedObjectID( mRawItemID ), CurrentWorld->GetDoor( WorldActors->GetLinkedObjectID( mRawItemID ) )->IsDoubleDoor() );\r
-                  ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 13: //Hack Button\r
-            {\r
-              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )\r
-              {\r
-                if ( tFurnitureTemplate->GetLinkedObjectID() )\r
-                {\r
-                  if ( nClient->GetAccountLevel() >= PAL_GM ) // Allow GameMasters and higher to just bypass HackButtons\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );\r
-                    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 106 ); // Damn, locked!\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-              else\r
-              {\r
-                uint32_t linkobjID = WorldActors->GetLinkedObjectID( mRawItemID );\r
-                if ( linkobjID )\r
-                {\r
-                  if ( nClient->GetAccountLevel() >= PAL_GM ) // Allow GameMasters and higher to just bypass HackButtons\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + linkobjID, CurrentWorld->GetDoor( linkobjID )->IsDoubleDoor() );\r
-                    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 106 ); // Damn, locked!\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            case 23: //EINTRITTSGELD BUTTON\r
-            {\r
-              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )\r
-              {\r
-                if ( tFurnitureTemplate->GetLinkedObjectID() )\r
-                {\r
-                  uint32_t OldCash = nChar->GetCash();\r
-                  uint32_t DoorFee = ( uint32_t )tFurnitureModel->GetFunctionValue();\r
-                  if ( OldCash >= DoorFee )\r
-                  {\r
-                    uint32_t NewCash = nChar->SetCash( OldCash - DoorFee );\r
-                    PMessage* tmpMsg_cash = MsgBuilder->BuildCharMoneyUpdateMsg( nClient, NewCash );\r
-                    nClient->SendUDPMessage( tmpMsg_cash );\r
-                    tmpMsg_cash = NULL;\r
-                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );\r
-                    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 12 );  // You dont have enough money!\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-              else\r
-              {\r
-                uint32_t linkobjID = WorldActors->GetLinkedObjectID( mRawItemID );\r
-                if ( linkobjID )\r
-                {\r
-                  uint32_t OldCash = nChar->GetCash();\r
-                  uint32_t DoorFee = ( uint32_t )tFurnitureModel->GetFunctionValue();\r
-                  if ( OldCash >= DoorFee )\r
-                  {\r
-                    uint32_t NewCash = nChar->SetCash( OldCash - DoorFee );\r
-                    PMessage* tmpMsg_cash = MsgBuilder->BuildCharMoneyUpdateMsg( nClient, NewCash );\r
-                    nClient->SendUDPMessage( tmpMsg_cash );\r
-                    tmpMsg_cash = NULL;\r
-                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + linkobjID, CurrentWorld->GetDoor( linkobjID )->IsDoubleDoor() );\r
-                    ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-                  }\r
-                  else\r
-                  {\r
-                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 12 );  // You dont have enough money!\r
-                    nClient->SendUDPMessage( tmpMsg );\r
-                  }\r
-                }\r
-                else\r
-                {\r
-                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );\r
-                  nClient->SendUDPMessage( tmpMsg );\r
-                }\r
-              }\r
-\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 1: //Itemcontainer\r
-            {\r
-              // TODO: Add check if container is already open / Make containers persistent\r
-              // PContainer* tContainer = World->GetContainer(mRawItemID);\r
-              PContainer* tContainer = new PContainerAutoCompactOnClose( INV_CABINET_MAXSLOTS );\r
-              int functionVal = tFurnitureModel->GetFunctionValue();\r
-              if ( functionVal <= 5 ) // force full random for cabinets for item testing\r
-                functionVal = -1;\r
-              tContainer->RandomFill( INV_CABINET_MAXSLOTS, functionVal );\r
-\r
-              /*nItem = new PItem(19, 1, 250, 250, 250, 250, 250, 250);\r
-              if(nItem->GetItemID());\r
-                tContainer->AddItem(nItem);*/\r
-              if ( gDevDebug ) Console->Print( "%s Temporary container created", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-              //if(gDevDebug) tContainer->Dump();\r
-              if ( tContainer->StartUse( nChar->GetID() ) )\r
-              {\r
-                nChar->SetContainerInExclusiveUse( tContainer );\r
-                tmpMsg = MsgBuilder->BuildCharOpenContainerMsg( nClient, mRawItemID, tContainer );\r
-                //tmpMsg->Dump();\r
-                nClient->FragmentAndSendUDPMessage( tmpMsg, 0x05 );\r
-              }\r
-              else\r
-              {\r
-                tmpMsg = MsgBuilder->BuildFurnitureActivateMsg( nClient, mRawItemID, 10 );\r
-                nClient->SendUDPMessage( tmpMsg );\r
-                tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, mRawItemID );\r
-                nClient->SendUDPMessage( tmpMsg );\r
-              }\r
-\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 32: // Text message\r
-            {\r
-              tmpMsg = MsgBuilder->BuildText100Msg( nClient, ( uint8_t )( 255 & tFurnitureModel->GetFunctionValue() ), mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            // Temp placeholder implementations ============================\r
-            case 4: //Trader\r
-            {\r
-              snprintf( DbgMessage, 128, "That's a trader" );\r
-              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 5: //Mineral\r
-            {\r
-              snprintf( DbgMessage, 128, "That's some minerals" );\r
-              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 8: //Hackterminal\r
-            {\r
-              snprintf( DbgMessage, 128, "That's a hacking terminal" );\r
-              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 14: //HOLOMATCH ENTRANCE\r
-            {\r
-              snprintf( DbgMessage, 128, "That's an holomatch entrance" );\r
-              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 19: //CLANTERMINAL\r
-            {\r
-              snprintf( DbgMessage, 128, "That's a clan terminal" );\r
-              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 25: //EXPLOSIVE\r
-            {\r
-              snprintf( DbgMessage, 128, "That's explosive !" );\r
-              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-            case 0: //May be roadsign if touchable\r
-            {\r
-              if ( ( tFurnitureModel->GetUseFlags() & ufTouchable ) ) // Touchable ?\r
-              {\r
-                snprintf( DbgMessage, 128, "You're at %s", tFurnitureModel->GetName().c_str() );\r
-                Chat->send( nClient, CHAT_GM, "Information", DbgMessage );\r
-                tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-                nClient->SendUDPMessage( tmpMsg );\r
-                mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-                break;\r
-              }\r
-              // else we continue to undefined\r
-            }\r
-            case 27: //Old goguardian\r
-              //case 21: //LOCATION FOR 20\r
-              //case 22: //\r
-            case 24: //TUTORIALEXIT\r
-              //case 30: //Static FX (Value=Type. 1=Fire 2=Smoke 3=Steam 4=Sparkle)\r
-            {\r
-              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );\r
-              nClient->SendUDPMessage( tmpMsg );\r
-              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-              break;\r
-            }\r
-\r
-            default:\r
-              break;\r
-          }\r
-        }\r
-      }\r
-      else\r
-      {\r
-        if ( gDevDebug )\r
-          Console->Print( "%s Item not known from world template (maybe seen as PASSIVE ?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-      }\r
-    }\r
-\r
-    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] PUdpUseObject::DoAction : No World defined for client %d (char %d)", nClient->GetID(), nChar->GetID() );\r
-    mDecodeData->mState = DECODE_ACTION_FAILED | DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-/**** PUdpCloseItemContainer ****/\r
-\r
-PUdpCloseItemContainer::PUdpCloseItemContainer( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x27";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpCloseItemContainer::Analyse()\r
-{\r
-  mDecodeData->mName << "=Closing item container";\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpCloseItemContainer::DoAction()\r
-{\r
-//  PClient* nClient = mDecodeData->mClient;\r
-//  PChar* nChar = nClient->GetChar();\r
-\r
-  PChar* nChar = mDecodeData->mClient->GetChar();\r
-  PContainer* tContainer = nChar->GetContainerInExclusiveUse();\r
-  if ( tContainer )\r
-  {\r
-    nChar->SetContainerInExclusiveUse( NULL );\r
-    tContainer->EndUse( nChar->GetID() );\r
-    if ( ! tContainer->GetOwnerId() )\r
-    {\r
-      delete tContainer;\r
-      if ( gDevDebug ) Console->Print( "%s Temporary container deleted", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );\r
-    }\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+uint32_t gVhcId = 0x3ff;
+
+/**** PUdpVhcMove ****/
+
+PUdpUseObject::PUdpUseObject( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x17";
+}
+
+PUdpMsgAnalyser* PUdpUseObject::Analyse()
+{
+  mDecodeData->mName << "=Object use";
+
+  mRawItemID = mDecodeData->mMessage->U32Data( mDecodeData->Sub0x13Start + 8 );
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpUseObject::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* nChar = nClient->GetChar();
+  uint32_t ItemID;
+  char DbgMessage[128];
+  PMessage* tmpMsg;
+
+  bool tHandleDynamicActor = false;
+
+  /*PMessage* cMsg = mDecodeData->mMessage;
+  uint32_t ClientTime = cMsg->U32Data(mDecodeData->Sub0x13Start+2);
+
+  tmpMsg = MsgBuilder->BuildPingMsg(mDecodeData->mClient, ClientTime);
+  mDecodeData->mClient->SendUDPMessage(tmpMsg);*/
+
+  nChar->SetLastUsedObject( mRawItemID );
+
+  if ( nClient->IsInRemoveActorMode() == true )
+  {
+    if ( WorldActors->IsDynamicActor( mRawItemID ) == true )
+    {
+      WorldActors->DelWorldActor( nClient, mRawItemID );
+      mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+      return true;
+    }
+    else
+      Chat->send( nClient, CHAT_DIRECT, "System", "This is not an dynamic worldactor. To remove it please type @remove <rawID>" );
+  }
+
+  if ( gDevDebug )
+  {
+    Console->Print( "Char at y=%f (0x%04x) z=%f (0x%04x) x=%f (0x%04x)", ( float )( nChar->Coords.mY - 32000 ), nChar->Coords.mY, ( float )( nChar->Coords.mZ - 32000 ), nChar->Coords.mZ, ( float )( nChar->Coords.mX - 32000 ), nChar->Coords.mX );
+    if ( mRawItemID & 1023 )
+      Console->Print( "using item %d (0x%08x)", mRawItemID, mRawItemID );
+    else
+      Console->Print( "using item %d (0x%08x) [dat entry %d (0x%08x)]", mRawItemID, mRawItemID, mRawItemID / 1024 - 1, mRawItemID / 1024 - 1 );
+  }
+
+  if ( nClient->GetDebugMode( DBG_ITEMID ) )
+  {
+    if ( mRawItemID & 1023 )
+      snprintf( DbgMessage, 128, "using item [raw: %d (0x%08x)]", mRawItemID, mRawItemID );
+    else
+      snprintf( DbgMessage, 128, "using item %d (0x%08x) [raw: %d (0x%08x)]", mRawItemID / 1024 - 1, mRawItemID / 1024 - 1, mRawItemID, mRawItemID );
+    Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+  }
+
+  PWorld* CurrentWorld = Worlds->GetWorld( nChar->GetLocation() );
+  if ( CurrentWorld )
+  {
+    if ( WorldActors->IsDynamicActor( mRawItemID ) == true )
+    {
+      tHandleDynamicActor = true;
+      if ( gDevDebug )
+        Console->Print( "%s Dynamic actor found, processing...", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    }
+
+    if ( mRawItemID & 1023 && tHandleDynamicActor == false ) // non-furniture objects
+    {
+      if ( mRawItemID > 0x80 ) // maybe door
+      {
+        if ( nClient->GetDebugMode( DBG_ITEMID ) )
+        {
+          snprintf( DbgMessage, 128, "Door : %d", mRawItemID - 0x80 );
+          Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+        }
+        const PDoorTemplate* tDoor = CurrentWorld->GetDoor( mRawItemID - 0x80 );
+        if ( tDoor )
+        {
+          if ( tDoor->IsTriggeredDoor() )
+          {
+            tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, mRawItemID );
+            nClient->SendUDPMessage( tmpMsg );
+          }
+          else
+          {
+            if ( gDevDebug )
+              Console->Print( "%s Opening %s door %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), ( tDoor->IsDoubleDoor() ? "double" : "simple" ), mRawItemID - 0x80 );
+            tmpMsg = MsgBuilder->BuildDoorOpenMsg( mRawItemID, tDoor->IsDoubleDoor() );
+            ClientManager->UDPBroadcast( tmpMsg, nClient );
+          }
+          mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+        }
+      }
+      if ( !( mDecodeData->mState & DECODE_ACTION_DONE ) ) // else might be PC, NPC, VHC
+      {
+        if ( gDevDebug )
+          Console->Print( "%s Clicking on char, npc or vhc %d (%x) - time = %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID, mRawItemID, GameServer->GetGameTime() );
+
+        if ( PSpawnedVehicles::IsPotentialSpawnedVehicle( mRawItemID ) )
+        {
+          bool vhcFound = false;
+
+          if ( nChar->GetSeatInUse() == seat_none ) // Refuse if Char is already sitting somewhere
+          {
+            PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mRawItemID );
+            if ( tVhc )
+            {
+              if ( gDevDebug )
+                Console->Print( "%s Using vhc %d (0x%04x)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID, mRawItemID );
+              vhcFound = true;
+
+              if ( tVhc->GetInformation().GetOwnerCharId() ==  nChar->GetID() ) // Requester is the owner
+              {
+                PUdpVhcUse::DoFreeSitting( nClient,  tVhc, mRawItemID );
+              }
+              else // Requester is not the owner
+              {
+                if ( tVhc->GetNumSeats() == 1 ) // single seat vhc
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 17, mRawItemID ); // "Not your vhc" msg
+                  nClient->SendUDPMessage( tmpMsg );
+                } // multi seats vhc
+                else if ( ! tVhc->IsCharInside( tVhc->GetInformation().GetOwnerCharId() ) )
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 18, mRawItemID ); // "Owner not on board" msg
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+                else if ( tVhc->GetNbFreeSeats() == 0 )
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 5, mRawItemID ); // "No free seat" msg
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+                else
+                {
+                  // Send request to owner
+                  PClient* ownerClient = ClientManager->getClientByChar( tVhc->GetInformation().GetOwnerCharId() );
+                  if ( ownerClient )
+                  {
+                    PChar* ownerChar = ownerClient->GetChar();
+                    // We could check for valid allowed access before adding a new one
+                    uint32_t newReqId = ownerChar->GetVhcAccessRequestList()->Add( nChar->GetID(), tVhc->GetInformation().GetVehicleId() );
+                    if ( newReqId )
+                    {
+                      tmpMsg = MsgBuilder->BuildVhcAccessRequestMsg( ownerClient, newReqId, nChar->GetID(), nClient->GetID(), tVhc->GetInformation().GetVehicleId() );
+                      ownerClient->SendUDPMessage( tmpMsg );
+                      tmpMsg = MsgBuilder->BuildText100Msg( nClient, 19, mRawItemID ); // "req transmitted" msg
+                      nClient->SendUDPMessage( tmpMsg );
+                    }
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID ); // Undefined failure / Owner not available
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+                }
+              }
+              //////// Msg100 id
+              //22 can't use that seat
+            }
+            else if (( nChar->GetLocation() == PWorlds::mNcSubwayWorldId ) && Subway->IsValidSubwayCab( mRawItemID ) && ( nChar->GetSeatInUse() == seat_none ) ) // Entering subway
+            {
+              vhcFound = true;
+              if ( Subway->IsDoorOpen( mRawItemID, GameServer->GetGameTime() ) )
+              {
+                uint8_t freeSeat = Subway->GetFreeSeat( mRawItemID );
+                if ( freeSeat && Subway->SetSeatUser( mRawItemID, freeSeat, nChar->GetID() ) )
+                {
+                  nChar->SetSeatInUse( seat_subway, mRawItemID, freeSeat );
+                  tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, mRawItemID, freeSeat );
+                  ClientManager->UDPBroadcast( tmpMsg, nClient );
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+              else
+              {
+                tmpMsg = MsgBuilder->BuildText100Msg( nClient, 6, mRawItemID );
+                nClient->SendUDPMessage( tmpMsg );
+              }
+            }
+            // else error: invalid vhc
+          } // else char alreay sitting
+          if ( vhcFound )
+            mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+        }
+
+        if ( !( mDecodeData->mState & DECODE_ACTION_DONE ) ) // not a vhc
+        {
+          // Is it a PC ?
+          PClient* tClient;
+          if (( tClient = CurrentWorld->GetClientByCharLocalId( mRawItemID ) ) )
+          {
+            /*if(gDevDebug)*/
+            Console->Print( "%s clicking on PC %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID );
+            tmpMsg = MsgBuilder->BuildCharInteractionMenuMsg( nClient, mRawItemID );
+            nClient->SendUDPMessage( tmpMsg );
+            mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+          }
+        }
+
+        if ( !( mDecodeData->mState & DECODE_ACTION_DONE ) ) // not a vhc nor a pc
+        {
+          //Console->Print(">>> Searching world");
+          // Is it a NPC ?
+          PNPC* targetNPC = 0;
+          PNPCWorld* currentNPCWorld = NPCManager->GetWorld( nChar->GetLocation() );
+          if ( currentNPCWorld )
+          {
+              //Console->Print(">>> Searching NPC (SQL Version)");
+            targetNPC = currentNPCWorld->GetNPC( mRawItemID );
+            if(!targetNPC)
+            {
+                //Console->Print(">>> Searching NPC (DEF Version)");
+                // Note to myself: This is UGLY!!!! and BAD!!! but it works for now. CHANGE THIS!
+                targetNPC = currentNPCWorld->GetNPC( mRawItemID - 255 );
+            }
+          }
+          if ( targetNPC )
+          {
+            /*if(gDevDebug)*/
+            Console->Print( "%s Player talks to NPC %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID );
+            //if(gDevDebug) tContainer->Dump();
+
+            // Well its not "start a conversation" its more "User clicked NPC, do anything with it (Trade, script,...)
+            targetNPC->StartConversation(nClient);
+
+            //tmpMsg = MsgBuilder->BuildTraderItemListMsg( nClient, mRawItemID );
+            //tmpMsg->Dump();
+            //nClient->FragmentAndSendUDPMessage( tmpMsg, 0xac );
+          }
+        }
+
+        mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+      }
+    }
+    else // furniture objects
+    {
+      const PFurnitureItemTemplate* tFurnitureTemplate = NULL;
+      const PDefWorldModel* tFurnitureModel = NULL;
+      if ( tHandleDynamicActor == false )
+      {
+        // We have an STATIC ACTOR, which means we DONT KNOW the FUNCTION VALUE from pak_worldmodel.def yet
+        // (the setentry one). So we need to get it over the .dat file:
+
+        // Dat files have smaller IDs
+        ItemID = mRawItemID / 1024 - 1;
+
+        // Now grab the template from .dat file
+        tFurnitureTemplate = CurrentWorld->GetFurnitureItemTemplate( ItemID );
+
+        // Then get the FUNCTION VALUE as furniture model so we can access its subvalues etc
+        tFurnitureModel = CurrentWorld->GetFurnitureItemModel( ItemID );
+      }
+      else
+      {
+        // We have an DYNAMIC ACTOR, which means we DO KNOW the FUNCTION VALUE (stored in SQL).
+
+        // First, assign the RawID to the "real" itemID, which is used for several objects to identify them clientside
+        ItemID = mRawItemID;
+
+        // Now get the get the function value:
+        int tFunctionVal = WorldActors->GetWorldActorFunctionID( mRawItemID );
+
+        // Then get the FUNCTION VALUE as furniture model so we can access its subvalues etc
+        tFurnitureModel = GameDefs->WorldModels()->GetDef( tFunctionVal );
+
+        if ( gDevDebug )
+          Console->Print( "%s Processing dynmic actor %d with Functionvalue %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mRawItemID, tFunctionVal );
+      }
+
+      if ( tFurnitureModel ) // valid active furniture (else invalid or passive furniture)
+      {
+        if ( nClient->GetDebugMode( DBG_ITEMID ) )
+        {
+          snprintf( DbgMessage, 128, "Item : %s", tFurnitureModel->GetName().c_str() );
+          Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+        }
+
+        if ( tFurnitureModel->GetUseFlags() & ufChair )
+        {
+          uint32_t cSeatObjectId;
+          PSeatType cSeatType = nChar->GetSeatInUse( &cSeatObjectId );
+          if (( cSeatType == seat_none ) || ( cSeatType == seat_chair ) )
+          {
+            if ( CurrentWorld->CharUseChair( nClient->GetLocalID(), ItemID ) )
+            {
+              if ( gDevDebug )
+                Console->Print( "%s Localchar %d was previously using chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nClient->GetLocalID(), cSeatObjectId );
+              if (( cSeatType ) && ( cSeatObjectId != ItemID ) )
+              {
+                CurrentWorld->CharLeaveChair( nClient->GetLocalID(), cSeatObjectId );
+              }
+              nChar->SetSeatInUse( seat_chair, ItemID );
+              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )
+              {
+                tFurnitureTemplate->GetFrontPos( &( nChar->Coords.mX ), &( nChar->Coords.mY ), &( nChar->Coords.mZ ) );
+                //(nChar->Coords).mLR = tFurnitureTemplate->GetFrontLR();
+              }
+              else
+              {
+                WorldActors->GetFrontPos( mRawItemID, &( nChar->Coords.mX ), &( nChar->Coords.mY ), &( nChar->Coords.mZ ) );
+                //(nChar->Coords).mLR = WorldActors->GetFrontLR();
+              }
+
+              tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, mRawItemID );
+              ClientManager->UDPBroadcast( tmpMsg, nClient );
+            }
+            else
+            {
+              tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, mRawItemID ); // "Already in use" msg
+              nClient->SendUDPMessage( tmpMsg );
+            }
+          }
+
+          mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+        }
+        else
+        {
+          if ( gDevDebug )
+            Console->Print( "%s Item function type: %d value: %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), tFurnitureModel->GetFunctionType(), tFurnitureModel->GetFunctionValue() );
+
+          DbgMessage[0] = 0;
+          switch ( tFurnitureModel->GetFunctionType() )
+          {
+            case 6: //Respawn Station (GenRep)
+            {
+              uint32_t nLocation = nChar->GetLocation();
+              uint16_t nEntity;
+              if ( Worlds->IsPotentialAppartement( nLocation ) )
+              {
+                nLocation = 0xffffffff; // (uint32_t)-1;
+                nEntity = 0xffff; //(uint16_t)-1;
+              }
+              else
+              {
+                //nEntity = MySQL->GetWorldItemOption(mRawItemID/256, nLocation, 1);
+                // This is a kind of nearly-not-hardcoded-hack ...
+                int nEntityInt = 0;
+                if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )
+                {
+                  nEntityInt = GameDefs->Respawns()->GetRespawnEntity( nChar->GetLocation(), tFurnitureTemplate->GetLinkedObjectID() );
+                }
+                else
+                {
+                  nEntityInt = GameDefs->Respawns()->GetRespawnEntity( nChar->GetLocation(), WorldActors->GetLinkedObjectID( mRawItemID ) );
+                }
+
+                nEntity = ( nEntityInt < 0 ? 0xffff : ( uint16_t )nEntityInt );
+              }
+
+              tmpMsg = MsgBuilder->BuildCharUseGenrepMsg( nClient, mRawItemID, nLocation, nEntity );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 7: //GoGuardian
+            {
+              tmpMsg = MsgBuilder->BuildCharUseGogoMsg( nClient );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 9: //Appartement Eingang
+            {
+              tmpMsg = MsgBuilder->BuildCharUseLiftMsg( nClient, mRawItemID, tFurnitureModel->GetFunctionValue() );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 10: //Appartement Ein/Ausgang
+            {
+              tmpMsg = MsgBuilder->BuildCharUseLiftMsg( nClient, mRawItemID, 0 );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 15: //HOLOMATCH EXIT
+            {
+              // temp hack + wrong entity... guess it works same as function 20
+              uint32_t HoloNum = nChar->GetLocation() - 90000; // value 1 to 16, to transalte to 540..547 550..557 for worldmodel.def
+
+              const PDefWorldModel* tHoloExitModel = GameDefs->WorldModels()->GetDef( 539 + HoloNum + ( HoloNum > 8 ? 2 : 0 ) );
+              if ( tHoloExitModel && ( tHoloExitModel->GetFunctionType() == 14 ) ) // we use the Holomatch entry. Takes care of bad zone id
+              {
+                const PDefAppPlace* nAppPlace = GameDefs->AppPlaces()->GetDef( tHoloExitModel->GetFunctionValue() );
+                if ( nAppPlace )
+                {
+                  uint32_t Location = nAppPlace->GetExitWorldID();
+                  uint16_t Entity = nAppPlace->GetExitWorldEntity();
+                  uint8_t SewerLevel = 0;
+
+                  tmpMsg = MsgBuilder->BuildChangeLocationMsg( nClient, Location, Entity, SewerLevel, 0 ); //mRawItemID
+                  nClient->SendUDPMessage( tmpMsg );
+                  if ( gDevDebug )
+                    Console->Print( "%s Holoexit: Client[%d] Char[%s] moving to zone %d (%s)", Console->ColorText( GREEN, BLACK, "[Debug]" ), nClient->GetID(), nChar->GetName().c_str(), Location, nAppPlace->GetName().c_str() );
+                  if ( gDevDebug )
+                    Console->Print( "%s Location=%d Entity=%d Level=%d", Console->ColorText( CYAN, BLACK, "[Debug]" ), Location, Entity, SewerLevel );
+                }
+                else
+                {
+                  Console->Print( "%s Client[%d] Char[%s] invalid destination %d (appplaces.def)", Console->ColorText( RED, BLACK, "[Warning]" ), nClient->GetID(), nChar->GetName().c_str(), tFurnitureModel->GetFunctionValue() );
+                }
+              }
+              else
+              {
+                Console->Print( "%s Client[%d] Char[%s] invalid holoentry used %d", Console->ColorText( RED, BLACK, "[Warning]" ), nClient->GetID(), nChar->GetName().c_str(), tFurnitureModel->GetFunctionValue() );
+              }
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 18: // "WORLDCHANGEACTOR"
+            case 20: // "DATFILE WORLDCHANGE ACTOR"
+            case 29: //Underground Exit
+            {
+              const PDefAppPlace* nAppPlace;
+              if ( tFurnitureModel->GetFunctionType() == 29 )
+              {
+                nAppPlace = GameDefs->AppPlaces()->GetDef( nChar->GetLocation() ); // special for UG exit
+              }
+              else
+              {
+                nAppPlace = GameDefs->AppPlaces()->GetDef( tFurnitureModel->GetFunctionValue() );
+              }
+              if ( nAppPlace )
+              {
+                uint32_t Location = nAppPlace->GetExitWorldID();
+                uint16_t Entity = nAppPlace->GetExitWorldEntity();
+                uint8_t SewerLevel = 0;
+                //if(((tFurnitureModel->GetFunctionType() == 20) && nAppPlace->GetSewerLevel()) || (tFurnitureModel->GetFunctionType() == 29))
+                if (( tFurnitureModel->GetFunctionType() == 20 ) || ( tFurnitureModel->GetFunctionType() == 29 ) )
+                {
+                  SewerLevel = 1;
+                }
+
+                tmpMsg = MsgBuilder->BuildChangeLocationMsg( nClient, Location, Entity, SewerLevel, mRawItemID ); //mRawItemID
+                nClient->SendUDPMessage( tmpMsg );
+                if ( gDevDebug )
+                {
+                  Console->Print( "%s Dungeon in/out: Client[%d] Char[%s] moving to zone %d, %s", Console->ColorText( GREEN, BLACK, "[Debug]" ), nClient->GetID(), nChar->GetName().c_str(), Location, nAppPlace->GetName().c_str() );
+                  Console->Print( "%s Location=%d Entity=%d Level=%d", Console->ColorText( CYAN, BLACK, "[Debug]" ), Location, Entity, SewerLevel );
+                  Console->Print( "%s Function: %d, Value: %d - Sewer level in appplaces.def for this point: %d", Console->ColorText( CYAN, BLACK, "[Debug]" ), tFurnitureModel->GetFunctionType(), tFurnitureModel->GetFunctionValue(), nAppPlace->GetSewerLevel() );
+                  Console->Print( "%s Worldmodel id: %d", Console->ColorText( CYAN, BLACK, "[Debug]" ), tFurnitureModel->GetID() );
+                }
+              }
+              else
+              {
+                Console->Print( "%s Client[%d] Char[%s] invalid destination %d (appplaces.def)", Console->ColorText( RED, BLACK, "[Warning]" ), nClient->GetID(), nChar->GetName().c_str(), tFurnitureModel->GetFunctionValue() );
+                // send a "refused" msg ?
+              }
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              //nextAnalyser = new PUdpCharJump(mDecodeData);
+              break;
+            }
+
+            case 2: //Terminal
+            case 3: //Outfitter
+            case 16: //HOLOMATCH REFRESH
+            case 17: //HOLOMATCH HEAL & Recreation units
+            case 26: //Outpost Switch
+            {
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 31: //Venture Warp Station
+            {
+              tmpMsg = MsgBuilder->BuildCharUseVentureWarpMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 28: //Fahrzeug Depot Interface
+            {
+              tmpMsg = MsgBuilder->BuildCharUseVhcTerminalMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 11: //Appartement Klingel/�ffner
+            {
+              if ( Appartements->CanFreelyEnter( nChar, nChar->GetLocation() ) )
+              {
+                if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )
+                {
+                  if ( tFurnitureTemplate->GetLinkedObjectID() )
+                  {
+                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );
+                    ClientManager->UDPBroadcast( tmpMsg, nClient );
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+                }
+                else
+                {
+                  if ( WorldActors->GetLinkedObjectID( mRawItemID ) )
+                  {
+                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + WorldActors->GetLinkedObjectID( mRawItemID ), CurrentWorld->GetDoor( WorldActors->GetLinkedObjectID( mRawItemID ) )->IsDoubleDoor() );
+                    ClientManager->UDPBroadcast( tmpMsg, nClient );
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+                }
+              }
+              else
+              {
+                tmpMsg = MsgBuilder->BuildFurnitureActivateMsg( nClient, mRawItemID, 5 ); // Ring
+                ClientManager->UDPBroadcast( tmpMsg, nClient );
+              }
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 12: //Standard Button
+            {
+              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )
+              {
+                if ( tFurnitureTemplate->GetLinkedObjectID() )
+                {
+                  tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );
+                  ClientManager->UDPBroadcast( tmpMsg, nClient );
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+              else
+              {
+                if ( WorldActors->GetLinkedObjectID( mRawItemID ) )
+                {
+                  tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + WorldActors->GetLinkedObjectID( mRawItemID ), CurrentWorld->GetDoor( WorldActors->GetLinkedObjectID( mRawItemID ) )->IsDoubleDoor() );
+                  ClientManager->UDPBroadcast( tmpMsg, nClient );
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 13: //Hack Button
+            {
+              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )
+              {
+                if ( tFurnitureTemplate->GetLinkedObjectID() )
+                {
+                  if ( nClient->GetAccountLevel() >= PAL_GM ) // Allow GameMasters and higher to just bypass HackButtons
+                  {
+                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );
+                    ClientManager->UDPBroadcast( tmpMsg, nClient );
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 106 ); // Damn, locked!
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+              else
+              {
+                uint32_t linkobjID = WorldActors->GetLinkedObjectID( mRawItemID );
+                if ( linkobjID )
+                {
+                  if ( nClient->GetAccountLevel() >= PAL_GM ) // Allow GameMasters and higher to just bypass HackButtons
+                  {
+                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + linkobjID, CurrentWorld->GetDoor( linkobjID )->IsDoubleDoor() );
+                    ClientManager->UDPBroadcast( tmpMsg, nClient );
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 106 ); // Damn, locked!
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            case 23: //EINTRITTSGELD BUTTON
+            {
+              if ( tHandleDynamicActor == false && tFurnitureTemplate != NULL )
+              {
+                if ( tFurnitureTemplate->GetLinkedObjectID() )
+                {
+                  uint32_t OldCash = nChar->GetCash();
+                  uint32_t DoorFee = ( uint32_t )tFurnitureModel->GetFunctionValue();
+                  if ( OldCash >= DoorFee )
+                  {
+                    uint32_t NewCash = nChar->SetCash( OldCash - DoorFee );
+                    PMessage* tmpMsg_cash = MsgBuilder->BuildCharMoneyUpdateMsg( nClient, NewCash );
+                    nClient->SendUDPMessage( tmpMsg_cash );
+                    tmpMsg_cash = NULL;
+                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + tFurnitureTemplate->GetLinkedObjectID(), CurrentWorld->GetDoor( tFurnitureTemplate->GetLinkedObjectID() )->IsDoubleDoor() );
+                    ClientManager->UDPBroadcast( tmpMsg, nClient );
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 12 );  // You dont have enough money!
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+              else
+              {
+                uint32_t linkobjID = WorldActors->GetLinkedObjectID( mRawItemID );
+                if ( linkobjID )
+                {
+                  uint32_t OldCash = nChar->GetCash();
+                  uint32_t DoorFee = ( uint32_t )tFurnitureModel->GetFunctionValue();
+                  if ( OldCash >= DoorFee )
+                  {
+                    uint32_t NewCash = nChar->SetCash( OldCash - DoorFee );
+                    PMessage* tmpMsg_cash = MsgBuilder->BuildCharMoneyUpdateMsg( nClient, NewCash );
+                    nClient->SendUDPMessage( tmpMsg_cash );
+                    tmpMsg_cash = NULL;
+                    tmpMsg = MsgBuilder->BuildDoorOpenMsg( 0x80 + linkobjID, CurrentWorld->GetDoor( linkobjID )->IsDoubleDoor() );
+                    ClientManager->UDPBroadcast( tmpMsg, nClient );
+                  }
+                  else
+                  {
+                    tmpMsg = MsgBuilder->BuildTextIniMsg( nClient, 6, 12 );  // You dont have enough money!
+                    nClient->SendUDPMessage( tmpMsg );
+                  }
+                }
+                else
+                {
+                  tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, mRawItemID );
+                  nClient->SendUDPMessage( tmpMsg );
+                }
+              }
+
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 1: //Itemcontainer
+            {
+              // TODO: Add check if container is already open / Make containers persistent
+              // PContainer* tContainer = World->GetContainer(mRawItemID);
+              PContainer* tContainer = new PContainerAutoCompactOnClose( INV_CABINET_MAXSLOTS );
+              int functionVal = tFurnitureModel->GetFunctionValue();
+              if ( functionVal <= 5 ) // force full random for cabinets for item testing
+                functionVal = -1;
+              tContainer->RandomFill( INV_CABINET_MAXSLOTS, functionVal );
+
+              /*nItem = new PItem(19, 1, 250, 250, 250, 250, 250, 250);
+              if(nItem->GetItemID());
+                tContainer->AddItem(nItem);*/
+              if ( gDevDebug ) Console->Print( "%s Temporary container created", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+              //if(gDevDebug) tContainer->Dump();
+              if ( tContainer->StartUse( nChar->GetID() ) )
+              {
+                nChar->SetContainerInExclusiveUse( tContainer );
+                tmpMsg = MsgBuilder->BuildCharOpenContainerMsg( nClient, mRawItemID, tContainer );
+                //tmpMsg->Dump();
+                nClient->FragmentAndSendUDPMessage( tmpMsg, 0x05 );
+              }
+              else
+              {
+                tmpMsg = MsgBuilder->BuildFurnitureActivateMsg( nClient, mRawItemID, 10 );
+                nClient->SendUDPMessage( tmpMsg );
+                tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, mRawItemID );
+                nClient->SendUDPMessage( tmpMsg );
+              }
+
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 32: // Text message
+            {
+              tmpMsg = MsgBuilder->BuildText100Msg( nClient, ( uint8_t )( 255 & tFurnitureModel->GetFunctionValue() ), mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            // Temp placeholder implementations ============================
+            case 4: //Trader
+            {
+              snprintf( DbgMessage, 128, "That's a trader" );
+              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 5: //Mineral
+            {
+              snprintf( DbgMessage, 128, "That's some minerals" );
+              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 8: //Hackterminal
+            {
+              snprintf( DbgMessage, 128, "That's a hacking terminal" );
+              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 14: //HOLOMATCH ENTRANCE
+            {
+              snprintf( DbgMessage, 128, "That's an holomatch entrance" );
+              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 19: //CLANTERMINAL
+            {
+              snprintf( DbgMessage, 128, "That's a clan terminal" );
+              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 25: //EXPLOSIVE
+            {
+              snprintf( DbgMessage, 128, "That's explosive !" );
+              Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+            case 0: //May be roadsign if touchable
+            {
+              if ( ( tFurnitureModel->GetUseFlags() & ufTouchable ) ) // Touchable ?
+              {
+                snprintf( DbgMessage, 128, "You're at %s", tFurnitureModel->GetName().c_str() );
+                Chat->send( nClient, CHAT_GM, "Information", DbgMessage );
+                tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+                nClient->SendUDPMessage( tmpMsg );
+                mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+                break;
+              }
+              // else we continue to undefined
+            }
+            case 27: //Old goguardian
+              //case 21: //LOCATION FOR 20
+              //case 22: //
+            case 24: //TUTORIALEXIT
+              //case 30: //Static FX (Value=Type. 1=Fire 2=Smoke 3=Steam 4=Sparkle)
+            {
+              tmpMsg = MsgBuilder->BuildCharUseFurnitureMsg( nClient, mRawItemID );
+              nClient->SendUDPMessage( tmpMsg );
+              mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+              break;
+            }
+
+            default:
+              break;
+          }
+        }
+      }
+      else
+      {
+        if ( gDevDebug )
+          Console->Print( "%s Item not known from world template (maybe seen as PASSIVE ?)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+      }
+    }
+
+    mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[ERROR] PUdpUseObject::DoAction : No World defined for client %d (char %d)", nClient->GetID(), nChar->GetID() );
+    mDecodeData->mState = DECODE_ACTION_FAILED | DECODE_ACTION_DONE | DECODE_FINISHED;
+  }
+
+  return true;
+}
+
+/**** PUdpCloseItemContainer ****/
+
+PUdpCloseItemContainer::PUdpCloseItemContainer( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x27";
+}
+
+PUdpMsgAnalyser* PUdpCloseItemContainer::Analyse()
+{
+  mDecodeData->mName << "=Closing item container";
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpCloseItemContainer::DoAction()
+{
+//  PClient* nClient = mDecodeData->mClient;
+//  PChar* nChar = nClient->GetChar();
+
+  PChar* nChar = mDecodeData->mClient->GetChar();
+  PContainer* tContainer = nChar->GetContainerInExclusiveUse();
+  if ( tContainer )
+  {
+    nChar->SetContainerInExclusiveUse( NULL );
+    tContainer->EndUse( nChar->GetID() );
+    if ( ! tContainer->GetOwnerId() )
+    {
+      delete tContainer;
+      if ( gDevDebug ) Console->Print( "%s Temporary container deleted", Console->ColorText( CYAN, BLACK, "[DEBUG]" ) );
+    }
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
index 0b22681..d701157 100644 (file)
@@ -1,25 +1,25 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpUseObject : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mRawItemID;\r
-\r
-    void OldHandler(); // Temp during migration only\r
-\r
-public:\r
-    PUdpUseObject(PMsgDecodeData *nDecodeData);\r
-    //~PUdpUseObject();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpCloseItemContainer : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpCloseItemContainer(PMsgDecodeData *nDecodeData);\r
-    //~PUdpCloseItemContainer();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpUseObject : public PUdpMsgAnalyser {
+private:
+    uint32_t mRawItemID;
+
+    void OldHandler(); // Temp during migration only
+
+public:
+    PUdpUseObject(PMsgDecodeData *nDecodeData);
+    //~PUdpUseObject();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpCloseItemContainer : public PUdpMsgAnalyser {
+public:
+    PUdpCloseItemContainer(PMsgDecodeData *nDecodeData);
+    //~PUdpCloseItemContainer();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index a593eca..efcbec6 100644 (file)
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PUdpVhcMove ****/\r
-\r
-PUdpVhcMove::PUdpVhcMove( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x32";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpVhcMove::Analyse()\r
-{\r
-  mDecodeData->mName << "=Vhc move";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 2 );\r
-\r
-  *nMsg >> mVhcLocalId;\r
-  *nMsg >> mMoveType; // 0 for subway/chair, 3 for vhc, 7 in nc2.2\r
-  *nMsg >> mNewY;\r
-  *nMsg >> mNewZ;\r
-  *nMsg >> mNewX;\r
-  *nMsg >> mNewUD; // neutral :=0x7f, > := upward, < := downward\r
-  *nMsg >> mNewLR;\r
-  *nMsg >> mNewRoll; // neutral := 0x7fff > := bank left, < := bank right\r
-  *nMsg >> mUnk1;\r
-  *nMsg >> mFF;\r
-  *nMsg >> mAction;\r
-//0 = not moving\r
-//&01 = Left\r
-//&02 = Right\r
-//&04 = Forward\r
-//&08 = Back\r
-//&10 = Shoot button\r
-//&20 = Pushing down\r
-//&40 = Pulling up\r
-//\r
-  /*\r
-  --- rolling front+left\r
-  13 b0 00 02 bf\r
-  15\r
-  32\r
-  c9 03 =short VhcId\r
-  07\r
-  c3 66 37 8b 47 6e 80 2a 88 70 27 22\r
-  81\r
-  01 00\r
-  ff = speed% ?\r
-  05 = forward+left ?\r
-  => srv resp\r
-  13 6b 01 bd bf\r
-  18\r
-  03 6a 01 32 c9 03 07 8b 66 37 8b d9 6d 80 e0 8f\r
-  ea 27 22 81 01 00 ff 05\r
-  0c\r
-  03 6b 01 1f 01 00 30 5e 79 36 87 87\r
-  13\r
-  32 c9 03 03 8b 66 38 8b d9 6d 7f 2a 88 92 7f 01 00 00 05\r
-  0b\r
-  20 ed 03 5d 5a c8 8d 9b 7b c2 00\r
-\r
-  --- stopped\r
-  13 88 01 da bf\r
-  13\r
-  32\r
-  c9 03 =short VhcId\r
-  03\r
-  05\r
-  66 36 8b 90 6d 7f 5b 9d 00\r
-  80\r
-  01 00\r
-  00 = speed% ?\r
-  00 = no move\r
-\r
-  */\r
-  if ( gDevDebug )\r
-  {\r
-    Console->Print( YELLOW, BLACK, "[DEBUG] VHC move type %d - objid %d", mMoveType, mVhcLocalId );\r
-    //nMsg->Dump();\r
-    Console->Print( "X=%d Y=%d Z=%d Act=%d", mNewX - 768, mNewY - 768, mNewZ - 768, mAction );\r
-    Console->Print( "LR=%d UD=%d Ro=%d Unk=%d Act=%02x ff=%x", mNewLR, mNewUD, mNewRoll, mUnk1, mAction, mFF );\r
-    Console->Print( "Msg len: %d", nMsg->U8Data( mDecodeData->Sub0x13Start ) );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpVhcMove::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  //PCharCoordinates* nCoords = &(nClient->GetChar()->Coords);\r
-  PWorld* CurrentWorld = Worlds->GetWorld( nClient->GetChar()->GetLocation() );\r
-\r
-  if ( CurrentWorld )\r
-  {\r
-    PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mVhcLocalId );\r
-    if ( tVhc )\r
-    {\r
-      //Todo: calc & mem Speed & Accel vectors\r
-      PVhcCoordinates nPos;\r
-      nPos.SetPosition( mNewY - 768, mNewZ - 768, mNewX - 768, mNewUD, mNewLR, mNewRoll, mAction, mUnk1, mFF );\r
-      tVhc->SetPosition( &nPos );\r
-      PMessage* tmpMsg = MsgBuilder->BuildVhcPosUpdate2Msg( tVhc );\r
-      ClientManager->UDPBroadcast( tmpMsg, mDecodeData->mClient );\r
-\r
-      tmpMsg = MsgBuilder->BuildVhcPosUpdateMsg( tVhc );\r
-      ClientManager->UDPBroadcast( tmpMsg, mDecodeData->mClient );\r
-\r
-      if( CurrentWorld->CheckVhcNeedZoning( &nPos ) )\r
-      {\r
-        uint32_t destWorldId;\r
-        PVhcCoordinates destPos;\r
-\r
-        if (( destWorldId = CurrentWorld->GetVhcZoningDestination( tVhc, &destPos ) ) )\r
-        {\r
-          if ( nClient->GetDebugMode( DBG_LOCATION ) )\r
-          {\r
-            uint8_t pH = 0;\r
-            uint8_t pV = 0;\r
-            Worlds->GetWorldmapFromWorldId( destWorldId, pH, pV );\r
-            char DbgMessage[128];\r
-            snprintf( DbgMessage, 128, "Vhc zoning to zone %c%02d (id %d)", ( 'a' + pV ), pH, destWorldId );\r
-            Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );\r
-          }\r
-\r
-          DoVhcZoning( tVhc, nClient->GetChar()->GetLocation(), destWorldId, &destPos );\r
-        }\r
-      }\r
-    }\r
-    else\r
-      Console->Print( RED, BLACK, "[Error] PUdpVhcMove: Inexistant vhc Id %d", mVhcLocalId );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-// Failures are not managed yet\r
-bool PUdpVhcMove::DoVhcZoning( PSpawnedVehicle* currVhc, uint32_t currWorldId, uint32_t destWorldId, PVhcCoordinates* destPos )\r
-{\r
-  uint32_t seatedCharsId[8];\r
-  uint32_t vhcGlobalId = currVhc->GetVehicleId();\r
-  uint32_t vhcLocalId = currVhc->GetLocalId();\r
-  PVhcCoordinates currCoords = currVhc->GetPosition();\r
-  uint8_t numSeats = currVhc->GetNumSeats();\r
-  uint32_t sittingCharId;\r
-  PClient* sittingClient;\r
-  PClient* sittingClients[8];\r
-  PMessage* tmpMsg;\r
-\r
-  for ( uint8_t i = 0; i < numSeats; ++i )\r
-  {\r
-    // Save seated chars list\r
-    seatedCharsId[i] = sittingCharId = currVhc->GetSeatUser( i );\r
-\r
-    if ( sittingCharId )\r
-    {\r
-      sittingClients[i] = sittingClient = ClientManager->getClientByChar( sittingCharId );\r
-      // Tag each client as zoning to avoid transient side effects\r
-      sittingClient->SetZoning();\r
-      sittingClient->SetVhcZoning();\r
-      // Trigger zoning\r
-      //tmpMsg = MsgBuilder->BuildGenrepZoningMsg( sittingClient, destWorldId, 0 ); // unknown value // 0x62bc or 0x2d4e\r
-      //sittingClient->SendUDPMessage( tmpMsg );\r
-      // We send the unseat msg to the corresponding client only.\r
-      sittingClient->GetChar()->Coords.SetPosition( currCoords.GetY(), currCoords.GetZ(), currCoords.GetX() );\r
-      tmpMsg = MsgBuilder->BuildCharExitSeatMsg( sittingClient );\r
-      sittingClient->FillInUDP_ID( tmpMsg );\r
-      sittingClient->SendUDPMessage( tmpMsg );\r
-    }\r
-    else\r
-      sittingClients[i] = 0;\r
-  }\r
-\r
-  // Unspawn vhc instance from local world\r
-  Vehicles->UnspawnVehicle( vhcGlobalId );\r
-  tmpMsg = MsgBuilder->BuildRemoveWorldObjectMsg( vhcLocalId );\r
-  ClientManager->UDPBroadcast( tmpMsg, currWorldId );\r
-\r
-  // Spawn vhc instance in destWorld\r
-  PSpawnedVehicle* destVhc = Vehicles->SpawnVehicle( vhcGlobalId, destWorldId, destPos );\r
-  if ( destVhc )\r
-  {\r
-    tmpMsg = MsgBuilder->BuildVhcPosUpdateMsg( destVhc );\r
-    ClientManager->UDPBroadcast( tmpMsg, destWorldId );\r
-\r
-    vhcLocalId = destVhc->GetLocalId();\r
-\r
-    // Update chars seat in use and restore vhc used seats\r
-    PChar* sittingChar;\r
-    for ( uint8_t i = 0; i < numSeats; ++i )\r
-    {\r
-      if (( sittingClient = sittingClients[i] ) )\r
-      {\r
-        //if ( gDevDebug )\r
-          Console->Print( "%s PUdpVhcMove::DoVhcZoning : Char %d sitting on vhc %d, seat %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), seatedCharsId[i], vhcLocalId, i );\r
-        sittingChar = sittingClient->GetChar();\r
-        sittingChar->SetSeatInUse( seat_vhc, vhcLocalId, i );\r
-        sittingChar->Coords.SetPosition( destPos->GetY(), destPos->GetZ(), destPos->GetX() );\r
-        destVhc->SetSeatUser( i, seatedCharsId[i] );\r
-      }\r
-    }\r
-  }\r
-  else\r
-  {\r
-    for ( uint8_t i = 0; i < numSeats; ++i )\r
-    {\r
-      if ( sittingClients[i] )\r
-      {\r
-        sittingClients[i]->GetChar()->SetSeatInUse( seat_none );\r
-      }\r
-    }\r
-\r
-    return false;\r
-  }\r
-\r
-  return true;\r
-\r
-}\r
-\r
-/**** PUdpVhcUse ****/\r
-\r
-PUdpVhcUse::PUdpVhcUse( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x0f";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpVhcUse::Analyse()\r
-{\r
-  mDecodeData->mName << "=Try enter vhc";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 12 );\r
-  *nMsg >> mVehicleID; // uint32_t\r
-  *nMsg >> mVehicleSeat;\r
-\r
-  if ( gDevDebug )\r
-    Console->Print( "%s Localid %d trying to enter vhc %d on seat %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetLocalID(), mVehicleID, mVehicleSeat );\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpVhcUse::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  PChar* nChar = nClient->GetChar();\r
-  PMessage* tmpMsg;\r
-\r
-  if ( nChar->GetSeatInUse() == seat_none ) // Refuse if Char is already sitting somewhere\r
-  {\r
-    PWorld* CurrentWorld = Worlds->GetWorld( nChar->GetLocation() );\r
-    if ( CurrentWorld )\r
-    {\r
-      PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mVehicleID );\r
-      if ( tVhc )\r
-      {\r
-        if ( tVhc->SetSeatUser( mVehicleSeat, nChar->GetID() ) ) // Char was able to sit\r
-        {\r
-          nChar->SetSeatInUse( seat_vhc, mVehicleID, mVehicleSeat );\r
-          tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, mVehicleID, mVehicleSeat );\r
-          ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-        }\r
-        else\r
-        {\r
-          tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, mVehicleID ); // Already in use\r
-          nClient->SendUDPMessage( tmpMsg );\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-void PUdpVhcUse::DoFreeSitting( PClient* nClient,  PSpawnedVehicle* nVhc, uint32_t nRawVhcLocalId, uint8_t nSeatId )\r
-{\r
-  PMessage* tmpMsg;\r
-\r
-  if (( nVhc->GetNbFreeSeats() > 1 ) && ( nSeatId > nVhc->GetNumSeats() ) )\r
-  {\r
-    uint8_t freeSeats = nVhc->GetFreeSeatsFlags();\r
-    tmpMsg = MsgBuilder->BuildCharUseVhcMsg( nClient, nRawVhcLocalId, nVhc->GetInformation().GetVehicleType(), freeSeats );\r
-    nClient->SendUDPMessage( tmpMsg ); // Open seat selection window\r
-  }\r
-  else\r
-  {\r
-    if ( nSeatId <= nVhc->GetNumSeats() )\r
-    {\r
-      if ( nVhc->GetSeatUser( nSeatId ) )\r
-      {\r
-        tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, nRawVhcLocalId ); // Already in use\r
-        nClient->SendUDPMessage( tmpMsg );\r
-      }\r
-    }\r
-    else\r
-    {\r
-      nSeatId = nVhc->GetFirstFreeSeat();\r
-\r
-      if ( nSeatId != 255 )\r
-      {\r
-        if ( nVhc->SetSeatUser( nSeatId, nClient->GetChar()->GetID() ) ) // Char was able to sit\r
-        {\r
-          nClient->GetChar()->SetSeatInUse( seat_vhc, nRawVhcLocalId, nSeatId );\r
-          tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, nRawVhcLocalId, nSeatId );\r
-          ClientManager->UDPBroadcast( tmpMsg, nClient );\r
-        }\r
-        else\r
-        {\r
-          tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, nRawVhcLocalId ); // Undefined failure\r
-          nClient->SendUDPMessage( tmpMsg );\r
-        }\r
-      }\r
-      else\r
-      {\r
-        tmpMsg = MsgBuilder->BuildText100Msg( nClient, 5, nRawVhcLocalId ); // "No free seat" msg\r
-        nClient->SendUDPMessage( tmpMsg );\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-/**** PUdpSubwayUpdate ****/\r
-\r
-PUdpSubwayUpdate::PUdpSubwayUpdate( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x00";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpSubwayUpdate::Analyse()\r
-{\r
-  uint8_t Dumb;\r
-\r
-  mDecodeData->mName << "=Subway update";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 2 );\r
-\r
-  *nMsg >> mVehicleID;\r
-  *nMsg >> Dumb;\r
-  *nMsg >> mPosition;\r
-  *nMsg >> mDoorOpened;\r
-\r
-  if ( gDevDebug )\r
-    Console->Print( "%s Subway update 0x%4x : pos 0x%4x, status 0x%2x", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mVehicleID, mPosition, mDoorOpened );\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpSubwayUpdate::DoAction()\r
-{\r
-  /* No real use for that ?\r
-    Subway->UpdateInfo(mVehicleID, mPosition, mDoorOpened);\r
-\r
-    PMessage* tmpMsg = MsgBuilder->BuildSubwaySingleUpdateMsg(mVehicleID, mPosition, mDoorOpened);\r
-    ClientManager->UDPBroadcast(tmpMsg, mDecodeData->mClient);\r
-  */\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
-\r
-/**** PUdpRequestVhcInfo ****/\r
-\r
-PUdpRequestVhcInfo::PUdpRequestVhcInfo( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )\r
-{\r
-  nDecodeData->mName << "/0x27";\r
-}\r
-\r
-PUdpMsgAnalyser* PUdpRequestVhcInfo::Analyse()\r
-{\r
-  mDecodeData->mName << "=Request seatable object info";\r
-\r
-  PMessage* nMsg = mDecodeData->mMessage;\r
-  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 2 );\r
-\r
-  *nMsg >> mVehicleID;\r
-\r
-  if ( gDevDebug )\r
-    Console->Print( "%s Request Seatable Info for 0x%04x :", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mVehicleID );\r
-\r
-  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;\r
-  return this;\r
-}\r
-\r
-bool PUdpRequestVhcInfo::DoAction()\r
-{\r
-  PClient* nClient = mDecodeData->mClient;\r
-  //PCharCoordinates* nCoords = &(nClient->GetChar()->Coords);\r
-  PWorld* CurrentWorld = Worlds->GetWorld( nClient->GetChar()->GetLocation() );\r
-\r
-  if ( CurrentWorld )\r
-  {\r
-    PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mVehicleID );\r
-    if ( tVhc )\r
-    {\r
-      if ( gDevDebug )\r
-        Console->Print("%s Sending Info for vhcId 0x%04x : type %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mVehicleID, tVhc->GetInformation().GetVehicleType() );\r
-      PMessage* tmpMsg = MsgBuilder->BuildVhcInfoMsg( nClient, tVhc );\r
-      nClient->SendUDPMessage( tmpMsg );\r
-    }\r
-    else\r
-      Console->Print( RED, BLACK, "[Error] PUdpRequestVhcInfo: Inexistant vhc Id %d", mVehicleID );\r
-  }\r
-\r
-  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;\r
-  return true;\r
-}\r
+#include "GameServer/Decoder/Includes.hxx"
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PUdpVhcMove ****/
+
+PUdpVhcMove::PUdpVhcMove( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x32";
+}
+
+PUdpMsgAnalyser* PUdpVhcMove::Analyse()
+{
+  mDecodeData->mName << "=Vhc move";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 2 );
+
+  *nMsg >> mVhcLocalId;
+  *nMsg >> mMoveType; // 0 for subway/chair, 3 for vhc, 7 in nc2.2
+  *nMsg >> mNewY;
+  *nMsg >> mNewZ;
+  *nMsg >> mNewX;
+  *nMsg >> mNewUD; // neutral :=0x7f, > := upward, < := downward
+  *nMsg >> mNewLR;
+  *nMsg >> mNewRoll; // neutral := 0x7fff > := bank left, < := bank right
+  *nMsg >> mUnk1;
+  *nMsg >> mFF;
+  *nMsg >> mAction;
+//0 = not moving
+//&01 = Left
+//&02 = Right
+//&04 = Forward
+//&08 = Back
+//&10 = Shoot button
+//&20 = Pushing down
+//&40 = Pulling up
+//
+  /*
+  --- rolling front+left
+  13 b0 00 02 bf
+  15
+  32
+  c9 03 =short VhcId
+  07
+  c3 66 37 8b 47 6e 80 2a 88 70 27 22
+  81
+  01 00
+  ff = speed% ?
+  05 = forward+left ?
+  => srv resp
+  13 6b 01 bd bf
+  18
+  03 6a 01 32 c9 03 07 8b 66 37 8b d9 6d 80 e0 8f
+  ea 27 22 81 01 00 ff 05
+  0c
+  03 6b 01 1f 01 00 30 5e 79 36 87 87
+  13
+  32 c9 03 03 8b 66 38 8b d9 6d 7f 2a 88 92 7f 01 00 00 05
+  0b
+  20 ed 03 5d 5a c8 8d 9b 7b c2 00
+
+  --- stopped
+  13 88 01 da bf
+  13
+  32
+  c9 03 =short VhcId
+  03
+  05
+  66 36 8b 90 6d 7f 5b 9d 00
+  80
+  01 00
+  00 = speed% ?
+  00 = no move
+
+  */
+  if ( gDevDebug )
+  {
+    Console->Print( YELLOW, BLACK, "[DEBUG] VHC move type %d - objid %d", mMoveType, mVhcLocalId );
+    //nMsg->Dump();
+    Console->Print( "X=%d Y=%d Z=%d Act=%d", mNewX - 768, mNewY - 768, mNewZ - 768, mAction );
+    Console->Print( "LR=%d UD=%d Ro=%d Unk=%d Act=%02x ff=%x", mNewLR, mNewUD, mNewRoll, mUnk1, mAction, mFF );
+    Console->Print( "Msg len: %d", nMsg->U8Data( mDecodeData->Sub0x13Start ) );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpVhcMove::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  //PCharCoordinates* nCoords = &(nClient->GetChar()->Coords);
+  PWorld* CurrentWorld = Worlds->GetWorld( nClient->GetChar()->GetLocation() );
+
+  if ( CurrentWorld )
+  {
+    PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mVhcLocalId );
+    if ( tVhc )
+    {
+      //Todo: calc & mem Speed & Accel vectors
+      PVhcCoordinates nPos;
+      nPos.SetPosition( mNewY - 768, mNewZ - 768, mNewX - 768, mNewUD, mNewLR, mNewRoll, mAction, mUnk1, mFF );
+      tVhc->SetPosition( &nPos );
+      PMessage* tmpMsg = MsgBuilder->BuildVhcPosUpdate2Msg( tVhc );
+      ClientManager->UDPBroadcast( tmpMsg, mDecodeData->mClient );
+
+      tmpMsg = MsgBuilder->BuildVhcPosUpdateMsg( tVhc );
+      ClientManager->UDPBroadcast( tmpMsg, mDecodeData->mClient );
+
+      if( CurrentWorld->CheckVhcNeedZoning( &nPos ) )
+      {
+        uint32_t destWorldId;
+        PVhcCoordinates destPos;
+
+        if (( destWorldId = CurrentWorld->GetVhcZoningDestination( tVhc, &destPos ) ) )
+        {
+          if ( nClient->GetDebugMode( DBG_LOCATION ) )
+          {
+            uint8_t pH = 0;
+            uint8_t pV = 0;
+            Worlds->GetWorldmapFromWorldId( destWorldId, pH, pV );
+            char DbgMessage[128];
+            snprintf( DbgMessage, 128, "Vhc zoning to zone %c%02d (id %d)", ( 'a' + pV ), pH, destWorldId );
+            Chat->send( nClient, CHAT_GM, "Debug", DbgMessage );
+          }
+
+          DoVhcZoning( tVhc, nClient->GetChar()->GetLocation(), destWorldId, &destPos );
+        }
+      }
+    }
+    else
+      Console->Print( RED, BLACK, "[Error] PUdpVhcMove: Inexistant vhc Id %d", mVhcLocalId );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+// Failures are not managed yet
+bool PUdpVhcMove::DoVhcZoning( PSpawnedVehicle* currVhc, uint32_t currWorldId, uint32_t destWorldId, PVhcCoordinates* destPos )
+{
+  uint32_t seatedCharsId[8];
+  uint32_t vhcGlobalId = currVhc->GetVehicleId();
+  uint32_t vhcLocalId = currVhc->GetLocalId();
+  PVhcCoordinates currCoords = currVhc->GetPosition();
+  uint8_t numSeats = currVhc->GetNumSeats();
+  uint32_t sittingCharId;
+  PClient* sittingClient;
+  PClient* sittingClients[8];
+  PMessage* tmpMsg;
+
+  for ( uint8_t i = 0; i < numSeats; ++i )
+  {
+    // Save seated chars list
+    seatedCharsId[i] = sittingCharId = currVhc->GetSeatUser( i );
+
+    if ( sittingCharId )
+    {
+      sittingClients[i] = sittingClient = ClientManager->getClientByChar( sittingCharId );
+      // Tag each client as zoning to avoid transient side effects
+      sittingClient->SetZoning();
+      sittingClient->SetVhcZoning();
+      // Trigger zoning
+      //tmpMsg = MsgBuilder->BuildGenrepZoningMsg( sittingClient, destWorldId, 0 ); // unknown value // 0x62bc or 0x2d4e
+      //sittingClient->SendUDPMessage( tmpMsg );
+      // We send the unseat msg to the corresponding client only.
+      sittingClient->GetChar()->Coords.SetPosition( currCoords.GetY(), currCoords.GetZ(), currCoords.GetX() );
+      tmpMsg = MsgBuilder->BuildCharExitSeatMsg( sittingClient );
+      sittingClient->FillInUDP_ID( tmpMsg );
+      sittingClient->SendUDPMessage( tmpMsg );
+    }
+    else
+      sittingClients[i] = 0;
+  }
+
+  // Unspawn vhc instance from local world
+  Vehicles->UnspawnVehicle( vhcGlobalId );
+  tmpMsg = MsgBuilder->BuildRemoveWorldObjectMsg( vhcLocalId );
+  ClientManager->UDPBroadcast( tmpMsg, currWorldId );
+
+  // Spawn vhc instance in destWorld
+  PSpawnedVehicle* destVhc = Vehicles->SpawnVehicle( vhcGlobalId, destWorldId, destPos );
+  if ( destVhc )
+  {
+    tmpMsg = MsgBuilder->BuildVhcPosUpdateMsg( destVhc );
+    ClientManager->UDPBroadcast( tmpMsg, destWorldId );
+
+    vhcLocalId = destVhc->GetLocalId();
+
+    // Update chars seat in use and restore vhc used seats
+    PChar* sittingChar;
+    for ( uint8_t i = 0; i < numSeats; ++i )
+    {
+      if (( sittingClient = sittingClients[i] ) )
+      {
+        //if ( gDevDebug )
+          Console->Print( "%s PUdpVhcMove::DoVhcZoning : Char %d sitting on vhc %d, seat %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), seatedCharsId[i], vhcLocalId, i );
+        sittingChar = sittingClient->GetChar();
+        sittingChar->SetSeatInUse( seat_vhc, vhcLocalId, i );
+        sittingChar->Coords.SetPosition( destPos->GetY(), destPos->GetZ(), destPos->GetX() );
+        destVhc->SetSeatUser( i, seatedCharsId[i] );
+      }
+    }
+  }
+  else
+  {
+    for ( uint8_t i = 0; i < numSeats; ++i )
+    {
+      if ( sittingClients[i] )
+      {
+        sittingClients[i]->GetChar()->SetSeatInUse( seat_none );
+      }
+    }
+
+    return false;
+  }
+
+  return true;
+
+}
+
+/**** PUdpVhcUse ****/
+
+PUdpVhcUse::PUdpVhcUse( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x0f";
+}
+
+PUdpMsgAnalyser* PUdpVhcUse::Analyse()
+{
+  mDecodeData->mName << "=Try enter vhc";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 12 );
+  *nMsg >> mVehicleID; // uint32_t
+  *nMsg >> mVehicleSeat;
+
+  if ( gDevDebug )
+    Console->Print( "%s Localid %d trying to enter vhc %d on seat %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mDecodeData->mClient->GetLocalID(), mVehicleID, mVehicleSeat );
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpVhcUse::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  PChar* nChar = nClient->GetChar();
+  PMessage* tmpMsg;
+
+  if ( nChar->GetSeatInUse() == seat_none ) // Refuse if Char is already sitting somewhere
+  {
+    PWorld* CurrentWorld = Worlds->GetWorld( nChar->GetLocation() );
+    if ( CurrentWorld )
+    {
+      PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mVehicleID );
+      if ( tVhc )
+      {
+        if ( tVhc->SetSeatUser( mVehicleSeat, nChar->GetID() ) ) // Char was able to sit
+        {
+          nChar->SetSeatInUse( seat_vhc, mVehicleID, mVehicleSeat );
+          tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, mVehicleID, mVehicleSeat );
+          ClientManager->UDPBroadcast( tmpMsg, nClient );
+        }
+        else
+        {
+          tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, mVehicleID ); // Already in use
+          nClient->SendUDPMessage( tmpMsg );
+        }
+      }
+    }
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+void PUdpVhcUse::DoFreeSitting( PClient* nClient,  PSpawnedVehicle* nVhc, uint32_t nRawVhcLocalId, uint8_t nSeatId )
+{
+  PMessage* tmpMsg;
+
+  if (( nVhc->GetNbFreeSeats() > 1 ) && ( nSeatId > nVhc->GetNumSeats() ) )
+  {
+    uint8_t freeSeats = nVhc->GetFreeSeatsFlags();
+    tmpMsg = MsgBuilder->BuildCharUseVhcMsg( nClient, nRawVhcLocalId, nVhc->GetInformation().GetVehicleType(), freeSeats );
+    nClient->SendUDPMessage( tmpMsg ); // Open seat selection window
+  }
+  else
+  {
+    if ( nSeatId <= nVhc->GetNumSeats() )
+    {
+      if ( nVhc->GetSeatUser( nSeatId ) )
+      {
+        tmpMsg = MsgBuilder->BuildText100Msg( nClient, 1, nRawVhcLocalId ); // Already in use
+        nClient->SendUDPMessage( tmpMsg );
+      }
+    }
+    else
+    {
+      nSeatId = nVhc->GetFirstFreeSeat();
+
+      if ( nSeatId != 255 )
+      {
+        if ( nVhc->SetSeatUser( nSeatId, nClient->GetChar()->GetID() ) ) // Char was able to sit
+        {
+          nClient->GetChar()->SetSeatInUse( seat_vhc, nRawVhcLocalId, nSeatId );
+          tmpMsg = MsgBuilder->BuildCharUseSeatMsg( nClient, nRawVhcLocalId, nSeatId );
+          ClientManager->UDPBroadcast( tmpMsg, nClient );
+        }
+        else
+        {
+          tmpMsg = MsgBuilder->BuildText100Msg( nClient, 0, nRawVhcLocalId ); // Undefined failure
+          nClient->SendUDPMessage( tmpMsg );
+        }
+      }
+      else
+      {
+        tmpMsg = MsgBuilder->BuildText100Msg( nClient, 5, nRawVhcLocalId ); // "No free seat" msg
+        nClient->SendUDPMessage( tmpMsg );
+      }
+    }
+  }
+}
+
+/**** PUdpSubwayUpdate ****/
+
+PUdpSubwayUpdate::PUdpSubwayUpdate( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x00";
+}
+
+PUdpMsgAnalyser* PUdpSubwayUpdate::Analyse()
+{
+  uint8_t Dumb;
+
+  mDecodeData->mName << "=Subway update";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 2 );
+
+  *nMsg >> mVehicleID;
+  *nMsg >> Dumb;
+  *nMsg >> mPosition;
+  *nMsg >> mDoorOpened;
+
+  if ( gDevDebug )
+    Console->Print( "%s Subway update 0x%4x : pos 0x%4x, status 0x%2x", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mVehicleID, mPosition, mDoorOpened );
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpSubwayUpdate::DoAction()
+{
+  /* No real use for that ?
+    Subway->UpdateInfo(mVehicleID, mPosition, mDoorOpened);
+
+    PMessage* tmpMsg = MsgBuilder->BuildSubwaySingleUpdateMsg(mVehicleID, mPosition, mDoorOpened);
+    ClientManager->UDPBroadcast(tmpMsg, mDecodeData->mClient);
+  */
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
+
+/**** PUdpRequestVhcInfo ****/
+
+PUdpRequestVhcInfo::PUdpRequestVhcInfo( PMsgDecodeData* nDecodeData ) : PUdpMsgAnalyser( nDecodeData )
+{
+  nDecodeData->mName << "/0x27";
+}
+
+PUdpMsgAnalyser* PUdpRequestVhcInfo::Analyse()
+{
+  mDecodeData->mName << "=Request seatable object info";
+
+  PMessage* nMsg = mDecodeData->mMessage;
+  nMsg->SetNextByteOffset( mDecodeData->Sub0x13Start + 2 );
+
+  *nMsg >> mVehicleID;
+
+  if ( gDevDebug )
+    Console->Print( "%s Request Seatable Info for 0x%04x :", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mVehicleID );
+
+  mDecodeData->mState = DECODE_ACTION_READY | DECODE_FINISHED;
+  return this;
+}
+
+bool PUdpRequestVhcInfo::DoAction()
+{
+  PClient* nClient = mDecodeData->mClient;
+  //PCharCoordinates* nCoords = &(nClient->GetChar()->Coords);
+  PWorld* CurrentWorld = Worlds->GetWorld( nClient->GetChar()->GetLocation() );
+
+  if ( CurrentWorld )
+  {
+    PSpawnedVehicle* tVhc = CurrentWorld->GetSpawnedVehicles()->GetVehicle( mVehicleID );
+    if ( tVhc )
+    {
+      if ( gDevDebug )
+        Console->Print("%s Sending Info for vhcId 0x%04x : type %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), mVehicleID, tVhc->GetInformation().GetVehicleType() );
+      PMessage* tmpMsg = MsgBuilder->BuildVhcInfoMsg( nClient, tVhc );
+      nClient->SendUDPMessage( tmpMsg );
+    }
+    else
+      Console->Print( RED, BLACK, "[Error] PUdpRequestVhcInfo: Inexistant vhc Id %d", mVehicleID );
+  }
+
+  mDecodeData->mState = DECODE_ACTION_DONE | DECODE_FINISHED;
+  return true;
+}
index bd93524..fbcf06a 100644 (file)
@@ -1,66 +1,66 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PSpawnedVehicle;\r
-class PVhcCoordinates;\r
-\r
-class PUdpVhcMove : public PUdpMsgAnalyser {\r
-private:\r
-    uint16_t mVhcLocalId;\r
-    uint16_t mNewY;\r
-    uint16_t mNewZ;\r
-    uint16_t mNewX;\r
-    uint16_t mNewLR;\r
-    uint16_t mNewRoll;\r
-    uint16_t mUnk1; // always 0x0001 ?\r
-    uint8_t mMoveType;\r
-    uint8_t mNewUD;\r
-    uint8_t mFF; // always 0xff ?\r
-    uint8_t mAction; // &1 = Left, &2 = Right, &4 = Forward, &8 = Backward\r
-\r
-public:\r
-    PUdpVhcMove(PMsgDecodeData *nDecodeData);\r
-    //~PUdpVhcMove();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-    bool DoVhcZoning(PSpawnedVehicle *currVhc, uint32_t currWorldId, uint32_t destWorldId, PVhcCoordinates *destPos);\r
-};\r
-\r
-class PUdpVhcUse : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mVehicleID;\r
-    uint8_t mVehicleSeat;\r
-\r
-public:\r
-    PUdpVhcUse(PMsgDecodeData *nDecodeData);\r
-    //~PUdpVhcUse();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-    static void DoFreeSitting(PClient *nClient, PSpawnedVehicle *nVhc, uint32_t nRawVhcLocalId, uint8_t nSeatId = 254);\r
-};\r
-\r
-class PUdpSubwayUpdate : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mVehicleID;\r
-    uint16_t mPosition;\r
-    uint8_t mDoorOpened;\r
-\r
-public:\r
-    PUdpSubwayUpdate(PMsgDecodeData *nDecodeData);\r
-    //~PUdpSubwayUpdate();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpRequestVhcInfo : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mVehicleID;\r
-\r
-public:\r
-    PUdpRequestVhcInfo(PMsgDecodeData *nDecodeData);\r
-    //~PUdpRequestVhcInfo();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PSpawnedVehicle;
+class PVhcCoordinates;
+
+class PUdpVhcMove : public PUdpMsgAnalyser {
+private:
+    uint16_t mVhcLocalId;
+    uint16_t mNewY;
+    uint16_t mNewZ;
+    uint16_t mNewX;
+    uint16_t mNewLR;
+    uint16_t mNewRoll;
+    uint16_t mUnk1; // always 0x0001 ?
+    uint8_t mMoveType;
+    uint8_t mNewUD;
+    uint8_t mFF; // always 0xff ?
+    uint8_t mAction; // &1 = Left, &2 = Right, &4 = Forward, &8 = Backward
+
+public:
+    PUdpVhcMove(PMsgDecodeData *nDecodeData);
+    //~PUdpVhcMove();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+    bool DoVhcZoning(PSpawnedVehicle *currVhc, uint32_t currWorldId, uint32_t destWorldId, PVhcCoordinates *destPos);
+};
+
+class PUdpVhcUse : public PUdpMsgAnalyser {
+private:
+    uint32_t mVehicleID;
+    uint8_t mVehicleSeat;
+
+public:
+    PUdpVhcUse(PMsgDecodeData *nDecodeData);
+    //~PUdpVhcUse();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+    static void DoFreeSitting(PClient *nClient, PSpawnedVehicle *nVhc, uint32_t nRawVhcLocalId, uint8_t nSeatId = 254);
+};
+
+class PUdpSubwayUpdate : public PUdpMsgAnalyser {
+private:
+    uint32_t mVehicleID;
+    uint16_t mPosition;
+    uint8_t mDoorOpened;
+
+public:
+    PUdpSubwayUpdate(PMsgDecodeData *nDecodeData);
+    //~PUdpSubwayUpdate();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpRequestVhcInfo : public PUdpMsgAnalyser {
+private:
+    uint32_t mVehicleID;
+
+public:
+    PUdpRequestVhcInfo(PMsgDecodeData *nDecodeData);
+    //~PUdpRequestVhcInfo();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index 9722fb3..f5f814c 100644 (file)
@@ -1,80 +1,80 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Decoder/UdpAnalyser.hxx"\r
-\r
-class PUdpZoning1 : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mNewLocation;\r
-    uint16_t mNewEntity;\r
-    uint8_t mUnknown;\r
-\r
-public:\r
-    PUdpZoning1(PMsgDecodeData *nDecodeData);\r
-    //~PUdpZoning1();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpZoning2 : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpZoning2(PMsgDecodeData *nDecodeData);\r
-    //~PUdpZoning2();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpGenrepZoning : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mNewLocation;\r
-    uint16_t mNewEntity;\r
-\r
-public:\r
-    PUdpGenrepZoning(PMsgDecodeData *nDecodeData);\r
-    //~PUdpGenrepZoning();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-    static bool DoEffectiveZoning(PClient *nClient, uint32_t nNewLocation, uint16_t nNewEntity);\r
-};\r
-\r
-class PUdpAptGRZoning : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpAptGRZoning(PMsgDecodeData *nDecodeData);\r
-    //~PUdpAptGRZoning();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-    static bool DoEffectiveZoning(PClient *nClient);\r
-};\r
-\r
-class PUdpAddGenrepToList : public PUdpMsgAnalyser {\r
-private:\r
-    uint32_t mLocation;\r
-    uint16_t mEntity;\r
-\r
-public:\r
-    PUdpAddGenrepToList(PMsgDecodeData *nDecodeData);\r
-    //~PUdpAddGenrepToList();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-class PUdpAppartmentAccess : public PUdpMsgAnalyser {\r
-private:\r
-    uint16_t mAppartmentPlace;\r
-    char *mPassword;\r
-\r
-public:\r
-    PUdpAppartmentAccess(PMsgDecodeData *nDecodeData);\r
-    //~PUdpAppartmentAccess();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
-\r
-\r
-class PUdpEndOfZoning : public PUdpMsgAnalyser {\r
-public:\r
-    PUdpEndOfZoning(PMsgDecodeData *nDecodeData);\r
-    //~PUdpEndOfZoning();\r
-    PUdpMsgAnalyser *Analyse();\r
-    bool DoAction();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Decoder/UdpAnalyser.hxx"
+
+class PUdpZoning1 : public PUdpMsgAnalyser {
+private:
+    uint32_t mNewLocation;
+    uint16_t mNewEntity;
+    uint8_t mUnknown;
+
+public:
+    PUdpZoning1(PMsgDecodeData *nDecodeData);
+    //~PUdpZoning1();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpZoning2 : public PUdpMsgAnalyser {
+public:
+    PUdpZoning2(PMsgDecodeData *nDecodeData);
+    //~PUdpZoning2();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpGenrepZoning : public PUdpMsgAnalyser {
+private:
+    uint32_t mNewLocation;
+    uint16_t mNewEntity;
+
+public:
+    PUdpGenrepZoning(PMsgDecodeData *nDecodeData);
+    //~PUdpGenrepZoning();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+    static bool DoEffectiveZoning(PClient *nClient, uint32_t nNewLocation, uint16_t nNewEntity);
+};
+
+class PUdpAptGRZoning : public PUdpMsgAnalyser {
+public:
+    PUdpAptGRZoning(PMsgDecodeData *nDecodeData);
+    //~PUdpAptGRZoning();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+    static bool DoEffectiveZoning(PClient *nClient);
+};
+
+class PUdpAddGenrepToList : public PUdpMsgAnalyser {
+private:
+    uint32_t mLocation;
+    uint16_t mEntity;
+
+public:
+    PUdpAddGenrepToList(PMsgDecodeData *nDecodeData);
+    //~PUdpAddGenrepToList();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+class PUdpAppartmentAccess : public PUdpMsgAnalyser {
+private:
+    uint16_t mAppartmentPlace;
+    char *mPassword;
+
+public:
+    PUdpAppartmentAccess(PMsgDecodeData *nDecodeData);
+    //~PUdpAppartmentAccess();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
+
+
+class PUdpEndOfZoning : public PUdpMsgAnalyser {
+public:
+    PUdpEndOfZoning(PMsgDecodeData *nDecodeData);
+    //~PUdpEndOfZoning();
+    PUdpMsgAnalyser *Analyse();
+    bool DoAction();
+};
index fa6078a..581ccd4 100644 (file)
@@ -1,35 +1,35 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefAppPlace::PDefAppPlace()\r
-{\r
-}\r
-\r
-bool PDefAppPlace::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0: // setentry\r
-                    continue;\r
-\r
-            case 1: // index\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2: // name\r
-                mName = *i; break;\r
-\r
-            case 3: // Exit World\r
-                mExitWorldID = atoi(i->c_str()); break;\r
-\r
-            case 4: // Exit World entity\r
-                mExitWorldEntity = atoi(i->c_str()); break;\r
-\r
-            case 5: // Sewer level\r
-                mSewerLevel = atoi(i->c_str()); break;\r
-        }\r
-    }\r
-\r
-    return true;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefAppPlace::PDefAppPlace()
+{
+}
+
+bool PDefAppPlace::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0: // setentry
+                    continue;
+
+            case 1: // index
+                mIndex = atoi(i->c_str()); break;
+
+            case 2: // name
+                mName = *i; break;
+
+            case 3: // Exit World
+                mExitWorldID = atoi(i->c_str()); break;
+
+            case 4: // Exit World entity
+                mExitWorldEntity = atoi(i->c_str()); break;
+
+            case 5: // Sewer level
+                mSewerLevel = atoi(i->c_str()); break;
+        }
+    }
+
+    return true;
+}
index 18d0268..f575958 100644 (file)
@@ -1,25 +1,25 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefAppPlace : public PDef {\r
-private :\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    int32_t mExitWorldID;\r
-    int32_t mExitWorldEntity;\r
-    int32_t mSewerLevel;\r
-\r
-public :\r
-    PDefAppPlace();\r
-    //~PDefAppPlace();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline int32_t GetExitWorldID() const { return mExitWorldID; }\r
-    inline int32_t GetExitWorldEntity() const { return mExitWorldEntity; }\r
-    inline int32_t GetSewerLevel() const { return mSewerLevel; }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefAppPlace : public PDef {
+private :
+    //int32_t mIndex;
+    std::string mName;
+    int32_t mExitWorldID;
+    int32_t mExitWorldEntity;
+    int32_t mSewerLevel;
+
+public :
+    PDefAppPlace();
+    //~PDefAppPlace();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline int32_t GetExitWorldID() const { return mExitWorldID; }
+    inline int32_t GetExitWorldEntity() const { return mExitWorldEntity; }
+    inline int32_t GetSewerLevel() const { return mSewerLevel; }
+};
index 9f37a69..c17da33 100644 (file)
@@ -1,50 +1,50 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefAppartement::PDefAppartement()\r
-{\r
-}\r
-\r
-bool PDefAppartement::LoadFromDef(PTokenList *Tokens)\r
-{\r
-  mFaction = 0;\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0: // setentry\r
-                    continue;\r
-\r
-            case 1: // index\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2: // name\r
-                mName = *i; break;\r
-\r
-            case 3: // world name\r
-                mWorldName = *i; break;\r
-\r
-            case 4: // value\r
-                mValue = atoi(i->c_str()); break;\r
-\r
-            case 5: // number of places\r
-                mPlaceCount = atoi(i->c_str()); break;\r
-\r
-          case 6:\r
-          case 7:\r
-          case 8:\r
-          case 9:\r
-          case 10:\r
-          case 11:\r
-          case 12:\r
-          case 13:\r
-            mPlace[Idx-6] = atoi(i->c_str()); break;\r
-\r
-            case 14: // faction if base appartement\r
-                mFaction = atoi(i->c_str()); break;\r
-        }\r
-    }\r
-//Console->Print("%04d:%s file:%s val:%d places:%d pl1:%d pl2:%d pl8:%d faction:%d",\r
-//      mIndex, mName.c_str(), mWorldName.c_str(), mValue, mPlaceCount, mPlace[0], mPlace[1], mPlace[7], mFaction);\r
-    return true;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefAppartement::PDefAppartement()
+{
+}
+
+bool PDefAppartement::LoadFromDef(PTokenList *Tokens)
+{
+  mFaction = 0;
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0: // setentry
+                    continue;
+
+            case 1: // index
+                mIndex = atoi(i->c_str()); break;
+
+            case 2: // name
+                mName = *i; break;
+
+            case 3: // world name
+                mWorldName = *i; break;
+
+            case 4: // value
+                mValue = atoi(i->c_str()); break;
+
+            case 5: // number of places
+                mPlaceCount = atoi(i->c_str()); break;
+
+          case 6:
+          case 7:
+          case 8:
+          case 9:
+          case 10:
+          case 11:
+          case 12:
+          case 13:
+            mPlace[Idx-6] = atoi(i->c_str()); break;
+
+            case 14: // faction if base appartement
+                mFaction = atoi(i->c_str()); break;
+        }
+    }
+//Console->Print("%04d:%s file:%s val:%d places:%d pl1:%d pl2:%d pl8:%d faction:%d",
+//      mIndex, mName.c_str(), mWorldName.c_str(), mValue, mPlaceCount, mPlace[0], mPlace[1], mPlace[7], mFaction);
+    return true;
+}
index 58dd293..fccd9ee 100644 (file)
@@ -1,37 +1,37 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-#include "GameServer/Definitions/Map.hxx"\r
-\r
-class PDefAppartement : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    std::string mWorldName;\r
-    int32_t mValue;\r
-    int32_t mPlaceCount;\r
-    int32_t mPlace[8];\r
-    int32_t mFaction;\r
-\r
-public:\r
-    PDefAppartement();\r
-    //~PDefAppartement();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline int32_t GetID() const { return mIndex; }\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline const std::string &GetWorldName() const { return mWorldName; }\r
-    inline int32_t GetValue() const { return mValue; }\r
-    inline int32_t GetPlaceCount() const { return mPlaceCount; }\r
-    inline int32_t GetPlace(int32_t nIdx) const { return ( (nIdx < mPlaceCount) ? mPlace[nIdx] : 0 ); }\r
-    inline int32_t GetFaction() const { return mFaction; }\r
-};\r
-\r
-class PDefAppartementsMap : public PDefMap<PDefAppartement> {\r
-public:\r
-    inline std::map<int32_t, PDefAppartement*>::const_iterator ConstIteratorBegin() const { return mDefs.begin(); }\r
-    inline std::map<int32_t, PDefAppartement*>::const_iterator ConstIteratorEnd() const { return mDefs.end(); }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+#include "GameServer/Definitions/Map.hxx"
+
+class PDefAppartement : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName;
+    std::string mWorldName;
+    int32_t mValue;
+    int32_t mPlaceCount;
+    int32_t mPlace[8];
+    int32_t mFaction;
+
+public:
+    PDefAppartement();
+    //~PDefAppartement();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline int32_t GetID() const { return mIndex; }
+    inline const std::string &GetName() const { return mName; }
+    inline const std::string &GetWorldName() const { return mWorldName; }
+    inline int32_t GetValue() const { return mValue; }
+    inline int32_t GetPlaceCount() const { return mPlaceCount; }
+    inline int32_t GetPlace(int32_t nIdx) const { return ( (nIdx < mPlaceCount) ? mPlace[nIdx] : 0 ); }
+    inline int32_t GetFaction() const { return mFaction; }
+};
+
+class PDefAppartementsMap : public PDefMap<PDefAppartement> {
+public:
+    inline std::map<int32_t, PDefAppartement*>::const_iterator ConstIteratorBegin() const { return mDefs.begin(); }
+    inline std::map<int32_t, PDefAppartement*>::const_iterator ConstIteratorEnd() const { return mDefs.end(); }
+};
index 4ee96b9..74aae52 100644 (file)
-#include <cstring>\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-\r
-// charkinds are character templates used for player char creation\r
-\r
-PDefCharKind::PDefCharKind()\r
-{\r
-    mSkillInfo = 0;\r
-    memset(mInventory, 0, sizeof(mInventory));\r
-}\r
-\r
-PDefCharKind::~PDefCharKind()\r
-{\r
-    delete [] mSkillInfo;\r
-    for(PSkillPtsMap::const_iterator i=mSkillPts.begin(); i!=mSkillPts.end(); i++)\r
-        delete i->second;\r
-    for(PSubSkillPtsMap::const_iterator i=mSubSkillPts.begin(); i!=mSubSkillPts.end(); i++)\r
-        delete i->second;\r
-    for(PStartLevelMap::const_iterator i=mStartLevels.begin(); i!=mStartLevels.end(); i++)\r
-        delete i->second;\r
-}\r
-\r
-bool PDefCharKind::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int NumSkills = GameDefs->Skills()->GetNumDefs();\r
-    //int NumSubSkills = GameDefs->SubSkills()->GetNumDefs();\r
-\r
-    int SkillInfoStart = 4;\r
-    int TrainPtsStart = SkillInfoStart+NumSkills*3;\r
-    int LevelsStart = TrainPtsStart + 32*2;\r
-    int MoneyStart = LevelsStart + 16*2;\r
-    int InventoryStart = MoneyStart+1;\r
-\r
-    mSkillInfo = new PSkillInfo[NumSkills];\r
-\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0 :    // setentry\r
-                continue;\r
-\r
-            case 1 :\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2 :\r
-                mName = *i; break;\r
-\r
-            case 3 :\r
-                mType = atoi(i->c_str()); break;\r
-\r
-        }\r
-\r
-        if((Idx >= SkillInfoStart) && (Idx < TrainPtsStart)) // skill info\r
-        {\r
-            int SkillIdx = (Idx-SkillInfoStart)/3;\r
-            int Value = atoi(i->c_str());\r
-\r
-            // start, max, grow per skill\r
-            switch((Idx-SkillInfoStart)%3)\r
-            {\r
-                case 0 : mSkillInfo[SkillIdx].mStart = Value; break;\r
-                case 1 : mSkillInfo[SkillIdx].mMax = Value; break;\r
-                case 2 : mSkillInfo[SkillIdx].mGrow = Value; break;\r
-            }\r
-        } else\r
-        // 32 skill/subskill train pts\r
-        if((Idx >= TrainPtsStart) && (Idx < LevelsStart))\r
-        {\r
-            static int SkillIndex = 0;\r
-            int Index = Idx-TrainPtsStart;\r
-            if((Index&1)==0)\r
-            {\r
-                SkillIndex = atoi(i->c_str());\r
-            } else\r
-            {\r
-                if(SkillIndex >= 1000)  // skill\r
-                {\r
-                    const PDefSkill *Skill = GameDefs->Skills()->GetDef(SkillIndex-1000);\r
-                    if(Skill)\r
-                    {\r
-                        int Index = Skill->GetIndex()-1;\r
-                        PSkillPtsInfo *CurrentSkillPts = new PSkillPtsInfo();\r
-                        CurrentSkillPts->mSkill = Index;\r
-                        CurrentSkillPts->mPoints = atoi(i->c_str());\r
-                        mSkillPts.insert(std::make_pair(Index, CurrentSkillPts));\r
-                    } else\r
-                    {\r
-                        if(SkillIndex-1000 != 0)\r
-                            Console->Print("Charkind def: invalid skill index %i", SkillIndex-1000);\r
-                    }\r
-                } else  // subskill\r
-                {\r
-                    const PDefSubSkill *SubSkill = GameDefs->SubSkills()->GetDef(SkillIndex);\r
-                    if(SubSkill)\r
-                    {\r
-                        int Index = SubSkill->GetIndex()-1;\r
-                        PSubSkillPtsInfo *CurrentSubSkillPts = new PSubSkillPtsInfo();\r
-                        CurrentSubSkillPts->mSubSkill = Index;\r
-                        CurrentSubSkillPts->mPoints = atoi(i->c_str());\r
-                        mSubSkillPts.insert(std::make_pair(Index, CurrentSubSkillPts));\r
-                    } else\r
-                    {\r
-                        if(SkillIndex != 0)\r
-                            Console->Print("Charkind def: invalid subskill index %i", SkillIndex);\r
-                    }\r
-                }\r
-            }\r
-        } else\r
-        // 16 subskill start levels\r
-        if((Idx >= LevelsStart) && (Idx < MoneyStart))\r
-        {\r
-            static int LevelIndex = 0;\r
-            int Index = Idx-NumSkills*3+4+(32*2);\r
-            if((Index&1)==0)\r
-            {\r
-                LevelIndex = atoi(i->c_str());\r
-            } else\r
-            {\r
-                if(LevelIndex > 0)\r
-                {\r
-                    const PDefSubSkill *SubSkill = GameDefs->SubSkills()->GetDef(LevelIndex);\r
-                    if(SubSkill)\r
-                    {\r
-                        PStartLevelInfo *Level = new PStartLevelInfo();\r
-                        Level->mSubSkill = SubSkill->GetIndex();\r
-                        Level->mLevel = atoi(i->c_str());\r
-                        mStartLevels.insert(std::make_pair(Level->mSubSkill, Level));\r
-                    } else\r
-                    {\r
-                        Console->Print("Charkind def: invalid subskill index %i", LevelIndex);\r
-                    }\r
-                }\r
-            }\r
-        } else\r
-        // money\r
-        if((Idx >= MoneyStart) && (Idx < InventoryStart))\r
-        {\r
-            mMoney = atoi(i->c_str());\r
-        } else\r
-        // inventory\r
-        if((Idx >= InventoryStart) && (Idx < InventoryStart+8))\r
-        {\r
-            mInventory[Idx-InventoryStart] = atoi(i->c_str());\r
-        }\r
-    }\r
-    \r
-    return true;\r
-}\r
-\r
+#include <cstring>
+#include "GameServer/Definitions/Includes.hxx"
+#include "GameServer/Includes.hxx"
+
+// charkinds are character templates used for player char creation
+
+PDefCharKind::PDefCharKind()
+{
+    mSkillInfo = 0;
+    memset(mInventory, 0, sizeof(mInventory));
+}
+
+PDefCharKind::~PDefCharKind()
+{
+    delete [] mSkillInfo;
+    for(PSkillPtsMap::const_iterator i=mSkillPts.begin(); i!=mSkillPts.end(); i++)
+        delete i->second;
+    for(PSubSkillPtsMap::const_iterator i=mSubSkillPts.begin(); i!=mSubSkillPts.end(); i++)
+        delete i->second;
+    for(PStartLevelMap::const_iterator i=mStartLevels.begin(); i!=mStartLevels.end(); i++)
+        delete i->second;
+}
+
+bool PDefCharKind::LoadFromDef(PTokenList *Tokens)
+{
+    int NumSkills = GameDefs->Skills()->GetNumDefs();
+    //int NumSubSkills = GameDefs->SubSkills()->GetNumDefs();
+
+    int SkillInfoStart = 4;
+    int TrainPtsStart = SkillInfoStart+NumSkills*3;
+    int LevelsStart = TrainPtsStart + 32*2;
+    int MoneyStart = LevelsStart + 16*2;
+    int InventoryStart = MoneyStart+1;
+
+    mSkillInfo = new PSkillInfo[NumSkills];
+
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0 :    // setentry
+                continue;
+
+            case 1 :
+                mIndex = atoi(i->c_str()); break;
+
+            case 2 :
+                mName = *i; break;
+
+            case 3 :
+                mType = atoi(i->c_str()); break;
+
+        }
+
+        if((Idx >= SkillInfoStart) && (Idx < TrainPtsStart)) // skill info
+        {
+            int SkillIdx = (Idx-SkillInfoStart)/3;
+            int Value = atoi(i->c_str());
+
+            // start, max, grow per skill
+            switch((Idx-SkillInfoStart)%3)
+            {
+                case 0 : mSkillInfo[SkillIdx].mStart = Value; break;
+                case 1 : mSkillInfo[SkillIdx].mMax = Value; break;
+                case 2 : mSkillInfo[SkillIdx].mGrow = Value; break;
+            }
+        } else
+        // 32 skill/subskill train pts
+        if((Idx >= TrainPtsStart) && (Idx < LevelsStart))
+        {
+            static int SkillIndex = 0;
+            int Index = Idx-TrainPtsStart;
+            if((Index&1)==0)
+            {
+                SkillIndex = atoi(i->c_str());
+            } else
+            {
+                if(SkillIndex >= 1000)  // skill
+                {
+                    const PDefSkill *Skill = GameDefs->Skills()->GetDef(SkillIndex-1000);
+                    if(Skill)
+                    {
+                        int Index = Skill->GetIndex()-1;
+                        PSkillPtsInfo *CurrentSkillPts = new PSkillPtsInfo();
+                        CurrentSkillPts->mSkill = Index;
+                        CurrentSkillPts->mPoints = atoi(i->c_str());
+                        mSkillPts.insert(std::make_pair(Index, CurrentSkillPts));
+                    } else
+                    {
+                        if(SkillIndex-1000 != 0)
+                            Console->Print("Charkind def: invalid skill index %i", SkillIndex-1000);
+                    }
+                } else  // subskill
+                {
+                    const PDefSubSkill *SubSkill = GameDefs->SubSkills()->GetDef(SkillIndex);
+                    if(SubSkill)
+                    {
+                        int Index = SubSkill->GetIndex()-1;
+                        PSubSkillPtsInfo *CurrentSubSkillPts = new PSubSkillPtsInfo();
+                        CurrentSubSkillPts->mSubSkill = Index;
+                        CurrentSubSkillPts->mPoints = atoi(i->c_str());
+                        mSubSkillPts.insert(std::make_pair(Index, CurrentSubSkillPts));
+                    } else
+                    {
+                        if(SkillIndex != 0)
+                            Console->Print("Charkind def: invalid subskill index %i", SkillIndex);
+                    }
+                }
+            }
+        } else
+        // 16 subskill start levels
+        if((Idx >= LevelsStart) && (Idx < MoneyStart))
+        {
+            static int LevelIndex = 0;
+            int Index = Idx-NumSkills*3+4+(32*2);
+            if((Index&1)==0)
+            {
+                LevelIndex = atoi(i->c_str());
+            } else
+            {
+                if(LevelIndex > 0)
+                {
+                    const PDefSubSkill *SubSkill = GameDefs->SubSkills()->GetDef(LevelIndex);
+                    if(SubSkill)
+                    {
+                        PStartLevelInfo *Level = new PStartLevelInfo();
+                        Level->mSubSkill = SubSkill->GetIndex();
+                        Level->mLevel = atoi(i->c_str());
+                        mStartLevels.insert(std::make_pair(Level->mSubSkill, Level));
+                    } else
+                    {
+                        Console->Print("Charkind def: invalid subskill index %i", LevelIndex);
+                    }
+                }
+            }
+        } else
+        // money
+        if((Idx >= MoneyStart) && (Idx < InventoryStart))
+        {
+            mMoney = atoi(i->c_str());
+        } else
+        // inventory
+        if((Idx >= InventoryStart) && (Idx < InventoryStart+8))
+        {
+            mInventory[Idx-InventoryStart] = atoi(i->c_str());
+        }
+    }
+    
+    return true;
+}
+
index 4f86772..ecfe19d 100644 (file)
@@ -1,82 +1,82 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-struct PSkillInfo {\r
-    int32_t mStart;\r
-    int32_t mMax;\r
-    int32_t mGrow;\r
-\r
-    inline PSkillInfo()\r
-    {\r
-        mStart = mMax = mGrow = 0;\r
-    }\r
-};\r
-\r
-struct PSkillPtsInfo {\r
-    int32_t mSkill;\r
-    int32_t mPoints;\r
-\r
-    inline PSkillPtsInfo()\r
-    {\r
-        mSkill = mPoints = 0;\r
-    }\r
-};\r
-\r
-struct PSubSkillPtsInfo {\r
-    int32_t mSubSkill;\r
-    int32_t mPoints;\r
-\r
-    inline PSubSkillPtsInfo()\r
-    {\r
-        mSubSkill = mPoints = 0;\r
-    }\r
-};\r
-\r
-struct PStartLevelInfo {\r
-    int32_t mSubSkill;\r
-    int32_t mLevel;\r
-\r
-    inline PStartLevelInfo()\r
-    {\r
-        mSubSkill = mLevel = 0;\r
-    }\r
-\r
-};\r
-\r
-class PDefCharKind : public PDef {\r
-private:\r
-    typedef std::map<int32_t, PSkillPtsInfo*> PSkillPtsMap;\r
-    typedef std::map<int32_t, PSubSkillPtsInfo*> PSubSkillPtsMap;\r
-    typedef std::map<int32_t, PStartLevelInfo*> PStartLevelMap;\r
-\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    int32_t mType;\r
-\r
-    // TODO: shouldnt this be a map?\r
-    PSkillInfo *mSkillInfo;\r
-\r
-    PSkillPtsMap mSkillPts;\r
-    PSubSkillPtsMap mSubSkillPts;\r
-    PStartLevelMap mStartLevels;\r
-    int32_t mMoney;\r
-    uint32_t mInventory[8];\r
-\r
-public:\r
-    PDefCharKind();\r
-    ~PDefCharKind();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline int32_t GetType() const { return mType; }\r
-    inline const PSkillInfo &GetSkillInfo(int32_t Skill) const { return mSkillInfo[Skill-1]; }\r
-\r
-    inline int32_t GetStartMoney() const { return mMoney; }\r
-    inline uint32_t GetStartInventory(uint8_t Index) const { return ((Index < 7) ?  mInventory[Index] : 0); }\r
-    // TODO: mission get() functions\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+struct PSkillInfo {
+    int32_t mStart;
+    int32_t mMax;
+    int32_t mGrow;
+
+    inline PSkillInfo()
+    {
+        mStart = mMax = mGrow = 0;
+    }
+};
+
+struct PSkillPtsInfo {
+    int32_t mSkill;
+    int32_t mPoints;
+
+    inline PSkillPtsInfo()
+    {
+        mSkill = mPoints = 0;
+    }
+};
+
+struct PSubSkillPtsInfo {
+    int32_t mSubSkill;
+    int32_t mPoints;
+
+    inline PSubSkillPtsInfo()
+    {
+        mSubSkill = mPoints = 0;
+    }
+};
+
+struct PStartLevelInfo {
+    int32_t mSubSkill;
+    int32_t mLevel;
+
+    inline PStartLevelInfo()
+    {
+        mSubSkill = mLevel = 0;
+    }
+
+};
+
+class PDefCharKind : public PDef {
+private:
+    typedef std::map<int32_t, PSkillPtsInfo*> PSkillPtsMap;
+    typedef std::map<int32_t, PSubSkillPtsInfo*> PSubSkillPtsMap;
+    typedef std::map<int32_t, PStartLevelInfo*> PStartLevelMap;
+
+    //int32_t mIndex;
+    std::string mName;
+    int32_t mType;
+
+    // TODO: shouldnt this be a map?
+    PSkillInfo *mSkillInfo;
+
+    PSkillPtsMap mSkillPts;
+    PSubSkillPtsMap mSubSkillPts;
+    PStartLevelMap mStartLevels;
+    int32_t mMoney;
+    uint32_t mInventory[8];
+
+public:
+    PDefCharKind();
+    ~PDefCharKind();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline int32_t GetType() const { return mType; }
+    inline const PSkillInfo &GetSkillInfo(int32_t Skill) const { return mSkillInfo[Skill-1]; }
+
+    inline int32_t GetStartMoney() const { return mMoney; }
+    inline uint32_t GetStartInventory(uint8_t Index) const { return ((Index < 7) ?  mInventory[Index] : 0); }
+    // TODO: mission get() functions
+};
index 95b2ddf..3e27efc 100644 (file)
@@ -1,55 +1,55 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-// characters.def contains all ingame characters (player types, npc's, monsters)\r
-\r
-PDefCharacter::PDefCharacter()\r
-{\r
-    mIndex = -1;\r
-    mName = "unknown";\r
-    mModel = -1;\r
-}\r
-\r
-bool PDefCharacter::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0 :    // setentry\r
-                continue;\r
-\r
-            case 1 :\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2 :\r
-                mName = *i; break;\r
-\r
-            case 3 :\r
-                mModel = atoi(i->c_str()); break;\r
-\r
-            case 4 : // 0\r
-                continue;\r
-\r
-            case 5 :\r
-                mHead = atoi(i->c_str()); break;\r
-\r
-            case 6 :\r
-                mTorso = atoi(i->c_str()); break;\r
-\r
-            case 7 :\r
-                mLegs = atoi(i->c_str()); break;\r
-\r
-            case 8 :\r
-                mColor = atoi(i->c_str()); break;\r
-\r
-            case 9 :\r
-                mBrightness = atoi(i->c_str()); break;\r
-        }\r
-\r
-        if(Idx==9)\r
-            return true;\r
-    }\r
-\r
-    return false;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+// characters.def contains all ingame characters (player types, npc's, monsters)
+
+PDefCharacter::PDefCharacter()
+{
+    mIndex = -1;
+    mName = "unknown";
+    mModel = -1;
+}
+
+bool PDefCharacter::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0 :    // setentry
+                continue;
+
+            case 1 :
+                mIndex = atoi(i->c_str()); break;
+
+            case 2 :
+                mName = *i; break;
+
+            case 3 :
+                mModel = atoi(i->c_str()); break;
+
+            case 4 : // 0
+                continue;
+
+            case 5 :
+                mHead = atoi(i->c_str()); break;
+
+            case 6 :
+                mTorso = atoi(i->c_str()); break;
+
+            case 7 :
+                mLegs = atoi(i->c_str()); break;
+
+            case 8 :
+                mColor = atoi(i->c_str()); break;
+
+            case 9 :
+                mBrightness = atoi(i->c_str()); break;
+        }
+
+        if(Idx==9)
+            return true;
+    }
+
+    return false;
+}
index 3abc2c0..f65e971 100644 (file)
@@ -1,31 +1,31 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefCharacter : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    int32_t mModel;\r
-    int32_t mHead;\r
-    int32_t mTorso;\r
-    int32_t mLegs;\r
-    int32_t mColor;\r
-    int32_t mBrightness;\r
-\r
-public:\r
-    PDefCharacter();\r
-    //~PDefCharacter();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline int32_t GetModel() const { return mModel; }\r
-    inline int32_t GetHead() const { return mHead; }\r
-    inline int32_t GetTorso() const { return mTorso; }\r
-    inline int32_t GetLegs() const { return mLegs; }\r
-    inline int32_t GetColor() const { return mColor; }\r
-    inline int32_t GetBrightness() const { return mBrightness; }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefCharacter : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName;
+    int32_t mModel;
+    int32_t mHead;
+    int32_t mTorso;
+    int32_t mLegs;
+    int32_t mColor;
+    int32_t mBrightness;
+
+public:
+    PDefCharacter();
+    //~PDefCharacter();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline int32_t GetModel() const { return mModel; }
+    inline int32_t GetHead() const { return mHead; }
+    inline int32_t GetTorso() const { return mTorso; }
+    inline int32_t GetLegs() const { return mLegs; }
+    inline int32_t GetColor() const { return mColor; }
+    inline int32_t GetBrightness() const { return mBrightness; }
+};
index 2e5ab9a..c4a8822 100644 (file)
@@ -1,56 +1,56 @@
-#include <cstring>\r
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefFaction::PDefFaction()\r
-{\r
-    memset(mRelations, 0, sizeof(mRelations)); // ... array members supposed to by auto-initialized by C++\r
-}\r
-\r
-bool PDefFaction::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        // setfracc 19  "Monster"   -1024   0   0   -1024   -1024   -1024   -1\r
-        switch(Idx)\r
-        {\r
-            case 0 : // setfrac\r
-                continue;\r
-\r
-            case 1 :\r
-                mIndex = atol(i->c_str()); break;\r
-\r
-            case 2 :\r
-                mName = *i;\r
-                CleanUpString(&mName);\r
-                break;\r
-\r
-            case 3 :\r
-                mStartValue = atol(i->c_str()); break;\r
-\r
-            case 4:\r
-                mAffected = atol(i->c_str())!=0; break;\r
-\r
-            case 5:\r
-                mSL = atol(i->c_str()); break;\r
-\r
-            default :\r
-            {\r
-                if(Idx-6 < NUMFACTIONS)\r
-                    mRelations[Idx-6] = atol(i->c_str()); break;\r
-            }\r
-        }\r
-    }\r
-\r
-    return true;\r
-}\r
-\r
-int PDefFaction::GetRelation(int Faction) const\r
-{\r
-    // faction 0 has no relations\r
-    if(Faction <= 0 || Faction > NUMFACTIONS)\r
-        return 0;\r
-\r
-    return mRelations[Faction-1];\r
-}\r
-\r
+#include <cstring>
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefFaction::PDefFaction()
+{
+    memset(mRelations, 0, sizeof(mRelations)); // ... array members supposed to by auto-initialized by C++
+}
+
+bool PDefFaction::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        // setfracc 19  "Monster"   -1024   0   0   -1024   -1024   -1024   -1
+        switch(Idx)
+        {
+            case 0 : // setfrac
+                continue;
+
+            case 1 :
+                mIndex = atol(i->c_str()); break;
+
+            case 2 :
+                mName = *i;
+                CleanUpString(&mName);
+                break;
+
+            case 3 :
+                mStartValue = atol(i->c_str()); break;
+
+            case 4:
+                mAffected = atol(i->c_str())!=0; break;
+
+            case 5:
+                mSL = atol(i->c_str()); break;
+
+            default :
+            {
+                if(Idx-6 < NUMFACTIONS)
+                    mRelations[Idx-6] = atol(i->c_str()); break;
+            }
+        }
+    }
+
+    return true;
+}
+
+int PDefFaction::GetRelation(int Faction) const
+{
+    // faction 0 has no relations
+    if(Faction <= 0 || Faction > NUMFACTIONS)
+        return 0;
+
+    return mRelations[Faction-1];
+}
+
index 22f35a4..c3190dd 100644 (file)
@@ -1,28 +1,28 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-static const int32_t NUMFACTIONS = 20;  // for faction relations only\r
-\r
-class PDefFaction : public PDef {\r
-private :\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    int32_t mStartValue;\r
-    bool mAffected;\r
-    int32_t mSL;\r
-    int32_t mRelations[NUMFACTIONS];\r
-public :\r
-    PDefFaction();\r
-    //~PDefFaction();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline int32_t GetStartValue() const { return mStartValue; }\r
-    inline bool GetAffected() const { return mAffected; }\r
-    inline int32_t GetSL() const { return mSL; };\r
-    int32_t GetRelation(int32_t Faction) const;\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+static const int32_t NUMFACTIONS = 20;  // for faction relations only
+
+class PDefFaction : public PDef {
+private :
+    //int32_t mIndex;
+    std::string mName;
+    int32_t mStartValue;
+    bool mAffected;
+    int32_t mSL;
+    int32_t mRelations[NUMFACTIONS];
+public :
+    PDefFaction();
+    //~PDefFaction();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline int32_t GetStartValue() const { return mStartValue; }
+    inline bool GetAffected() const { return mAffected; }
+    inline int32_t GetSL() const { return mSL; };
+    int32_t GetRelation(int32_t Faction) const;
+};
index b056c3b..4c68725 100644 (file)
@@ -1,65 +1,65 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-/*\r
- --------------------------------------------------------------------\r
- WARNING:\r
- When adding new .def support, don't forget to add required stuff in PGameDefs::Init()\r
-   (compiler won't complain if you don't add that)\r
- --------------------------------------------------------------------\r
-\r
- NOTA: as PGameDefs uses the PDefParser class, which uses the PFileSystem and PFile classes,\r
-   files are searched in the same way as the NC client does:\r
-     - first try to load the file in unpacked form from the given directory,\r
-     - else tries to load the file in packed form from the given directory,\r
-         appending pak_ to its name,\r
-     - else tries to load the packed file from the .pak archive which name is\r
-         derived from the last part of the path.\r
-*/\r
-\r
-PGameDefs::PGameDefs() {}\r
-PGameDefs::~PGameDefs() {}\r
-\r
-bool PGameDefs::Init()\r
-{\r
-  Console->Print( "Initializing game defs..." );\r
-  bool Res = true;\r
-\r
-  Res |= mActionModsDefs.Load ("Action mods", "defs/actionmod.def");\r
-  Res |= mAmmosDefs.Load ("Ammos", "defs/ammo.def");\r
-  Res |= mAppartementsDefs.Load ("Apartments", "defs/appartements.def");\r
-  Res |= mAppPlacesDefs.Load ("App Places", "defs/appplaces.def");\r
-  Res |= mBlueprintPiecesDefs.Load ("Blueprint pieces", "defs/blueprintpieces.def");\r
-  Res |= mCharsDefs.Load ("Chars", "defs/characters.def");\r
-  Res |= mCharActionsDefs.Load ("Char actions", "defs/charaction.def");\r
-  Res |= mDamagesDefs.Load ("Damage", "defs/damage.def");\r
-  Res |= mDrugsDefs.Load ("Drugs", "defs/drugs.def");\r
-  Res |= mFactionsDefs.Load ("Factions", "defs/fractions.def");\r
-  //Res |= mHacksDefs.Load ("Hack", "defs/hack.def");\r
-  Res |= mImplantsDefs.Load ("Implants", "defs/implants.def");\r
-  Res |= mItemContainersDefs.Load ("Item containers", "defs/itemcontainer.def");\r
-  Res |= mItemModsDefs.Load ("Item mods", "defs/itemmod.def");\r
-  Res |= mItemRestrictionsDefs.Load ("Item restrictions", "defs/itemres.def");\r
-  Res |= mItemsDefs.Load ("Items", "defs/items.def");\r
-  Res |= mMissionsDefs.Load ("Missions", "defs/missionbase.def");\r
-  Res |= mNpcArmorsDefs.Load ("NPC Armors", "defs/npcarmor.def");\r
-  Res |= mNpcGroupSpawnsDefs.Load ("NPC group spawns", "defs/npcgroupspawn.def");\r
-  Res |= mNpcsDefs.Load ("NPC", "defs/npc.def");\r
-  Res |= mOutpostsDefs.Load ("Outposts", "defs/outposts.def");\r
-  Res |= mRecyclesDefs.Load ("Recycles", "defs/recycles.def");\r
-  Res |= mRespawnsDefs.Load ("Respawns", "defs/respawn.def");\r
-  Res |= mShotsDefs.Load ("Shots", "defs/shots.def");\r
-  Res |= mSubSkillsDefs.Load ("Subskills", "defs/subskill.def"); // Loading before skills is required\r
-  Res |= mSkillsDefs.Load ("Skills", "defs/skills.def");\r
-  Res |= mCharKindsDefs.Load ("Char kinds", "defs/charkinds.def"); // Loading after skills is required\r
-  Res |= mTradersDefs.Load ("Traders", "defs/trader.def");\r
-  Res |= mVhcsDefs.Load ("Vehicles", "defs/vehicles.def");\r
-  Res |= mVhcSeatsDefs.Load ("Vehicle seats", "defs/vehiclesits.def");\r
-  Res |= mWeaponsDefs.Load ("Weapons", "defs/weapons.def");\r
-  Res |= mWeathersDefs.Load ("Weathers", "defs/weather.def");\r
-  Res |= mWorldsDefs.Load ("Worldinfo", "defs/worldinfo.def");\r
-  Res |= mWorldFilesDefs.Load ("World files", "worlds/worlds.ini");\r
-  Res |= mWorldModelsDefs.Load ("World models", "defs/worldmodel.def");\r
-  Res |= mScriptDefs.Load ("Script defs", "defs/scripts.def");\r
-\r
-  return ( Res );\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+/*
+ --------------------------------------------------------------------
+ WARNING:
+ When adding new .def support, don't forget to add required stuff in PGameDefs::Init()
+   (compiler won't complain if you don't add that)
+ --------------------------------------------------------------------
+
+ NOTA: as PGameDefs uses the PDefParser class, which uses the PFileSystem and PFile classes,
+   files are searched in the same way as the NC client does:
+     - first try to load the file in unpacked form from the given directory,
+     - else tries to load the file in packed form from the given directory,
+         appending pak_ to its name,
+     - else tries to load the packed file from the .pak archive which name is
+         derived from the last part of the path.
+*/
+
+PGameDefs::PGameDefs() {}
+PGameDefs::~PGameDefs() {}
+
+bool PGameDefs::Init()
+{
+  Console->Print( "Initializing game defs..." );
+  bool Res = true;
+
+  Res |= mActionModsDefs.Load ("Action mods", "defs/actionmod.def");
+  Res |= mAmmosDefs.Load ("Ammos", "defs/ammo.def");
+  Res |= mAppartementsDefs.Load ("Apartments", "defs/appartements.def");
+  Res |= mAppPlacesDefs.Load ("App Places", "defs/appplaces.def");
+  Res |= mBlueprintPiecesDefs.Load ("Blueprint pieces", "defs/blueprintpieces.def");
+  Res |= mCharsDefs.Load ("Chars", "defs/characters.def");
+  Res |= mCharActionsDefs.Load ("Char actions", "defs/charaction.def");
+  Res |= mDamagesDefs.Load ("Damage", "defs/damage.def");
+  Res |= mDrugsDefs.Load ("Drugs", "defs/drugs.def");
+  Res |= mFactionsDefs.Load ("Factions", "defs/fractions.def");
+  //Res |= mHacksDefs.Load ("Hack", "defs/hack.def");
+  Res |= mImplantsDefs.Load ("Implants", "defs/implants.def");
+  Res |= mItemContainersDefs.Load ("Item containers", "defs/itemcontainer.def");
+  Res |= mItemModsDefs.Load ("Item mods", "defs/itemmod.def");
+  Res |= mItemRestrictionsDefs.Load ("Item restrictions", "defs/itemres.def");
+  Res |= mItemsDefs.Load ("Items", "defs/items.def");
+  Res |= mMissionsDefs.Load ("Missions", "defs/missionbase.def");
+  Res |= mNpcArmorsDefs.Load ("NPC Armors", "defs/npcarmor.def");
+  Res |= mNpcGroupSpawnsDefs.Load ("NPC group spawns", "defs/npcgroupspawn.def");
+  Res |= mNpcsDefs.Load ("NPC", "defs/npc.def");
+  Res |= mOutpostsDefs.Load ("Outposts", "defs/outposts.def");
+  Res |= mRecyclesDefs.Load ("Recycles", "defs/recycles.def");
+  Res |= mRespawnsDefs.Load ("Respawns", "defs/respawn.def");
+  Res |= mShotsDefs.Load ("Shots", "defs/shots.def");
+  Res |= mSubSkillsDefs.Load ("Subskills", "defs/subskill.def"); // Loading before skills is required
+  Res |= mSkillsDefs.Load ("Skills", "defs/skills.def");
+  Res |= mCharKindsDefs.Load ("Char kinds", "defs/charkinds.def"); // Loading after skills is required
+  Res |= mTradersDefs.Load ("Traders", "defs/trader.def");
+  Res |= mVhcsDefs.Load ("Vehicles", "defs/vehicles.def");
+  Res |= mVhcSeatsDefs.Load ("Vehicle seats", "defs/vehiclesits.def");
+  Res |= mWeaponsDefs.Load ("Weapons", "defs/weapons.def");
+  Res |= mWeathersDefs.Load ("Weathers", "defs/weather.def");
+  Res |= mWorldsDefs.Load ("Worldinfo", "defs/worldinfo.def");
+  Res |= mWorldFilesDefs.Load ("World files", "worlds/worlds.ini");
+  Res |= mWorldModelsDefs.Load ("World models", "defs/worldmodel.def");
+  Res |= mScriptDefs.Load ("Script defs", "defs/scripts.def");
+
+  return ( Res );
+}
index d1de8d8..cc004b3 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-#include "GameServer/Definitions/Implants.hxx"\r
-#include "GameServer/Definitions/ItemContainer.hxx"\r
-#include "GameServer/Definitions/ItemMod.hxx"\r
-#include "GameServer/Definitions/ItemRes.hxx"\r
-#include "GameServer/Definitions/Items.hxx"\r
-#include "GameServer/Definitions/Mission.hxx"\r
-#include "GameServer/Definitions/NpcArmor.hxx"\r
-#include "GameServer/Definitions/NpcGroupSpawn.hxx"\r
-#include "GameServer/Definitions/Npc.hxx"\r
-#include "GameServer/Definitions/Outposts.hxx"\r
-#include "GameServer/Definitions/Recycles.hxx"\r
-#include "GameServer/Definitions/Respawn.hxx"\r
-#include "GameServer/Definitions/Scripts.hxx"\r
-#include "GameServer/Definitions/Shots.hxx"\r
-#include "GameServer/Definitions/Skills.hxx"\r
-#include "GameServer/Definitions/SubSkills.hxx"\r
-#include "GameServer/Definitions/Trader.hxx"\r
-#include "GameServer/Definitions/Vehicles.hxx"\r
-#include "GameServer/Definitions/VehicleSits.hxx"\r
-#include "GameServer/Definitions/Weapons.hxx"\r
-#include "GameServer/Definitions/Weather.hxx"\r
-#include "GameServer/Definitions/WorldFile.hxx"\r
-#include "GameServer/Definitions/WorldModels.hxx"\r
-#include "GameServer/Definitions/Worlds.hxx"\r
-\r
-typedef PDefMap<PDefActionMod> PDefActionModsMap;\r
-typedef PDefMap<PDefAmmo> PDefAmmosMap;\r
-class PDefAppartementsMap; // Derived classe for addition of specific members\r
-typedef PDefMap<PDefAppPlace> PDefAppPlacesMap; // No derived class needed here\r
-typedef PDefMap<PDefBlueprintPieces> PDefBlueprintPiecesMap;\r
-typedef PDefMap<PDefCharacter> PDefCharactersMap;\r
-typedef PDefMap<PDefCharAction> PDefCharActionsMap;\r
-typedef PDefMap<PDefCharKind> PDefCharKindsMap;\r
-typedef PDefMap<PDefDamage> PDefDamagesMap;\r
-typedef PDefMap<PDefDrug> PDefDrugsMap;\r
-typedef PDefMap<PDefFaction> PDefFactionsMap;\r
-//typedef PDefMap<PDefHack> PDefHacksMap; // File not used by KK\r
-typedef PDefMap<PDefImplant> PDefImplantsMap;\r
-typedef PDefMap<PDefItemContainer> PDefItemContainersMap;\r
-typedef PDefMap<PDefItemMod> PDefItemModsMap;\r
-typedef PDefMap<PDefItemRestriction> PDefItemRestrictionsMap;\r
-class PDefItemsMap;\r
-typedef PDefMap<PDefMission> PDefMissionsMap;\r
-typedef PDefMap<PDefNpcArmor> PDefNpcArmorsMap;\r
-typedef PDefMap<PDefNpcGroupSpawn> PDefNpcGroupSpawnsMap;\r
-typedef PDefMap<PDefNpc> PDefNpcsMap;\r
-typedef PDefMap<PDefOutpost> PDefOutpostsMap;\r
-typedef PDefMap<PDefRecycle> PDefRecyclesMap;\r
-class PDefRespawnsMap;\r
-typedef PDefMap<PDefShot> PDefShotsMap;\r
-typedef PDefMap<PDefSkill> PDefSkillsMap;\r
-typedef PDefMap<PDefSubSkill> PDefSubSkillsMap;\r
-typedef PDefMap<PDefTrader> PDefTradersMap;\r
-typedef PDefMap<PDefVhc> PDefVhcsMap;\r
-typedef PDefMap<PDefVhcSeat> PDefVhcSeatsMap;\r
-typedef PDefMap<PDefWeapon> PDefWeaponsMap;\r
-typedef PDefMap<PDefWeather> PDefWeathersMap;\r
-typedef PDefMap<PDefWorld> PDefWorldsMap;\r
-class PDefWorldFilesMap;\r
-typedef PDefMap<PDefWorldModel> PDefWorldModelsMap;\r
-\r
-class PDefScriptsMap;\r
-//typedef PDefMap<PDefScripts> PDefScriptsMap;\r
-// ___Add new entries here in alpÄ¥abetical order___\r
-\r
-\r
-class PGameDefs {\r
-private:\r
-    PDefActionModsMap mActionModsDefs;\r
-    PDefAmmosMap mAmmosDefs;\r
-    PDefAppartementsMap mAppartementsDefs;\r
-    PDefAppPlacesMap mAppPlacesDefs;\r
-    PDefBlueprintPiecesMap mBlueprintPiecesDefs;\r
-    PDefCharactersMap mCharsDefs;\r
-    PDefCharActionsMap mCharActionsDefs;\r
-    PDefCharKindsMap mCharKindsDefs;\r
-    PDefDamagesMap mDamagesDefs;\r
-    PDefDrugsMap mDrugsDefs;\r
-    PDefFactionsMap mFactionsDefs;\r
-    //PDefHacksMap mHacksDefs;\r
-    PDefImplantsMap mImplantsDefs;\r
-    PDefItemContainersMap mItemContainersDefs;\r
-    PDefItemModsMap mItemModsDefs;\r
-    PDefItemRestrictionsMap mItemRestrictionsDefs;\r
-    PDefItemsMap mItemsDefs;\r
-    PDefMissionsMap mMissionsDefs;\r
-    PDefNpcArmorsMap mNpcArmorsDefs;\r
-    PDefNpcGroupSpawnsMap mNpcGroupSpawnsDefs;\r
-    PDefNpcsMap mNpcsDefs;\r
-    PDefOutpostsMap mOutpostsDefs;\r
-    PDefRecyclesMap mRecyclesDefs;\r
-    PDefRespawnsMap mRespawnsDefs;\r
-    PDefShotsMap mShotsDefs;\r
-    PDefSkillsMap mSkillsDefs;\r
-    PDefSubSkillsMap mSubSkillsDefs;\r
-    PDefTradersMap mTradersDefs;\r
-    PDefVhcsMap mVhcsDefs;\r
-    PDefVhcSeatsMap mVhcSeatsDefs;\r
-    PDefWeaponsMap mWeaponsDefs;\r
-    PDefWeathersMap mWeathersDefs;\r
-    PDefWorldsMap mWorldsDefs;\r
-    PDefWorldFilesMap mWorldFilesDefs;\r
-    PDefWorldModelsMap mWorldModelsDefs;\r
-    PDefScriptsMap mScriptDefs;\r
-    // ___Add new entries here___\r
-\r
-public:\r
-    PGameDefs();\r
-    ~PGameDefs();\r
-\r
-    bool Init();\r
-\r
-    inline const PDefActionModsMap* ActionMods() const { return &mActionModsDefs; }\r
-    inline const PDefAmmosMap* Ammos() const { return &mAmmosDefs; }\r
-    inline const PDefAppartementsMap* Appartements() const { return &mAppartementsDefs; }\r
-    inline const PDefAppPlacesMap* AppPlaces() const { return &mAppPlacesDefs; }\r
-    inline const PDefBlueprintPiecesMap* BlueprintPieces() const { return &mBlueprintPiecesDefs; }\r
-    inline const PDefCharactersMap* Chars() const { return &mCharsDefs; }\r
-    inline const PDefCharActionsMap* CharActions() const { return &mCharActionsDefs; }\r
-    inline const PDefCharKindsMap* CharKinds() const { return &mCharKindsDefs; }\r
-    inline const PDefDamagesMap* Damages() const { return &mDamagesDefs; }\r
-    inline const PDefDrugsMap* Drugs() const { return &mDrugsDefs; }\r
-    inline const PDefFactionsMap* Factions() const { return &mFactionsDefs; }\r
-    //inline const PDefHacksMap* Hacks() const { return &mHacksDefs; }\r
-    inline const PDefImplantsMap* Implants() const { return &mImplantsDefs;}\r
-    inline const PDefItemContainersMap* ItemContainers() const { return &mItemContainersDefs; }\r
-    inline const PDefItemModsMap* ItemMods() const { return &mItemModsDefs; }\r
-    inline const PDefItemRestrictionsMap* ItemRestrictions() const { return & mItemRestrictionsDefs; }\r
-    inline const PDefItemsMap* Items() const { return &mItemsDefs; }\r
-    inline const PDefMissionsMap* Missions() const { return &mMissionsDefs; }\r
-    inline const PDefNpcArmorsMap* NpcArmors() const { return & mNpcArmorsDefs; }\r
-    inline const PDefNpcGroupSpawnsMap* GroupSpawns() const { return &mNpcGroupSpawnsDefs; }\r
-    inline const PDefNpcsMap* Npcs() const { return &mNpcsDefs; }\r
-    inline const PDefOutpostsMap* Outposts() const { return &mOutpostsDefs; }\r
-    inline const PDefRecyclesMap* Recycles() const { return &mRecyclesDefs; }\r
-    inline const PDefRespawnsMap* Respawns() const { return &mRespawnsDefs; }\r
-    inline const PDefShotsMap* Shots() const { return &mShotsDefs; }\r
-    inline const PDefSkillsMap* Skills() const { return &mSkillsDefs; }\r
-    inline const PDefSubSkillsMap* SubSkills() const { return &mSubSkillsDefs; }\r
-    inline const PDefTradersMap* Traders() const { return &mTradersDefs; }\r
-    inline const PDefVhcsMap* Vhcs() const { return &mVhcsDefs; }\r
-    inline const PDefVhcSeatsMap* VhcSeats() const { return &mVhcSeatsDefs; }\r
-    inline const PDefWeaponsMap* Weapons() const { return &mWeaponsDefs; }\r
-    inline const PDefWeathersMap* Weathers() const { return &mWeathersDefs; }\r
-    inline const PDefWorldsMap* Worlds() const { return &mWorldsDefs; }\r
-    inline const PDefWorldFilesMap* WorldFiles() const { return &mWorldFilesDefs; }\r
-    inline const PDefWorldModelsMap* WorldModels() const { return &mWorldModelsDefs; }\r
-    inline const PDefScriptsMap* Scripts() const { return &mScriptDefs; }\r
-    // ___Add new entries here___\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include "GameServer/Definitions/Definition.hxx"
+#include "GameServer/Definitions/Implants.hxx"
+#include "GameServer/Definitions/ItemContainer.hxx"
+#include "GameServer/Definitions/ItemMod.hxx"
+#include "GameServer/Definitions/ItemRes.hxx"
+#include "GameServer/Definitions/Items.hxx"
+#include "GameServer/Definitions/Mission.hxx"
+#include "GameServer/Definitions/NpcArmor.hxx"
+#include "GameServer/Definitions/NpcGroupSpawn.hxx"
+#include "GameServer/Definitions/Npc.hxx"
+#include "GameServer/Definitions/Outposts.hxx"
+#include "GameServer/Definitions/Recycles.hxx"
+#include "GameServer/Definitions/Respawn.hxx"
+#include "GameServer/Definitions/Scripts.hxx"
+#include "GameServer/Definitions/Shots.hxx"
+#include "GameServer/Definitions/Skills.hxx"
+#include "GameServer/Definitions/SubSkills.hxx"
+#include "GameServer/Definitions/Trader.hxx"
+#include "GameServer/Definitions/Vehicles.hxx"
+#include "GameServer/Definitions/VehicleSits.hxx"
+#include "GameServer/Definitions/Weapons.hxx"
+#include "GameServer/Definitions/Weather.hxx"
+#include "GameServer/Definitions/WorldFile.hxx"
+#include "GameServer/Definitions/WorldModels.hxx"
+#include "GameServer/Definitions/Worlds.hxx"
+
+typedef PDefMap<PDefActionMod> PDefActionModsMap;
+typedef PDefMap<PDefAmmo> PDefAmmosMap;
+class PDefAppartementsMap; // Derived classe for addition of specific members
+typedef PDefMap<PDefAppPlace> PDefAppPlacesMap; // No derived class needed here
+typedef PDefMap<PDefBlueprintPieces> PDefBlueprintPiecesMap;
+typedef PDefMap<PDefCharacter> PDefCharactersMap;
+typedef PDefMap<PDefCharAction> PDefCharActionsMap;
+typedef PDefMap<PDefCharKind> PDefCharKindsMap;
+typedef PDefMap<PDefDamage> PDefDamagesMap;
+typedef PDefMap<PDefDrug> PDefDrugsMap;
+typedef PDefMap<PDefFaction> PDefFactionsMap;
+//typedef PDefMap<PDefHack> PDefHacksMap; // File not used by KK
+typedef PDefMap<PDefImplant> PDefImplantsMap;
+typedef PDefMap<PDefItemContainer> PDefItemContainersMap;
+typedef PDefMap<PDefItemMod> PDefItemModsMap;
+typedef PDefMap<PDefItemRestriction> PDefItemRestrictionsMap;
+class PDefItemsMap;
+typedef PDefMap<PDefMission> PDefMissionsMap;
+typedef PDefMap<PDefNpcArmor> PDefNpcArmorsMap;
+typedef PDefMap<PDefNpcGroupSpawn> PDefNpcGroupSpawnsMap;
+typedef PDefMap<PDefNpc> PDefNpcsMap;
+typedef PDefMap<PDefOutpost> PDefOutpostsMap;
+typedef PDefMap<PDefRecycle> PDefRecyclesMap;
+class PDefRespawnsMap;
+typedef PDefMap<PDefShot> PDefShotsMap;
+typedef PDefMap<PDefSkill> PDefSkillsMap;
+typedef PDefMap<PDefSubSkill> PDefSubSkillsMap;
+typedef PDefMap<PDefTrader> PDefTradersMap;
+typedef PDefMap<PDefVhc> PDefVhcsMap;
+typedef PDefMap<PDefVhcSeat> PDefVhcSeatsMap;
+typedef PDefMap<PDefWeapon> PDefWeaponsMap;
+typedef PDefMap<PDefWeather> PDefWeathersMap;
+typedef PDefMap<PDefWorld> PDefWorldsMap;
+class PDefWorldFilesMap;
+typedef PDefMap<PDefWorldModel> PDefWorldModelsMap;
+
+class PDefScriptsMap;
+//typedef PDefMap<PDefScripts> PDefScriptsMap;
+// ___Add new entries here in alpÄ¥abetical order___
+
+
+class PGameDefs {
+private:
+    PDefActionModsMap mActionModsDefs;
+    PDefAmmosMap mAmmosDefs;
+    PDefAppartementsMap mAppartementsDefs;
+    PDefAppPlacesMap mAppPlacesDefs;
+    PDefBlueprintPiecesMap mBlueprintPiecesDefs;
+    PDefCharactersMap mCharsDefs;
+    PDefCharActionsMap mCharActionsDefs;
+    PDefCharKindsMap mCharKindsDefs;
+    PDefDamagesMap mDamagesDefs;
+    PDefDrugsMap mDrugsDefs;
+    PDefFactionsMap mFactionsDefs;
+    //PDefHacksMap mHacksDefs;
+    PDefImplantsMap mImplantsDefs;
+    PDefItemContainersMap mItemContainersDefs;
+    PDefItemModsMap mItemModsDefs;
+    PDefItemRestrictionsMap mItemRestrictionsDefs;
+    PDefItemsMap mItemsDefs;
+    PDefMissionsMap mMissionsDefs;
+    PDefNpcArmorsMap mNpcArmorsDefs;
+    PDefNpcGroupSpawnsMap mNpcGroupSpawnsDefs;
+    PDefNpcsMap mNpcsDefs;
+    PDefOutpostsMap mOutpostsDefs;
+    PDefRecyclesMap mRecyclesDefs;
+    PDefRespawnsMap mRespawnsDefs;
+    PDefShotsMap mShotsDefs;
+    PDefSkillsMap mSkillsDefs;
+    PDefSubSkillsMap mSubSkillsDefs;
+    PDefTradersMap mTradersDefs;
+    PDefVhcsMap mVhcsDefs;
+    PDefVhcSeatsMap mVhcSeatsDefs;
+    PDefWeaponsMap mWeaponsDefs;
+    PDefWeathersMap mWeathersDefs;
+    PDefWorldsMap mWorldsDefs;
+    PDefWorldFilesMap mWorldFilesDefs;
+    PDefWorldModelsMap mWorldModelsDefs;
+    PDefScriptsMap mScriptDefs;
+    // ___Add new entries here___
+
+public:
+    PGameDefs();
+    ~PGameDefs();
+
+    bool Init();
+
+    inline const PDefActionModsMap* ActionMods() const { return &mActionModsDefs; }
+    inline const PDefAmmosMap* Ammos() const { return &mAmmosDefs; }
+    inline const PDefAppartementsMap* Appartements() const { return &mAppartementsDefs; }
+    inline const PDefAppPlacesMap* AppPlaces() const { return &mAppPlacesDefs; }
+    inline const PDefBlueprintPiecesMap* BlueprintPieces() const { return &mBlueprintPiecesDefs; }
+    inline const PDefCharactersMap* Chars() const { return &mCharsDefs; }
+    inline const PDefCharActionsMap* CharActions() const { return &mCharActionsDefs; }
+    inline const PDefCharKindsMap* CharKinds() const { return &mCharKindsDefs; }
+    inline const PDefDamagesMap* Damages() const { return &mDamagesDefs; }
+    inline const PDefDrugsMap* Drugs() const { return &mDrugsDefs; }
+    inline const PDefFactionsMap* Factions() const { return &mFactionsDefs; }
+    //inline const PDefHacksMap* Hacks() const { return &mHacksDefs; }
+    inline const PDefImplantsMap* Implants() const { return &mImplantsDefs;}
+    inline const PDefItemContainersMap* ItemContainers() const { return &mItemContainersDefs; }
+    inline const PDefItemModsMap* ItemMods() const { return &mItemModsDefs; }
+    inline const PDefItemRestrictionsMap* ItemRestrictions() const { return & mItemRestrictionsDefs; }
+    inline const PDefItemsMap* Items() const { return &mItemsDefs; }
+    inline const PDefMissionsMap* Missions() const { return &mMissionsDefs; }
+    inline const PDefNpcArmorsMap* NpcArmors() const { return & mNpcArmorsDefs; }
+    inline const PDefNpcGroupSpawnsMap* GroupSpawns() const { return &mNpcGroupSpawnsDefs; }
+    inline const PDefNpcsMap* Npcs() const { return &mNpcsDefs; }
+    inline const PDefOutpostsMap* Outposts() const { return &mOutpostsDefs; }
+    inline const PDefRecyclesMap* Recycles() const { return &mRecyclesDefs; }
+    inline const PDefRespawnsMap* Respawns() const { return &mRespawnsDefs; }
+    inline const PDefShotsMap* Shots() const { return &mShotsDefs; }
+    inline const PDefSkillsMap* Skills() const { return &mSkillsDefs; }
+    inline const PDefSubSkillsMap* SubSkills() const { return &mSubSkillsDefs; }
+    inline const PDefTradersMap* Traders() const { return &mTradersDefs; }
+    inline const PDefVhcsMap* Vhcs() const { return &mVhcsDefs; }
+    inline const PDefVhcSeatsMap* VhcSeats() const { return &mVhcSeatsDefs; }
+    inline const PDefWeaponsMap* Weapons() const { return &mWeaponsDefs; }
+    inline const PDefWeathersMap* Weathers() const { return &mWeathersDefs; }
+    inline const PDefWorldsMap* Worlds() const { return &mWorldsDefs; }
+    inline const PDefWorldFilesMap* WorldFiles() const { return &mWorldFilesDefs; }
+    inline const PDefWorldModelsMap* WorldModels() const { return &mWorldModelsDefs; }
+    inline const PDefScriptsMap* Scripts() const { return &mScriptDefs; }
+    // ___Add new entries here___
+};
index 202b60e..0c059db 100644 (file)
@@ -1,27 +1,27 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefHack::PDefHack()\r
-{\r
-}\r
-\r
-bool PDefHack::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0: // setentry\r
-                continue ;\r
-\r
-\r
-            case 1: // index\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-\r
-        }\r
-    }\r
-\r
-    return true;\r
-}\r
-\r
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefHack::PDefHack()
+{
+}
+
+bool PDefHack::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0: // setentry
+                continue ;
+
+
+            case 1: // index
+                mIndex = atoi(i->c_str()); break;
+
+
+        }
+    }
+
+    return true;
+}
+
index 1a6b90a..8045e15 100644 (file)
@@ -1,16 +1,16 @@
-#pragma once\r
-\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefHack : public PDef {\r
-private:\r
-    //int mIndex;\r
-    //qui aggiungere valori\r
-public:\r
-    PDefHack();\r
-    //~PDefHack();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    //qui aggiungere funzioni per i gets\r
-};\r
+#pragma once
+
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefHack : public PDef {
+private:
+    //int mIndex;
+    //qui aggiungere valori
+public:
+    PDefHack();
+    //~PDefHack();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    //qui aggiungere funzioni per i gets
+};
index ab1ab49..2b8e54e 100644 (file)
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-#define GAMEDEFS_DEFITEMSMAXSEQ 100\r
-\r
-PDefItems::PDefItems()\r
-{\r
-  //mIndex = 0;\r
-  mModel = 0;\r
-  mType = 0;\r
-  mValue1 = 0;\r
-  mValue2 = 0;\r
-  mValue3 = 0;\r
-  //mBmNum = 0;\r
-  //mmBmNumIndex = 0;\r
-  mSizeX = 1;\r
-  mSizeY = 1;\r
-  //mSmallbmnum = 0;\r
-  mWeight = 0;\r
-  mStackable = 0;\r
-  mFillWeight = 0;\r
-  mQualifier = 0;\r
-  mGfxMods = 0;\r
-  mItemGroupID = 0;\r
-  mTextDescID = 0;\r
-  mBasePrice = 0;\r
-  mTechlevel = 0;\r
-  mItemflags = 0;\r
-  // std::mShortname = "";\r
-}\r
-\r
-bool PDefItems::LoadFromDef( PTokenList *Tokens )\r
-{\r
-  int Idx = 0;\r
-  for ( PTokenList::iterator i = Tokens->begin(); i != Tokens->end(); i++, Idx++ )\r
-  {\r
-    switch ( Idx )\r
-    {\r
-      case 0: // setentry\r
-        continue;\r
-      case 1: // index\r
-        mIndex = atoi( i->c_str() ); break;\r
-      case 2: // name\r
-        mName = *i; break;\r
-      case 3:\r
-        mModel = atoi(i->c_str()); // used for IG display\r
-        break;\r
-      case 4:\r
-        mType = atoi( i->c_str() ); break;\r
-      case 5:\r
-        mValue1 = atoi( i->c_str() ); break;\r
-      case 6:\r
-        mValue2 = atoi( i->c_str() ); break;\r
-      case 7:\r
-        mValue3 = atoi( i->c_str() ); break;\r
-      case 8:\r
-        // mBmNum = atoi(i->c_str()); // used IG for inventory display\r
-        break;\r
-      case 9:\r
-        // mmBmNumIndex = atoi(i->c_str()); // used IG for inventory display\r
-        break;\r
-      case 10:\r
-        mSizeX = atoi( i->c_str() ); break;\r
-      case 11:\r
-        mSizeY = atoi( i->c_str() ); break;\r
-      case 12:\r
-        // mSmallbmnum = atoi(i->c_str()); // used IG for inventory display\r
-        break;\r
-      case 13:\r
-        mWeight = atof( i->c_str() ); break;\r
-      case 14:\r
-        mStackable = atoi( i->c_str() ); break;\r
-      case 15:\r
-        mFillWeight = atof( i->c_str() ); break;\r
-      case 16:\r
-        mQualifier = atoi( i->c_str() ); break;\r
-      case 17:\r
-        mGfxMods = atoi( i->c_str() ); break;\r
-      case 18:\r
-        mItemGroupID = atoi( i->c_str() ); break;\r
-      case 19:\r
-        mTextDescID = atoi( i->c_str() ); break;\r
-      case 20:\r
-        mBasePrice = atoi( i->c_str() ); break;\r
-      case 21:\r
-        mTechlevel = atoi( i->c_str() ); break;\r
-      case 22:\r
-        mItemflags = atoi( i->c_str() ); break;\r
-      case 23:\r
-        // mShortname = *i; // used IG for display on inventories Icons\r
-        break;\r
-    }\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-\r
-PDefItemsMap::PDefItemsMap()\r
-{\r
-  mMapItCache = NULL;\r
-  mMapItCacheCount = 0;\r
-  mMaxItemGroupId = -1;\r
-}\r
-\r
-PDefItemsMap::~PDefItemsMap()\r
-{\r
-  delete [] mMapItCache;\r
-}\r
-\r
-void PDefItemsMap::BuildMapItCache()\r
-{\r
-  int CacheEntryIdx = 0;\r
-  int EntrySeqIdx = 1;\r
-\r
-  mMapItCacheCount = 1 + ( mDefs.size() / GAMEDEFS_DEFITEMSMAXSEQ );\r
-\r
-  if ( mMapItCacheCount )\r
-  {\r
-    if( mMapItCache )\r
-    {\r
-      delete [] mMapItCache;\r
-    }\r
-    mMapItCache = new std::map<int, PDefItems*>::const_iterator[mMapItCacheCount];\r
-    mMapItCache[CacheEntryIdx++] = mDefs.begin();\r
-\r
-    std::map<int, PDefItems*>::const_iterator It = mDefs.begin();\r
-    while ( It != mDefs.end() )\r
-    {\r
-      if ( EntrySeqIdx++ == GAMEDEFS_DEFITEMSMAXSEQ )\r
-      {\r
-        mMapItCache[CacheEntryIdx++] = It;\r
-        EntrySeqIdx = 1;\r
-      }\r
-      It++;\r
-    }\r
-  }\r
-}\r
-\r
-void PDefItemsMap::BuildItemGroups()\r
-{\r
-  //std::map<int, std::vector<int> > mItemGroups;\r
-  // Implementation more complicated than needed but avoid too many realloc\r
-  \r
-  // Group size conting\r
-  std::map<int, int> groupSize;\r
-  for ( std::map<int, PDefItems*>::const_iterator i = mDefs.begin(); i != mDefs.end(); i++ )\r
-    groupSize[ i->second->GetItemGroupID() ]++;\r
-\r
-  // Item group vectors size reservation\r
-  mItemGroups.clear();\r
-  for ( std::map<int, int>::const_iterator i = groupSize.begin(); i != groupSize.end(); i++ )\r
-  {\r
-    mItemGroups[i->first].reserve(i->second);\r
-    if(i->first > mMaxItemGroupId)\r
-      mMaxItemGroupId = i->first;\r
-    //Console->Print("Item group %d : %d items", i->first, i->second);\r
-  }\r
-  \r
-  // Effective groups building\r
-  for ( std::map<int, PDefItems*>::const_iterator i = mDefs.begin(); i != mDefs.end(); i++ )\r
-    mItemGroups[ i->second->GetItemGroupID() ].push_back(i->first); // i->first is ItemIndex\r
-}\r
-\r
-bool PDefItemsMap::Load(const char* nName, const char* nFilename)\r
-{\r
-  if( PDefMap<PDefItems>::Load( nName, nFilename) )\r
-  {\r
-    BuildMapItCache();\r
-    BuildItemGroups();\r
-    return ( true );\r
-  }\r
-  else\r
-    return ( false );\r
-}\r
-\r
-const PDefItems* PDefItemsMap::GetDefBySeqIndex( int nSeqIndex ) const\r
-{\r
-  int CacheEntryIdx = nSeqIndex / GAMEDEFS_DEFITEMSMAXSEQ;\r
-  if ( CacheEntryIdx >= mMapItCacheCount )\r
-    return NULL;\r
-\r
-  std::map<int, PDefItems*>::const_iterator It = mMapItCache[CacheEntryIdx];\r
-  int EntrySeqIdx = CacheEntryIdx * GAMEDEFS_DEFITEMSMAXSEQ;\r
-\r
-  while (( EntrySeqIdx < nSeqIndex ) && ( It != mDefs.end() ) )\r
-  {\r
-    EntrySeqIdx++;\r
-    It++;\r
-  }\r
-\r
-  if (( EntrySeqIdx == nSeqIndex ) && ( It != mDefs.end() ) )\r
-  {\r
-    return It->second;\r
-  }\r
-  else\r
-    return NULL;\r
-}\r
-\r
-int PDefItemsMap::GetRandomItemIdFromGroup( int nGroupId ) const\r
-{\r
-  if( (nGroupId >= 0) && (nGroupId <= mMaxItemGroupId) )\r
-  {\r
-    std::map<int, std::vector<int> >::const_iterator selectedEntry = mItemGroups.find(nGroupId);\r
-    if(selectedEntry != mItemGroups.end())\r
-    {\r
-      int groupSize = selectedEntry->second.size();\r
-      if( groupSize )\r
-      {\r
-        return selectedEntry->second[GetRandom(groupSize - 1, 0)];\r
-      }\r
-    }\r
-  }\r
-\r
-  return 0;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+#define GAMEDEFS_DEFITEMSMAXSEQ 100
+
+PDefItems::PDefItems()
+{
+  //mIndex = 0;
+  mModel = 0;
+  mType = 0;
+  mValue1 = 0;
+  mValue2 = 0;
+  mValue3 = 0;
+  //mBmNum = 0;
+  //mmBmNumIndex = 0;
+  mSizeX = 1;
+  mSizeY = 1;
+  //mSmallbmnum = 0;
+  mWeight = 0;
+  mStackable = 0;
+  mFillWeight = 0;
+  mQualifier = 0;
+  mGfxMods = 0;
+  mItemGroupID = 0;
+  mTextDescID = 0;
+  mBasePrice = 0;
+  mTechlevel = 0;
+  mItemflags = 0;
+  // std::mShortname = "";
+}
+
+bool PDefItems::LoadFromDef( PTokenList *Tokens )
+{
+  int Idx = 0;
+  for ( PTokenList::iterator i = Tokens->begin(); i != Tokens->end(); i++, Idx++ )
+  {
+    switch ( Idx )
+    {
+      case 0: // setentry
+        continue;
+      case 1: // index
+        mIndex = atoi( i->c_str() ); break;
+      case 2: // name
+        mName = *i; break;
+      case 3:
+        mModel = atoi(i->c_str()); // used for IG display
+        break;
+      case 4:
+        mType = atoi( i->c_str() ); break;
+      case 5:
+        mValue1 = atoi( i->c_str() ); break;
+      case 6:
+        mValue2 = atoi( i->c_str() ); break;
+      case 7:
+        mValue3 = atoi( i->c_str() ); break;
+      case 8:
+        // mBmNum = atoi(i->c_str()); // used IG for inventory display
+        break;
+      case 9:
+        // mmBmNumIndex = atoi(i->c_str()); // used IG for inventory display
+        break;
+      case 10:
+        mSizeX = atoi( i->c_str() ); break;
+      case 11:
+        mSizeY = atoi( i->c_str() ); break;
+      case 12:
+        // mSmallbmnum = atoi(i->c_str()); // used IG for inventory display
+        break;
+      case 13:
+        mWeight = atof( i->c_str() ); break;
+      case 14:
+        mStackable = atoi( i->c_str() ); break;
+      case 15:
+        mFillWeight = atof( i->c_str() ); break;
+      case 16:
+        mQualifier = atoi( i->c_str() ); break;
+      case 17:
+        mGfxMods = atoi( i->c_str() ); break;
+      case 18:
+        mItemGroupID = atoi( i->c_str() ); break;
+      case 19:
+        mTextDescID = atoi( i->c_str() ); break;
+      case 20:
+        mBasePrice = atoi( i->c_str() ); break;
+      case 21:
+        mTechlevel = atoi( i->c_str() ); break;
+      case 22:
+        mItemflags = atoi( i->c_str() ); break;
+      case 23:
+        // mShortname = *i; // used IG for display on inventories Icons
+        break;
+    }
+  }
+
+  return true;
+}
+
+
+PDefItemsMap::PDefItemsMap()
+{
+  mMapItCache = NULL;
+  mMapItCacheCount = 0;
+  mMaxItemGroupId = -1;
+}
+
+PDefItemsMap::~PDefItemsMap()
+{
+  delete [] mMapItCache;
+}
+
+void PDefItemsMap::BuildMapItCache()
+{
+  int CacheEntryIdx = 0;
+  int EntrySeqIdx = 1;
+
+  mMapItCacheCount = 1 + ( mDefs.size() / GAMEDEFS_DEFITEMSMAXSEQ );
+
+  if ( mMapItCacheCount )
+  {
+    if( mMapItCache )
+    {
+      delete [] mMapItCache;
+    }
+    mMapItCache = new std::map<int, PDefItems*>::const_iterator[mMapItCacheCount];
+    mMapItCache[CacheEntryIdx++] = mDefs.begin();
+
+    std::map<int, PDefItems*>::const_iterator It = mDefs.begin();
+    while ( It != mDefs.end() )
+    {
+      if ( EntrySeqIdx++ == GAMEDEFS_DEFITEMSMAXSEQ )
+      {
+        mMapItCache[CacheEntryIdx++] = It;
+        EntrySeqIdx = 1;
+      }
+      It++;
+    }
+  }
+}
+
+void PDefItemsMap::BuildItemGroups()
+{
+  //std::map<int, std::vector<int> > mItemGroups;
+  // Implementation more complicated than needed but avoid too many realloc
+  
+  // Group size conting
+  std::map<int, int> groupSize;
+  for ( std::map<int, PDefItems*>::const_iterator i = mDefs.begin(); i != mDefs.end(); i++ )
+    groupSize[ i->second->GetItemGroupID() ]++;
+
+  // Item group vectors size reservation
+  mItemGroups.clear();
+  for ( std::map<int, int>::const_iterator i = groupSize.begin(); i != groupSize.end(); i++ )
+  {
+    mItemGroups[i->first].reserve(i->second);
+    if(i->first > mMaxItemGroupId)
+      mMaxItemGroupId = i->first;
+    //Console->Print("Item group %d : %d items", i->first, i->second);
+  }
+  
+  // Effective groups building
+  for ( std::map<int, PDefItems*>::const_iterator i = mDefs.begin(); i != mDefs.end(); i++ )
+    mItemGroups[ i->second->GetItemGroupID() ].push_back(i->first); // i->first is ItemIndex
+}
+
+bool PDefItemsMap::Load(const char* nName, const char* nFilename)
+{
+  if( PDefMap<PDefItems>::Load( nName, nFilename) )
+  {
+    BuildMapItCache();
+    BuildItemGroups();
+    return ( true );
+  }
+  else
+    return ( false );
+}
+
+const PDefItems* PDefItemsMap::GetDefBySeqIndex( int nSeqIndex ) const
+{
+  int CacheEntryIdx = nSeqIndex / GAMEDEFS_DEFITEMSMAXSEQ;
+  if ( CacheEntryIdx >= mMapItCacheCount )
+    return NULL;
+
+  std::map<int, PDefItems*>::const_iterator It = mMapItCache[CacheEntryIdx];
+  int EntrySeqIdx = CacheEntryIdx * GAMEDEFS_DEFITEMSMAXSEQ;
+
+  while (( EntrySeqIdx < nSeqIndex ) && ( It != mDefs.end() ) )
+  {
+    EntrySeqIdx++;
+    It++;
+  }
+
+  if (( EntrySeqIdx == nSeqIndex ) && ( It != mDefs.end() ) )
+  {
+    return It->second;
+  }
+  else
+    return NULL;
+}
+
+int PDefItemsMap::GetRandomItemIdFromGroup( int nGroupId ) const
+{
+  if( (nGroupId >= 0) && (nGroupId <= mMaxItemGroupId) )
+  {
+    std::map<int, std::vector<int> >::const_iterator selectedEntry = mItemGroups.find(nGroupId);
+    if(selectedEntry != mItemGroups.end())
+    {
+      int groupSize = selectedEntry->second.size();
+      if( groupSize )
+      {
+        return selectedEntry->second[GetRandom(groupSize - 1, 0)];
+      }
+    }
+  }
+
+  return 0;
+}
index 0bf6903..bfe4576 100644 (file)
@@ -1,77 +1,77 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefItems : public PDef {\r
-private:\r
-    //int32_t mIndex;//1\r
-    std::string mName;//2\r
-    int32_t mModel; // used for IG display\r
-    int32_t mType;\r
-    int32_t mValue1;\r
-    int32_t mValue2;\r
-    int32_t mValue3;\r
-    // int32_t mBmNum; // used IG for inventory display\r
-    // int32_t mmBmNumIndex; // used IG for inventory display\r
-    int32_t mSizeX;\r
-    int32_t mSizeY;\r
-    // int32_t mSmallbmnum; // used IG for inventory display\r
-    float mWeight;\r
-    int32_t mStackable;\r
-    float mFillWeight;\r
-    int32_t mQualifier;\r
-    int32_t mGfxMods;\r
-    int32_t mItemGroupID;\r
-    int32_t mTextDescID;\r
-    int32_t mBasePrice;\r
-    int32_t mTechlevel;\r
-    int32_t mItemflags;\r
-    // std::mShortname; // used IG for display on inventories Icons\r
-\r
-public:\r
-    PDefItems();\r
-    //~PDefItems();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline int32_t GetModel() const { return mModel; }\r
-    inline int32_t GetType() const { return mType; }\r
-    inline int32_t GetValue1() const { return mValue1; }\r
-    inline int32_t GetValue2() const { return mValue2; }\r
-    inline int32_t GetValue3() const { return mValue3; }\r
-    inline int32_t GetSizeX() const { return mSizeX; }\r
-    inline int32_t GetSizeY() const { return mSizeY; }\r
-    inline float GetWeight() const { return mWeight; }\r
-    inline bool IsStackable() const { return (mStackable == 1); }\r
-    inline float GetFillWeight() const { return mFillWeight; }\r
-    inline int32_t GetQualifier() const { return mQualifier; }\r
-    inline int32_t GetGfxMods() const { return mGfxMods; }\r
-    inline int32_t GetItemGroupID() const { return mItemGroupID; }\r
-    inline int32_t GetTextDescID() const { return mTextDescID; }\r
-    inline int32_t GetBasePrice() const { return mBasePrice; }\r
-    inline int32_t GetTechlevel() const { return mTechlevel; }\r
-    inline int32_t GetItemflags() const { return mItemflags; }\r
-};\r
-\r
-class PDefItemsMap : public PDefMap<PDefItems> {\r
-private:\r
-    std::map<int32_t, PDefItems*>::const_iterator* mMapItCache;\r
-    int32_t mMapItCacheCount;\r
-    std::map<int32_t, std::vector<int32_t> > mItemGroups;\r
-    int32_t mMaxItemGroupId;\r
-    void BuildMapItCache();\r
-    void BuildItemGroups();\r
-\r
-public:\r
-    PDefItemsMap();\r
-    ~PDefItemsMap();\r
-    bool Load(const char* nName, const char* nFilename);\r
-    const PDefItems* GetDefBySeqIndex( int32_t nSeqIndex ) const;\r
-    int32_t GetRandomItemIdFromGroup( int32_t nGroupId ) const;\r
-\r
-    inline std::map<int32_t, PDefItems*>::const_iterator ConstIteratorBegin() const { return mDefs.begin(); }\r
-    inline std::map<int32_t, PDefItems*>::const_iterator ConstIteratorEnd() const { return mDefs.end(); }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefItems : public PDef {
+private:
+    //int32_t mIndex;//1
+    std::string mName;//2
+    int32_t mModel; // used for IG display
+    int32_t mType;
+    int32_t mValue1;
+    int32_t mValue2;
+    int32_t mValue3;
+    // int32_t mBmNum; // used IG for inventory display
+    // int32_t mmBmNumIndex; // used IG for inventory display
+    int32_t mSizeX;
+    int32_t mSizeY;
+    // int32_t mSmallbmnum; // used IG for inventory display
+    float mWeight;
+    int32_t mStackable;
+    float mFillWeight;
+    int32_t mQualifier;
+    int32_t mGfxMods;
+    int32_t mItemGroupID;
+    int32_t mTextDescID;
+    int32_t mBasePrice;
+    int32_t mTechlevel;
+    int32_t mItemflags;
+    // std::mShortname; // used IG for display on inventories Icons
+
+public:
+    PDefItems();
+    //~PDefItems();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline int32_t GetModel() const { return mModel; }
+    inline int32_t GetType() const { return mType; }
+    inline int32_t GetValue1() const { return mValue1; }
+    inline int32_t GetValue2() const { return mValue2; }
+    inline int32_t GetValue3() const { return mValue3; }
+    inline int32_t GetSizeX() const { return mSizeX; }
+    inline int32_t GetSizeY() const { return mSizeY; }
+    inline float GetWeight() const { return mWeight; }
+    inline bool IsStackable() const { return (mStackable == 1); }
+    inline float GetFillWeight() const { return mFillWeight; }
+    inline int32_t GetQualifier() const { return mQualifier; }
+    inline int32_t GetGfxMods() const { return mGfxMods; }
+    inline int32_t GetItemGroupID() const { return mItemGroupID; }
+    inline int32_t GetTextDescID() const { return mTextDescID; }
+    inline int32_t GetBasePrice() const { return mBasePrice; }
+    inline int32_t GetTechlevel() const { return mTechlevel; }
+    inline int32_t GetItemflags() const { return mItemflags; }
+};
+
+class PDefItemsMap : public PDefMap<PDefItems> {
+private:
+    std::map<int32_t, PDefItems*>::const_iterator* mMapItCache;
+    int32_t mMapItCacheCount;
+    std::map<int32_t, std::vector<int32_t> > mItemGroups;
+    int32_t mMaxItemGroupId;
+    void BuildMapItCache();
+    void BuildItemGroups();
+
+public:
+    PDefItemsMap();
+    ~PDefItemsMap();
+    bool Load(const char* nName, const char* nFilename);
+    const PDefItems* GetDefBySeqIndex( int32_t nSeqIndex ) const;
+    int32_t GetRandomItemIdFromGroup( int32_t nGroupId ) const;
+
+    inline std::map<int32_t, PDefItems*>::const_iterator ConstIteratorBegin() const { return mDefs.begin(); }
+    inline std::map<int32_t, PDefItems*>::const_iterator ConstIteratorEnd() const { return mDefs.end(); }
+};
index a91e76a..5d1206f 100644 (file)
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-\r
-PDefParser::PDefParser()\r
-{\r
-}\r
-\r
-PDefParser::~PDefParser()\r
-{\r
-    for(PDefTokenList::iterator i=mTokens.begin(); i!=mTokens.end(); i++)\r
-        delete *i;\r
-}\r
-\r
-bool PDefParser::Parse(const char *File)\r
-{\r
-    PFile *f = Filesystem->Open("", File, Config->GetOption("nc_data_path"));\r
-    enum { NOPE, MAYBE, LINE, BLOCK, MAYBE_END } Comment = NOPE;\r
-\r
-    if(f)\r
-    {\r
-        while(!f->Eof())\r
-        {\r
-            std::string Str = f->ReadString();\r
-            int Len = Str.length();\r
-            if(Len <= 0)\r
-                continue;\r
-\r
-            if(Str.substr(0, 3)!="set")\r
-                continue;\r
-\r
-            //Console->Print("%s", Str.c_str());//NEW was commented , just to be sure of what we are reading\r
-\r
-            PTokenList *List = new PTokenList();\r
-            int Start=0, Tokens=0;\r
-            bool Quote=false;\r
-            for(int i=0; i<Len; i++)\r
-            {\r
-                if(Str[i]=='\r' || Str[i]=='\n' || Str[i]=='|' || Str[i]==';')\r
-                {\r
-                    if(Comment < LINE)\r
-                    {\r
-                        int End=i-1;\r
-                        if(End >= Start)\r
-                        {\r
-                            List->push_back(std::string(Str.substr(Start, (End-Start)+1)));\r
-                            Tokens++;\r
-                            break;\r
-                        }\r
-                        Quote=false;\r
-                    }\r
-                    if(Comment != BLOCK)\r
-                        Comment=NOPE;\r
-                    break;\r
-                }\r
-\r
-                if(!Quote)\r
-                {\r
-                    if(Comment < LINE && (Str[i]=='\t' || Str[i]==',' || Str[i]==' ' || Str[i]==';' || Str[i]=='|' || i==Len-1))\r
-                    {\r
-                        int End=i-1;\r
-                        if(End >= Start)\r
-                        {\r
-                            List->push_back(std::string(Str.substr(Start, (End-Start)+1)));\r
-                            Tokens++;\r
-                        }\r
-                        Start=i+1;\r
-                    }\r
-\r
-                    if(Str[i] <= ' ')\r
-                        continue;\r
-\r
-                    if(Str[i]=='*')\r
-                    {\r
-                        if(Comment==MAYBE)\r
-                            Comment=BLOCK;\r
-                        else\r
-                        if(Comment==BLOCK)\r
-                            Comment=MAYBE_END;\r
-                    } else\r
-                    if(Str[i]=='/')\r
-                    {\r
-                        if(Comment==MAYBE)\r
-                        {\r
-                            // second slash, skip rest of line\r
-                            Comment=LINE;\r
-                            break;\r
-                        } else\r
-                        if(Comment==MAYBE_END)\r
-                        {\r
-                            Comment=NOPE;   // comment block ends\r
-                            Start=i+1;\r
-                        } else\r
-                            if(Comment != BLOCK)\r
-                                Comment=MAYBE;  // first slash\r
-                    } else\r
-                    {\r
-                        if(Comment==MAYBE)\r
-                            Comment=NOPE;   // stand-alone slash\r
-                        else\r
-                        if(Comment==MAYBE_END)\r
-                            Comment=BLOCK;  // comment block did not end\r
-                    }\r
-                }\r
-\r
-                if(Str[i]=='"')\r
-                    Quote ^= true;\r
-            }\r
-\r
-            if(Tokens > 0)\r
-                mTokens.push_back(List);\r
-            else\r
-                delete List;\r
-        }\r
-    } else\r
-    {\r
-        Console->Print("%s PDefParser::Parse: could not open file %s", Console->ColorText( RED, BLACK, "[ERROR]" ), File);\r
-        return false;\r
-    }\r
-\r
-    return true;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+#include "GameServer/Includes.hxx"
+
+PDefParser::PDefParser()
+{
+}
+
+PDefParser::~PDefParser()
+{
+    for(PDefTokenList::iterator i=mTokens.begin(); i!=mTokens.end(); i++)
+        delete *i;
+}
+
+bool PDefParser::Parse(const char *File)
+{
+    PFile *f = Filesystem->Open("", File, Config->GetOption("nc_data_path"));
+    enum { NOPE, MAYBE, LINE, BLOCK, MAYBE_END } Comment = NOPE;
+
+    if(f)
+    {
+        while(!f->Eof())
+        {
+            std::string Str = f->ReadString();
+            int Len = Str.length();
+            if(Len <= 0)
+                continue;
+
+            if(Str.substr(0, 3)!="set")
+                continue;
+
+            //Console->Print("%s", Str.c_str());//NEW was commented , just to be sure of what we are reading
+
+            PTokenList *List = new PTokenList();
+            int Start=0, Tokens=0;
+            bool Quote=false;
+            for(int i=0; i<Len; i++)
+            {
+                if(Str[i]=='\r' || Str[i]=='\n' || Str[i]=='|' || Str[i]==';')
+                {
+                    if(Comment < LINE)
+                    {
+                        int End=i-1;
+                        if(End >= Start)
+                        {
+                            List->push_back(std::string(Str.substr(Start, (End-Start)+1)));
+                            Tokens++;
+                            break;
+                        }
+                        Quote=false;
+                    }
+                    if(Comment != BLOCK)
+                        Comment=NOPE;
+                    break;
+                }
+
+                if(!Quote)
+                {
+                    if(Comment < LINE && (Str[i]=='\t' || Str[i]==',' || Str[i]==' ' || Str[i]==';' || Str[i]=='|' || i==Len-1))
+                    {
+                        int End=i-1;
+                        if(End >= Start)
+                        {
+                            List->push_back(std::string(Str.substr(Start, (End-Start)+1)));
+                            Tokens++;
+                        }
+                        Start=i+1;
+                    }
+
+                    if(Str[i] <= ' ')
+                        continue;
+
+                    if(Str[i]=='*')
+                    {
+                        if(Comment==MAYBE)
+                            Comment=BLOCK;
+                        else
+                        if(Comment==BLOCK)
+                            Comment=MAYBE_END;
+                    } else
+                    if(Str[i]=='/')
+                    {
+                        if(Comment==MAYBE)
+                        {
+                            // second slash, skip rest of line
+                            Comment=LINE;
+                            break;
+                        } else
+                        if(Comment==MAYBE_END)
+                        {
+                            Comment=NOPE;   // comment block ends
+                            Start=i+1;
+                        } else
+                            if(Comment != BLOCK)
+                                Comment=MAYBE;  // first slash
+                    } else
+                    {
+                        if(Comment==MAYBE)
+                            Comment=NOPE;   // stand-alone slash
+                        else
+                        if(Comment==MAYBE_END)
+                            Comment=BLOCK;  // comment block did not end
+                    }
+                }
+
+                if(Str[i]=='"')
+                    Quote ^= true;
+            }
+
+            if(Tokens > 0)
+                mTokens.push_back(List);
+            else
+                delete List;
+        }
+    } else
+    {
+        Console->Print("%s PDefParser::Parse: could not open file %s", Console->ColorText( RED, BLACK, "[ERROR]" ), File);
+        return false;
+    }
+
+    return true;
+}
index c9f3741..818fc84 100644 (file)
@@ -1,18 +1,18 @@
-#pragma once\r
-\r
-#include <list>\r
-#include <string>\r
-\r
-typedef std::list<std::string> PTokenList;\r
-typedef std::list<PTokenList *> PDefTokenList;\r
-\r
-class PDefParser {\r
-private:\r
-    PDefTokenList mTokens;\r
-\r
-public:\r
-    PDefParser();\r
-    ~PDefParser();\r
-    bool Parse(const char *File);\r
-    inline const PDefTokenList &GetTokens() const { return mTokens; }\r
-};\r
+#pragma once
+
+#include <list>
+#include <string>
+
+typedef std::list<std::string> PTokenList;
+typedef std::list<PTokenList *> PDefTokenList;
+
+class PDefParser {
+private:
+    PDefTokenList mTokens;
+
+public:
+    PDefParser();
+    ~PDefParser();
+    bool Parse(const char *File);
+    inline const PDefTokenList &GetTokens() const { return mTokens; }
+};
index bf992e7..8d8a317 100644 (file)
@@ -1,64 +1,64 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefRespawn::PDefRespawn()\r
-{\r
-}\r
-\r
-bool PDefRespawn::LoadFromDef( PTokenList *Tokens )\r
-{\r
-  int Idx = 0;\r
-  for ( PTokenList::iterator i = Tokens->begin(); i != Tokens->end(); i++, Idx++ )\r
-  {\r
-    switch ( Idx )\r
-    {\r
-      case 0: // setentry\r
-        continue;\r
-\r
-      case 1: // index\r
-        mIndex = atoi( i->c_str() ); break;\r
-\r
-      case 2: // value\r
-        mWorldID = atoi( i->c_str() ); break;\r
-\r
-      case 3: // value\r
-        mEntityID = atoi( i->c_str() ); break;\r
-\r
-      case 4: // value\r
-        mHazardLevel = atoi( i->c_str() ); break;\r
-\r
-      case 5: // name\r
-        mName = *i; break;\r
-\r
-      case 6: // world name\r
-        mFlag = *i; break;\r
-    }\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-// class PDefRespawnMap defined in gamedefs.h\r
-int PDefRespawnsMap::GetRespawnEntity( uint32_t nWorldID, uint16_t nGROrder ) const\r
-{\r
-  uint16_t tOrder = 0;\r
-\r
-  for ( std::map<int, PDefRespawn*>::const_iterator it = mDefs.begin(); it != mDefs.end(); it++ )\r
-  {\r
-    if (( uint32_t )( it->second->GetWorldID() ) == nWorldID )\r
-    {\r
-      ++tOrder;\r
-      if (( nWorldID == 1 ) || ( nWorldID == 2 ) ) // hack for zones 1 & 2\r
-      {\r
-        if (( 3 - tOrder ) == nGROrder )\r
-        {\r
-          return ( it->second->GetEntityID() );\r
-        }\r
-      }\r
-      else if ( tOrder == nGROrder )\r
-      {\r
-        return ( it->second->GetEntityID() );\r
-      }\r
-    }\r
-  }\r
-  return 0;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefRespawn::PDefRespawn()
+{
+}
+
+bool PDefRespawn::LoadFromDef( PTokenList *Tokens )
+{
+  int Idx = 0;
+  for ( PTokenList::iterator i = Tokens->begin(); i != Tokens->end(); i++, Idx++ )
+  {
+    switch ( Idx )
+    {
+      case 0: // setentry
+        continue;
+
+      case 1: // index
+        mIndex = atoi( i->c_str() ); break;
+
+      case 2: // value
+        mWorldID = atoi( i->c_str() ); break;
+
+      case 3: // value
+        mEntityID = atoi( i->c_str() ); break;
+
+      case 4: // value
+        mHazardLevel = atoi( i->c_str() ); break;
+
+      case 5: // name
+        mName = *i; break;
+
+      case 6: // world name
+        mFlag = *i; break;
+    }
+  }
+
+  return true;
+}
+
+// class PDefRespawnMap defined in gamedefs.h
+int PDefRespawnsMap::GetRespawnEntity( uint32_t nWorldID, uint16_t nGROrder ) const
+{
+  uint16_t tOrder = 0;
+
+  for ( std::map<int, PDefRespawn*>::const_iterator it = mDefs.begin(); it != mDefs.end(); it++ )
+  {
+    if (( uint32_t )( it->second->GetWorldID() ) == nWorldID )
+    {
+      ++tOrder;
+      if (( nWorldID == 1 ) || ( nWorldID == 2 ) ) // hack for zones 1 & 2
+      {
+        if (( 3 - tOrder ) == nGROrder )
+        {
+          return ( it->second->GetEntityID() );
+        }
+      }
+      else if ( tOrder == nGROrder )
+      {
+        return ( it->second->GetEntityID() );
+      }
+    }
+  }
+  return 0;
+}
index 52b573d..fcaf910 100644 (file)
@@ -1,32 +1,32 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefRespawn : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    int32_t mWorldID;\r
-    int32_t mEntityID; // Station ID\r
-    int32_t mHazardLevel;\r
-    std::string mName; // Description\r
-    std::string mFlag; // ???\r
-\r
-public:\r
-    PDefRespawn();\r
-    //~PDefRespawn();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline int32_t GetWorldID() const { return mWorldID; }\r
-    inline int32_t GetEntityID() const { return mEntityID; }\r
-    inline int32_t GetHazardLevel() const { return mHazardLevel; }\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline const std::string &GetFlag() const { return mFlag; }\r
-};\r
-\r
-class PDefRespawnsMap : public PDefMap<PDefRespawn> {\r
-public:\r
-    int32_t GetRespawnEntity( uint32_t nWorldID, uint16_t nGROrder ) const;\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefRespawn : public PDef {
+private:
+    //int32_t mIndex;
+    int32_t mWorldID;
+    int32_t mEntityID; // Station ID
+    int32_t mHazardLevel;
+    std::string mName; // Description
+    std::string mFlag; // ???
+
+public:
+    PDefRespawn();
+    //~PDefRespawn();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline int32_t GetWorldID() const { return mWorldID; }
+    inline int32_t GetEntityID() const { return mEntityID; }
+    inline int32_t GetHazardLevel() const { return mHazardLevel; }
+    inline const std::string &GetName() const { return mName; }
+    inline const std::string &GetFlag() const { return mFlag; }
+};
+
+class PDefRespawnsMap : public PDefMap<PDefRespawn> {
+public:
+    int32_t GetRespawnEntity( uint32_t nWorldID, uint16_t nGROrder ) const;
+};
index 14c28c5..a0d208d 100644 (file)
@@ -1,63 +1,63 @@
-#include <cstring>\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-\r
-// skill.def includes skill names and skill/subskill mapping\r
-\r
-PDefSkill::PDefSkill()\r
-{\r
-    mSubSkills = 0;\r
-    mNumSubSkills = 0;\r
-}\r
-\r
-PDefSkill::~PDefSkill()\r
-{\r
-    delete [] mSubSkills;\r
-}\r
-\r
-bool PDefSkill::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0 :    // setentry\r
-                continue;\r
-\r
-            case 1 :\r
-                mIndex = atol(i->c_str()); break;\r
-\r
-            case 2 :\r
-                mName = *i; break;\r
-\r
-            case 3 :\r
-                mShortName = *i; break;\r
-\r
-            case 4 :\r
-            {\r
-                mNumSubSkills = atol(i->c_str());\r
-                mSubSkills = new int[mNumSubSkills];\r
-                std::memset(mSubSkills, 0, sizeof(int)*mNumSubSkills);\r
-                break;\r
-            }\r
-        }\r
-\r
-        if(Idx >= 5)\r
-        {\r
-            mSubSkills[Idx-5] = atoi(i->c_str());\r
-            if(!GameDefs->SubSkills()->GetDef(mSubSkills[Idx-5]))\r
-            {\r
-                Console->Print("Skill def error: skill %s refers to nonexistant subskill %i", mShortName.c_str(), mSubSkills[Idx-5]);\r
-                return false;\r
-            }\r
-        }\r
-    }\r
-\r
-    if(Idx-5 != mNumSubSkills)\r
-    {\r
-        Console->Print("Warning: skill %s has incorrect number of subskills", mShortName.c_str());\r
-        Console->Print("  Expected %i, available %i", mNumSubSkills, Idx-5);\r
-    }\r
-    return true;\r
-}\r
+#include <cstring>
+#include "GameServer/Definitions/Includes.hxx"
+#include "GameServer/Includes.hxx"
+
+// skill.def includes skill names and skill/subskill mapping
+
+PDefSkill::PDefSkill()
+{
+    mSubSkills = 0;
+    mNumSubSkills = 0;
+}
+
+PDefSkill::~PDefSkill()
+{
+    delete [] mSubSkills;
+}
+
+bool PDefSkill::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0 :    // setentry
+                continue;
+
+            case 1 :
+                mIndex = atol(i->c_str()); break;
+
+            case 2 :
+                mName = *i; break;
+
+            case 3 :
+                mShortName = *i; break;
+
+            case 4 :
+            {
+                mNumSubSkills = atol(i->c_str());
+                mSubSkills = new int[mNumSubSkills];
+                std::memset(mSubSkills, 0, sizeof(int)*mNumSubSkills);
+                break;
+            }
+        }
+
+        if(Idx >= 5)
+        {
+            mSubSkills[Idx-5] = atoi(i->c_str());
+            if(!GameDefs->SubSkills()->GetDef(mSubSkills[Idx-5]))
+            {
+                Console->Print("Skill def error: skill %s refers to nonexistant subskill %i", mShortName.c_str(), mSubSkills[Idx-5]);
+                return false;
+            }
+        }
+    }
+
+    if(Idx-5 != mNumSubSkills)
+    {
+        Console->Print("Warning: skill %s has incorrect number of subskills", mShortName.c_str());
+        Console->Print("  Expected %i, available %i", mNumSubSkills, Idx-5);
+    }
+    return true;
+}
index dcf42f8..45cc4c1 100644 (file)
@@ -1,24 +1,24 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefSkill : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    std::string mShortName;\r
-    int32_t mNumSubSkills;\r
-    int32_t *mSubSkills;\r
-public:\r
-    PDefSkill();\r
-    ~PDefSkill();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline const std::string &GetShortName() const { return mShortName; }\r
-    inline int32_t GetNumSubSkills() const { return mNumSubSkills; }\r
-    inline int32_t GetSubSkill(int32_t Index) const { return mSubSkills[Index]; }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefSkill : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName;
+    std::string mShortName;
+    int32_t mNumSubSkills;
+    int32_t *mSubSkills;
+public:
+    PDefSkill();
+    ~PDefSkill();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline const std::string &GetShortName() const { return mShortName; }
+    inline int32_t GetNumSubSkills() const { return mNumSubSkills; }
+    inline int32_t GetSubSkill(int32_t Index) const { return mSubSkills[Index]; }
+};
index ac6512f..87d02d1 100644 (file)
@@ -1,54 +1,54 @@
-#include <cstring>\r
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-// subskill.def, names and parameters of all subskills\r
-\r
-PDefSubSkill::PDefSubSkill()\r
-{\r
-    mActionModifiers = 0;\r
-    mNumActionModifiers = 0;\r
-}\r
-\r
-PDefSubSkill::~PDefSubSkill()\r
-{\r
-    delete [] mActionModifiers;\r
-}\r
-\r
-bool PDefSubSkill::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0 :    // setentry\r
-                continue;\r
-\r
-            case 1 :\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2 :\r
-                mName = *i; break;\r
-\r
-            case 3 :\r
-                mShortName = *i; break;\r
-\r
-            case 4 :\r
-                mStrengthenFactor = static_cast<float>(atof(i->c_str())); break;\r
-\r
-            case 5 :\r
-            {\r
-                mNumActionModifiers = atoi(i->c_str());\r
-                mActionModifiers = new int[mNumActionModifiers];\r
-                std::memset(mActionModifiers, 0, sizeof(int)*mNumActionModifiers);\r
-                break;\r
-            }\r
-        }\r
-\r
-        if(Idx>=6)\r
-            mActionModifiers[Idx-6] = atoi(i->c_str());\r
-    }\r
-\r
-    return true;\r
-}\r
-\r
+#include <cstring>
+#include "GameServer/Definitions/Includes.hxx"
+
+// subskill.def, names and parameters of all subskills
+
+PDefSubSkill::PDefSubSkill()
+{
+    mActionModifiers = 0;
+    mNumActionModifiers = 0;
+}
+
+PDefSubSkill::~PDefSubSkill()
+{
+    delete [] mActionModifiers;
+}
+
+bool PDefSubSkill::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0 :    // setentry
+                continue;
+
+            case 1 :
+                mIndex = atoi(i->c_str()); break;
+
+            case 2 :
+                mName = *i; break;
+
+            case 3 :
+                mShortName = *i; break;
+
+            case 4 :
+                mStrengthenFactor = static_cast<float>(atof(i->c_str())); break;
+
+            case 5 :
+            {
+                mNumActionModifiers = atoi(i->c_str());
+                mActionModifiers = new int[mNumActionModifiers];
+                std::memset(mActionModifiers, 0, sizeof(int)*mNumActionModifiers);
+                break;
+            }
+        }
+
+        if(Idx>=6)
+            mActionModifiers[Idx-6] = atoi(i->c_str());
+    }
+
+    return true;
+}
+
index d2d1195..01dd301 100644 (file)
@@ -1,27 +1,27 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefSubSkill : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    std::string mShortName;\r
-    float mStrengthenFactor;\r
-    int32_t mNumActionModifiers;\r
-    int32_t *mActionModifiers;\r
-\r
-public:\r
-    PDefSubSkill();\r
-    ~PDefSubSkill();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline const std::string &GetShortName() const { return mShortName; }\r
-    inline float GetStrengthenFactor() const { return mStrengthenFactor; }\r
-    inline int32_t GetNumActionModifiers() const { return mNumActionModifiers; }\r
-    inline int32_t GetActionModifier(int32_t Index) const { return mActionModifiers[Index]; }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefSubSkill : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName;
+    std::string mShortName;
+    float mStrengthenFactor;
+    int32_t mNumActionModifiers;
+    int32_t *mActionModifiers;
+
+public:
+    PDefSubSkill();
+    ~PDefSubSkill();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline const std::string &GetShortName() const { return mShortName; }
+    inline float GetStrengthenFactor() const { return mStrengthenFactor; }
+    inline int32_t GetNumActionModifiers() const { return mNumActionModifiers; }
+    inline int32_t GetActionModifier(int32_t Index) const { return mActionModifiers[Index]; }
+};
index 86a4354..346a320 100644 (file)
-#include <cmath>\r
-#include <cstring>\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-\r
-const uint16_t nonDiscardUseFlags = ufTouchable | ufUsable | ufChair | ufToolTarget ; // furniture always to keep even if function type = 0\r
-\r
-PWorldDatParser::PWorldDatParser()\r
-{\r
-    f = NULL;\r
-}\r
-\r
-PWorldDatParser::~PWorldDatParser()\r
-{\r
-\r
-}\r
-\r
-int PWorldDatParser::LoadDatFile( const std::string& nFilename, PWorldDataTemplate* nWorld, const bool nDiscardPassiveObjects, const bool nTestAccesOnly )\r
-{\r
-    PWorldFileHeader FileHeader;\r
-    PSectionHeader SectionHeader;\r
-    PSec2ElemHeader Sec2ElemHeader;\r
-\r
-    uint32_t FileLen;\r
-    uint32_t NextSectionOffset = 0;\r
-    uint32_t NextElementOffset;\r
-    bool ProcessOK;\r
-\r
-    mWorld = nWorld;\r
-    mDiscardPassiveObjects = nDiscardPassiveObjects;\r
-\r
-    if ( mNCDataPath == "" )\r
-    {\r
-        mNCDataPath = Config->GetOption( "nc_data_path" );\r
-    }\r
-\r
-    if ( gDevDebug )\r
-        Console->Print( "Reading file %s/%s", mNCDataPath.c_str(), nFilename.c_str() );\r
-    f = Filesystem->Open( "", nFilename.c_str(), mNCDataPath );\r
-\r
-    if ( nTestAccesOnly )\r
-    {\r
-        ProcessOK = ( bool )f;\r
-        Filesystem->Close( f );\r
-        return ( ProcessOK ? 0 : -1 );\r
-    }\r
-\r
-    if ( f )\r
-    {\r
-        FileLen = f->GetSize();\r
-\r
-        // Section 1\r
-        if (gDevDebug)\r
-            Console->Print( "Reading file header (section 1) ... " );\r
-        f->Read( &FileHeader, sizeof( PWorldFileHeader ) );\r
-        if (( FileHeader.mHeaderSize != 0x00000008 )\r
-                || ( FileHeader.mHeaderSig != 0x000fcfcf )\r
-                || ( FileHeader.mSection != 0x00000001 ) )\r
-        {\r
-            if (gDevDebug)\r
-                Console->Print( "Read header: %08x / %08x / %08x",  FileHeader.mHeaderSize, FileHeader.mHeaderSig, FileHeader.mSection);\r
-            Filesystem->Close( f );\r
-            return -2;\r
-        }\r
-        NextSectionOffset += FileHeader.mHeaderSize + 4;\r
-\r
-        // Other Sections\r
-        //  Header\r
-        while ( ! f->Eof() )\r
-        {\r
-            f->Seek( NextSectionOffset ); // Make sure we are at the computed offset\r
-            if (gDevDebug)\r
-                Console->Print( "Reading next section header ... " );\r
-            if (( uint32_t )( f->Read( &SectionHeader, sizeof( PSectionHeader ) ) ) < sizeof( PSectionHeader ) )\r
-            {\r
-                Filesystem->Close( f );\r
-                return -3;\r
-            }\r
-\r
-            if (( SectionHeader.mHeaderSize != 0x0000000c ) || ( SectionHeader.mHeaderSig != 0x0000ffcf ) )\r
-            {\r
-                Filesystem->Close( f );\r
-                return -2;\r
-            }\r
-\r
-            if ( SectionHeader.mSection == 0 )\r
-            {\r
-                if (gDevDebug)\r
-                    Console->Print( "Ending section reached" );\r
-                break;\r
-            }\r
-\r
-            NextElementOffset = NextSectionOffset + SectionHeader.mHeaderSize + 4;\r
-            NextSectionOffset = NextElementOffset + SectionHeader.mDataSize;\r
-            if (gDevDebug)\r
-                Console->Print( "Processing section %d (size %d)", SectionHeader.mSection, SectionHeader.mDataSize );\r
-\r
-            if ( SectionHeader.mSection == 2 )\r
-            {\r
-                //int cnt=0;\r
-                if ( gDevDebug )\r
-                    Console->Print( "Element Type 3 size: %d or %d", sizeof( PSec2ElemType3a ), sizeof( PSec2ElemType3a ) + sizeof( PSec2ElemType3b ) );\r
-                while ( NextElementOffset < NextSectionOffset )\r
-                {\r
-                    f->Seek( NextElementOffset ); // Make sure we are at the computed offset\r
-\r
-                    //if ( gDevDebug )\r
-                    //    Console->Print( "Reading next element header ... " );\r
-                    if (( uint32_t )( f->Read( &Sec2ElemHeader, sizeof( PSec2ElemHeader ) ) ) < sizeof( PSec2ElemHeader ) )\r
-                    {\r
-                        Filesystem->Close( f );\r
-                        return -3;\r
-                    }\r
-                    if (( Sec2ElemHeader.mHeaderSize != 0x0000000c ) || ( Sec2ElemHeader.mHeaderSig != 0x0ffefef1 ) )\r
-                    {\r
-                        Filesystem->Close( f );\r
-                        return -2;\r
-                    }\r
-                    NextElementOffset += ( Sec2ElemHeader.mHeaderSize + 4 + Sec2ElemHeader.mDataSize );\r
-                    //if (gDevDebug) Console->Print("Found element %d of type %d, size %d", ++cnt, Sec2ElemHeader.mElementType, Sec2ElemHeader.mDataSize);\r
-                    switch ( Sec2ElemHeader.mElementType )\r
-                    {\r
-                    case 1000003:\r
-                    {\r
-                        ProcessOK = ProcessSec2ElemType3( Sec2ElemHeader.mDataSize );\r
-                        break;\r
-                    }\r
-                    case 1000005:\r
-                    {\r
-                        ProcessOK = ProcessSec2ElemType5( Sec2ElemHeader.mDataSize );\r
-                        break;\r
-                    }\r
-                    case 1000006:\r
-                    {\r
-                        ProcessOK = ProcessSec2NPCEntry( Sec2ElemHeader.mDataSize );\r
-                        break;\r
-                    }\r
-                    default:\r
-                    {\r
-                        if (gDevDebug) Console->Print( "Ignoring SectionID %d, not supportet yet", Sec2ElemHeader.mElementType );\r
-                        ProcessOK = true;\r
-                        break;\r
-                    }\r
-                    }\r
-\r
-                    if ( !ProcessOK )\r
-                        return -4;\r
-                }\r
-            }\r
-            else\r
-            {\r
-                if ( gDevDebug )\r
-                    Console->Print( "Section %d ignored", SectionHeader.mSection );\r
-                continue;\r
-            }\r
-\r
-        }\r
-\r
-        Filesystem->Close( f );\r
-    }\r
-    else\r
-    {\r
-        return -1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-bool PWorldDatParser::ProcessSec2ElemType3( uint32_t nSize ) // furniture\r
-{\r
-    PSec2ElemType3a DataA;\r
-    PSec2ElemType3b DataB;\r
-    const PDefWorldModel* nWorldModel;\r
-    std::string nName;\r
-    const uint32_t sza = sizeof( PSec2ElemType3a );\r
-    const uint32_t szb = sizeof( PSec2ElemType3a ) + sizeof( PSec2ElemType3b );\r
-\r
-    if (( nSize != szb ) && ( nSize != sza ) )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Wrong size for Sec2ElemType3 (%d read vs %d or %d needed", nSize, sza, szb );\r
-        return false;\r
-    }\r
-    if (( uint32_t )( f->Read( &DataA, sza ) ) < sza )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType3a" );\r
-        return false;\r
-    }\r
-    if ( nSize == szb )\r
-    {\r
-        if (( uint32_t )( f->Read( &DataB, sizeof( PSec2ElemType3b ) ) ) < sizeof( PSec2ElemType3b ) )\r
-        {\r
-            Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType3b" );\r
-            return false;\r
-        }\r
-    }\r
-    else\r
-    {\r
-        DataB.mBoxLowerY = DataB.mBoxLowerZ = DataB.mBoxLowerX = 0;\r
-        DataB.mBoxUpperY = DataB.mBoxUpperZ = DataB.mBoxUpperX = 0;\r
-    }\r
-\r
-    if ( DataA.mWorldmodelID )\r
-    {\r
-        nWorldModel = GameDefs->WorldModels()->GetDef( DataA.mWorldmodelID );\r
-        if ( nWorldModel )\r
-            nName = nWorldModel->GetName();\r
-        else\r
-            nName = "UNKNOWN";\r
-    }\r
-    else\r
-    {\r
-        nName = "PASSIVE";\r
-        nWorldModel = NULL;\r
-    }\r
-\r
-    /* if (gDevDebug) {\r
-    Console->Print("-------------------------------------------------------");\r
-    Console->Print("%s (%d) : ID %d", nName.c_str(), DataA.mWorldmodelID, DataA.mObjectID);\r
-    if (!nWorldModel) Console->Print("y:%f z:%f x:%f model %d", DataA.mPosY , DataA.mPosZ, DataA.mPosX, DataA.mModelID);\r
-    Console->Print("Scale:%f Uk2:0x%08x Uk3:0x%08x", DataA.mScale, DataA.mUnknown2, DataA.mUnknown3);\r
-    Console->Print("Uk4:0x%08x Uk5:0x%04x", DataA.mUnknown4, DataA.mUnknown5);\r
-    //Console->Print("Ly:%f Lz:%f Lx:%f", DataB.mBoxLowerY, DataB.mBoxLowerZ, DataB.mBoxLowerX);\r
-    //Console->Print("Uy:%f Uz:%f Ux:%f", DataB.mBoxUpperY, DataB.mBoxUpperZ, DataB.mBoxUpperX);\r
-    }*/\r
-\r
-    if (( !nWorldModel || ( !nWorldModel->GetFunctionType() && !( nWorldModel->GetUseFlags() & nonDiscardUseFlags ) ) ) && mDiscardPassiveObjects )\r
-    {\r
-        //if ( gDevDebug )\r
-        //    Console->Print( "Discarded" );\r
-        return true;\r
-    }\r
-\r
-    PFurnitureItemTemplate* nItem = new PFurnitureItemTemplate;\r
-    nItem->mObjectID = DataA.mObjectID;\r
-\r
-    // The commented out values are not loaded from dat file atm because they are not used yet.\r
-    nItem->mPosY = DataA.mPosY; // float pos values are kept 0-centered\r
-    nItem->mPosZ = DataA.mPosZ;\r
-    nItem->mPosX = DataA.mPosX;\r
-//  nItem->mRotY = DataA.mRotY;\r
-    nItem->mRotZ = DataA.mRotZ;\r
-//  nItem->mRotX = DataA.mRotX;\r
-//  nItem->mScale = DataA.mScale;\r
-//  nItem->mUnknown2 = DataA.mUnknown2;\r
-    nItem->mModelID = DataA.mModelID;\r
-//  nItem->mUnknown3 = DataA.mUnknown3;\r
-//  nItem->mUnknown4 = DataA.mUnknown4;\r
-    nItem->mWorldmodelID = DataA.mWorldmodelID;\r
-//  nItem->mUnknown5 = DataA.mUnknown5;\r
-\r
-//  nItem->mBoxLowerY = DataB.mBoxLowerY;\r
-//  nItem->mBoxLowerZ = DataB.mBoxLowerZ;\r
-//  nItem->mBoxLowerX = DataB.mBoxLowerX;\r
-//  nItem->mBoxUpperY = DataB.mBoxUpperY;\r
-//  nItem->mBoxUpperZ = DataB.mBoxUpperZ;\r
-//  nItem->mBoxUpperX = DataB.mBoxUpperX;\r
-\r
-    nItem->mDefWorldModel = nWorldModel;\r
-    /*uint16_t func=nWorldModel->GetFunctionType();\r
-    if((func==18) || (func==20) || (func==29))\r
-    Console->Print("gate model: %d", DataA.mWorldmodelID);*/\r
-\r
-    float Angle = ( 180 + DataA.mRotZ ) * 3.14159 / 180;\r
-    float Radius = abs(( int )(( DataB.mBoxUpperX - DataB.mBoxLowerX ) / 2 ) );\r
-    if ( Radius == 0 )\r
-    {\r
-        Radius = 10;\r
-    }\r
-    Radius *= DataA.mScale;\r
-    Radius += 5;\r
-\r
-    // int pos values are change to match char pos scale (32000 centered)\r
-    nItem->mFrontPosY = ( uint16_t )( 32000 + DataA.mPosY + Radius * sinf( Angle ) );\r
-    nItem->mFrontPosZ = ( uint16_t )( 32000 + DataA.mPosZ );\r
-    nItem->mFrontPosX = ( uint16_t )( 32000 + DataA.mPosX + Radius * cosf( Angle ) );\r
-    nItem->mFrontLR = ( uint8_t )( 0.5 * ( DataA.mRotZ + ( DataA.mRotZ < 0 ? 360 : 0 ) ) );\r
-\r
-    mWorld->AddFurnitureItem( nItem );\r
-\r
-    return true;\r
-}\r
-\r
-bool PWorldDatParser::ProcessSec2ElemType5( uint32_t nSize ) // doors\r
-{\r
-    PSec2ElemType5Start Data;\r
-    char StringData[64];\r
-\r
-    const PDefWorldModel* nWorldModel;\r
-    std::string nName;\r
-    char* ActorString;\r
-    char* ParamString;\r
-\r
-    const uint32_t sza = sizeof( PSec2ElemType5Start );\r
-\r
-    if (( nSize < sza ) )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Wrong size for Sec2ElemType5 (%d read vs %d needed", nSize, sza );\r
-        return false;\r
-    }\r
-    if (( uint32_t )( f->Read( &Data, sza ) ) < sza )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType5start" );\r
-        return false;\r
-    }\r
-    uint32_t szb = Data.mActorStringSize  + Data.mParamStringSize;\r
-\r
-    if ( nSize != ( sza + szb ) )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Wrong size for Sec2ElemType5 (%d read vs %d needed", nSize, sza + szb );\r
-        return false;\r
-    }\r
-    else\r
-    {\r
-        if ( szb > 64 )\r
-        {\r
-            Console->Print( RED, BLACK, "[Warning] String data too long in Sec2ElemType5 End String. End will be ignored" );\r
-            szb = 64;\r
-        }\r
-        if (( uint32_t )( f->Read( StringData, szb ) ) < szb )\r
-        {\r
-            Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType5 End Strings" );\r
-            return false;\r
-        }\r
-    }\r
-\r
-    if ( Data.mWorldmodelID )\r
-    {\r
-        nWorldModel = GameDefs->WorldModels()->GetDef( Data.mWorldmodelID );\r
-        if ( nWorldModel )\r
-            nName = nWorldModel->GetName();\r
-        else\r
-            nName = "UNKNOWN";\r
-    }\r
-    else\r
-    {\r
-        nName = "PASSIVE";\r
-        nWorldModel = NULL;\r
-    }\r
-\r
-    StringData[Data.mActorStringSize - 1] = 0;\r
-    ActorString = StringData;\r
-    StringData[szb - 1] = 0;\r
-    ParamString = StringData + Data.mActorStringSize;\r
-    /*\r
-        if ( gDevDebug )\r
-        {\r
-            Console->Print( "-------------------------------------------------------" );\r
-            Console->Print( "Door %s (%d) : ID %d", nName.c_str(), Data.mWorldmodelID, Data.mDoorID );\r
-            Console->Print( "y:%f z:%f x:%f", Data.mPosY , Data.mPosZ, Data.mPosX );\r
-            Console->Print( "Uk1:0x%04x Uk1bis:0x%04x Uk5:0x%04x", Data.mUnknown1, Data.mUnknown1bis, Data.mUnknown5 );\r
-            Console->Print( "Type=%s Param=%s", ActorString, ParamString );\r
-        }\r
-    */\r
-// Let's keep knowledge of doors even without models !\r
-    /*  if ((!nWorldModel || (!nWorldModel->GetFunctionType() && !(nWorldModel->GetUseFlags() & nonDiscardUseFlags))) && mDiscardPassiveObjects)\r
-      {\r
-    if (gDevDebug) Console->Print("Discarded");\r
-    if (gDevDebug)\r
-    {\r
-    Console->Print("Door %s (%d) : ID %d", nName.c_str(), Data.mWorldmodelID, Data.mDoorID);\r
-    Console->Print("Type=%s Param=%s", ActorString, ParamString);\r
-    }\r
-        return true;\r
-      }*/\r
-\r
-    PDoorTemplate* nDoor = new PDoorTemplate;\r
-    nDoor->mDoorID = Data.mDoorID;\r
-\r
-    //nDoor->mUnknown1 = Data.mUnknown1; //18 00\r
-    //nDoor->mUnknown1bis = Data.mUnknown1bis; //00 00 ? varies\r
-    nDoor->mPosY = Data.mPosY;\r
-    nDoor->mPosZ = Data.mPosZ;\r
-    nDoor->mPosX = Data.mPosX;\r
-    //nDoor->mUnknown5 = Data.mUnknown5; //00 00 ? second byte varies\r
-    nDoor->mWorldmodelID = Data.mWorldmodelID; //door type from worldmodel.def\r
-    nDoor->mDefWorldModel = nWorldModel;\r
-\r
-    nDoor->SetDoorTypeName( ActorString );\r
-    nDoor->SetDoorParameters( ParamString );\r
-\r
-    mWorld->AddDoor( nDoor );\r
-\r
-    return true;\r
-}\r
-\r
-bool PWorldDatParser::ProcessSec2NPCEntry( uint32_t nSize )\r
-{\r
-    PSec2NPC_EntryPart1         tNPCPartA;\r
-    PSec2NPC_EntryPart2         tNPCPartB;\r
-    std::string                 tActorName;\r
-    std::string                 tAngle;\r
-    char                        tStrBuffer[64];\r
-\r
-    uint32_t tSizeOfA = sizeof(tNPCPartA);\r
-    uint32_t tSizeOfB = sizeof(tNPCPartB);\r
-\r
-    // Are we able to read enough bytes from the file? means: CAN we safely read our entire struct from the file?\r
-    if ( nSize < tSizeOfA )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Wrong size for PSec2NPC_EntryPart1 (%d read vs %d needed", nSize, tSizeOfA );\r
-        return false;\r
-    }\r
-    // yes we can! So read it now. If we reach EOF, break\r
-    if (( uint32_t )( f->Read( &tNPCPartA, tSizeOfA ) ) < tSizeOfA )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry" );\r
-        return false;\r
-    }\r
-    // Now we have the header. lets check if we have some waypoints for this NPC\r
-    // Size of entire NPC entry in file\r
-    uint32_t tCompleteNPCSize = tSizeOfA + tNPCPartA.mActorStringSize + tNPCPartA.mAngleStringSize;\r
-    if ( tNPCPartA.mHasAdditionalCoords > 0 )\r
-    {\r
-        // It has additional coords, add 'em\r
-        tCompleteNPCSize += tSizeOfB*tNPCPartA.mHasAdditionalCoords;\r
-    }\r
-\r
-    // Do a last check if we're on the correct size\r
-    if ( nSize != tCompleteNPCSize )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Wrong size for PSec2NPC_Entry (%d available vs %d expected", nSize, tCompleteNPCSize );\r
-        Console->Print( RED, BLACK, "NPC ID was: %d", tNPCPartA.mNpcID);\r
-        return false;\r
-    }\r
-    // We are. Continue reading!\r
-    // Assign the 2 strings and watch out for EOF!\r
-    memset(tStrBuffer, 0, 64);\r
-    if (( uint32_t )( f->Read( tStrBuffer, tNPCPartA.mActorStringSize ) ) < tNPCPartA.mActorStringSize )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry mActorStringSize" );\r
-        return false;\r
-    }\r
-    tActorName = tStrBuffer;\r
-\r
-    memset(tStrBuffer, 0, 64);\r
-    if (( uint32_t )( f->Read( tStrBuffer, tNPCPartA.mAngleStringSize ) ) < tNPCPartA.mAngleStringSize )\r
-    {\r
-        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry mAngleStringSize" );\r
-        return false;\r
-    }\r
-    tAngle = tStrBuffer;\r
-\r
-    // We're done. Now create new NPC entry\r
-    PNPCTemplate* tNPC = new PNPCTemplate;\r
-\r
-    // and assing all that stuff\r
-    tNPC->SetUnknown1(tNPCPartA.mUnknown1);\r
-    tNPC->SetPosX(tNPCPartA.mPosX);\r
-    tNPC->SetPosY(tNPCPartA.mPosY);\r
-    tNPC->SetPosZ(tNPCPartA.mPosZ);\r
-    tNPC->SetNPCTypeID(tNPCPartA.mNPCTypeID);\r
-    tNPC->SetActorStrSize(tNPCPartA.mActorStringSize);\r
-    tNPC->SetAngleStrSize(tNPCPartA.mAngleStringSize);\r
-    tNPC->SetNpcID(tNPCPartA.mNpcID);\r
-    tNPC->SetUnknown2a(tNPCPartA.mUnknown2a);\r
-    tNPC->SetUnknown2b(tNPCPartA.mUnknown2b);\r
-    tNPC->SetUnknown2c(tNPCPartA.mUnknown2c);\r
-    tNPC->SetTradeID/*SetUnknown3*/(tNPCPartA.mTradeID/*mUnknown3*/);\r
-    tNPC->SetUnknown4(tNPCPartA.mUnknown4);\r
-\r
-    tNPC->SetActorName(tActorName);\r
-    tNPC->SetAngle(tAngle);\r
-\r
-    // Read additional Waypoints if available\r
-    uint8_t tCurrWayP = 0;\r
-    if ( tNPCPartA.mHasAdditionalCoords > 0 )\r
-    {\r
-        while ( tCurrWayP < tNPCPartA.mHasAdditionalCoords )\r
-        {\r
-            memset(&tNPCPartB, 0, tSizeOfB);\r
-            if (( uint32_t )( f->Read( &tNPCPartB, tSizeOfB ) ) < tSizeOfB )\r
-            {\r
-                Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry while reading WayPoints" );\r
-                return false;\r
-            }\r
-            tNPC->AddWayPoint(tNPCPartB.mPosX, tNPCPartB.mPosY, tNPCPartB.mPosZ, tCurrWayP);\r
-            tCurrWayP++;\r
-        }\r
-    }\r
-\r
-    if (gDevDebug) Console->Print("Added NPC ID %d", tNPCPartA.mNpcID);\r
-\r
-    mWorld->AddNPC(tNPC);\r
-    return true;\r
-}\r
+#include <cmath>
+#include <cstring>
+#include "GameServer/Definitions/Includes.hxx"
+#include "GameServer/Includes.hxx"
+
+const uint16_t nonDiscardUseFlags = ufTouchable | ufUsable | ufChair | ufToolTarget ; // furniture always to keep even if function type = 0
+
+PWorldDatParser::PWorldDatParser()
+{
+    f = NULL;
+}
+
+PWorldDatParser::~PWorldDatParser()
+{
+
+}
+
+int PWorldDatParser::LoadDatFile( const std::string& nFilename, PWorldDataTemplate* nWorld, const bool nDiscardPassiveObjects, const bool nTestAccesOnly )
+{
+    PWorldFileHeader FileHeader;
+    PSectionHeader SectionHeader;
+    PSec2ElemHeader Sec2ElemHeader;
+
+    uint32_t FileLen;
+    uint32_t NextSectionOffset = 0;
+    uint32_t NextElementOffset;
+    bool ProcessOK;
+
+    mWorld = nWorld;
+    mDiscardPassiveObjects = nDiscardPassiveObjects;
+
+    if ( mNCDataPath == "" )
+    {
+        mNCDataPath = Config->GetOption( "nc_data_path" );
+    }
+
+    if ( gDevDebug )
+        Console->Print( "Reading file %s/%s", mNCDataPath.c_str(), nFilename.c_str() );
+    f = Filesystem->Open( "", nFilename.c_str(), mNCDataPath );
+
+    if ( nTestAccesOnly )
+    {
+        ProcessOK = ( bool )f;
+        Filesystem->Close( f );
+        return ( ProcessOK ? 0 : -1 );
+    }
+
+    if ( f )
+    {
+        FileLen = f->GetSize();
+
+        // Section 1
+        if (gDevDebug)
+            Console->Print( "Reading file header (section 1) ... " );
+        f->Read( &FileHeader, sizeof( PWorldFileHeader ) );
+        if (( FileHeader.mHeaderSize != 0x00000008 )
+                || ( FileHeader.mHeaderSig != 0x000fcfcf )
+                || ( FileHeader.mSection != 0x00000001 ) )
+        {
+            if (gDevDebug)
+                Console->Print( "Read header: %08x / %08x / %08x",  FileHeader.mHeaderSize, FileHeader.mHeaderSig, FileHeader.mSection);
+            Filesystem->Close( f );
+            return -2;
+        }
+        NextSectionOffset += FileHeader.mHeaderSize + 4;
+
+        // Other Sections
+        //  Header
+        while ( ! f->Eof() )
+        {
+            f->Seek( NextSectionOffset ); // Make sure we are at the computed offset
+            if (gDevDebug)
+                Console->Print( "Reading next section header ... " );
+            if (( uint32_t )( f->Read( &SectionHeader, sizeof( PSectionHeader ) ) ) < sizeof( PSectionHeader ) )
+            {
+                Filesystem->Close( f );
+                return -3;
+            }
+
+            if (( SectionHeader.mHeaderSize != 0x0000000c ) || ( SectionHeader.mHeaderSig != 0x0000ffcf ) )
+            {
+                Filesystem->Close( f );
+                return -2;
+            }
+
+            if ( SectionHeader.mSection == 0 )
+            {
+                if (gDevDebug)
+                    Console->Print( "Ending section reached" );
+                break;
+            }
+
+            NextElementOffset = NextSectionOffset + SectionHeader.mHeaderSize + 4;
+            NextSectionOffset = NextElementOffset + SectionHeader.mDataSize;
+            if (gDevDebug)
+                Console->Print( "Processing section %d (size %d)", SectionHeader.mSection, SectionHeader.mDataSize );
+
+            if ( SectionHeader.mSection == 2 )
+            {
+                //int cnt=0;
+                if ( gDevDebug )
+                    Console->Print( "Element Type 3 size: %d or %d", sizeof( PSec2ElemType3a ), sizeof( PSec2ElemType3a ) + sizeof( PSec2ElemType3b ) );
+                while ( NextElementOffset < NextSectionOffset )
+                {
+                    f->Seek( NextElementOffset ); // Make sure we are at the computed offset
+
+                    //if ( gDevDebug )
+                    //    Console->Print( "Reading next element header ... " );
+                    if (( uint32_t )( f->Read( &Sec2ElemHeader, sizeof( PSec2ElemHeader ) ) ) < sizeof( PSec2ElemHeader ) )
+                    {
+                        Filesystem->Close( f );
+                        return -3;
+                    }
+                    if (( Sec2ElemHeader.mHeaderSize != 0x0000000c ) || ( Sec2ElemHeader.mHeaderSig != 0x0ffefef1 ) )
+                    {
+                        Filesystem->Close( f );
+                        return -2;
+                    }
+                    NextElementOffset += ( Sec2ElemHeader.mHeaderSize + 4 + Sec2ElemHeader.mDataSize );
+                    //if (gDevDebug) Console->Print("Found element %d of type %d, size %d", ++cnt, Sec2ElemHeader.mElementType, Sec2ElemHeader.mDataSize);
+                    switch ( Sec2ElemHeader.mElementType )
+                    {
+                    case 1000003:
+                    {
+                        ProcessOK = ProcessSec2ElemType3( Sec2ElemHeader.mDataSize );
+                        break;
+                    }
+                    case 1000005:
+                    {
+                        ProcessOK = ProcessSec2ElemType5( Sec2ElemHeader.mDataSize );
+                        break;
+                    }
+                    case 1000006:
+                    {
+                        ProcessOK = ProcessSec2NPCEntry( Sec2ElemHeader.mDataSize );
+                        break;
+                    }
+                    default:
+                    {
+                        if (gDevDebug) Console->Print( "Ignoring SectionID %d, not supportet yet", Sec2ElemHeader.mElementType );
+                        ProcessOK = true;
+                        break;
+                    }
+                    }
+
+                    if ( !ProcessOK )
+                        return -4;
+                }
+            }
+            else
+            {
+                if ( gDevDebug )
+                    Console->Print( "Section %d ignored", SectionHeader.mSection );
+                continue;
+            }
+
+        }
+
+        Filesystem->Close( f );
+    }
+    else
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
+bool PWorldDatParser::ProcessSec2ElemType3( uint32_t nSize ) // furniture
+{
+    PSec2ElemType3a DataA;
+    PSec2ElemType3b DataB;
+    const PDefWorldModel* nWorldModel;
+    std::string nName;
+    const uint32_t sza = sizeof( PSec2ElemType3a );
+    const uint32_t szb = sizeof( PSec2ElemType3a ) + sizeof( PSec2ElemType3b );
+
+    if (( nSize != szb ) && ( nSize != sza ) )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Wrong size for Sec2ElemType3 (%d read vs %d or %d needed", nSize, sza, szb );
+        return false;
+    }
+    if (( uint32_t )( f->Read( &DataA, sza ) ) < sza )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType3a" );
+        return false;
+    }
+    if ( nSize == szb )
+    {
+        if (( uint32_t )( f->Read( &DataB, sizeof( PSec2ElemType3b ) ) ) < sizeof( PSec2ElemType3b ) )
+        {
+            Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType3b" );
+            return false;
+        }
+    }
+    else
+    {
+        DataB.mBoxLowerY = DataB.mBoxLowerZ = DataB.mBoxLowerX = 0;
+        DataB.mBoxUpperY = DataB.mBoxUpperZ = DataB.mBoxUpperX = 0;
+    }
+
+    if ( DataA.mWorldmodelID )
+    {
+        nWorldModel = GameDefs->WorldModels()->GetDef( DataA.mWorldmodelID );
+        if ( nWorldModel )
+            nName = nWorldModel->GetName();
+        else
+            nName = "UNKNOWN";
+    }
+    else
+    {
+        nName = "PASSIVE";
+        nWorldModel = NULL;
+    }
+
+    /* if (gDevDebug) {
+    Console->Print("-------------------------------------------------------");
+    Console->Print("%s (%d) : ID %d", nName.c_str(), DataA.mWorldmodelID, DataA.mObjectID);
+    if (!nWorldModel) Console->Print("y:%f z:%f x:%f model %d", DataA.mPosY , DataA.mPosZ, DataA.mPosX, DataA.mModelID);
+    Console->Print("Scale:%f Uk2:0x%08x Uk3:0x%08x", DataA.mScale, DataA.mUnknown2, DataA.mUnknown3);
+    Console->Print("Uk4:0x%08x Uk5:0x%04x", DataA.mUnknown4, DataA.mUnknown5);
+    //Console->Print("Ly:%f Lz:%f Lx:%f", DataB.mBoxLowerY, DataB.mBoxLowerZ, DataB.mBoxLowerX);
+    //Console->Print("Uy:%f Uz:%f Ux:%f", DataB.mBoxUpperY, DataB.mBoxUpperZ, DataB.mBoxUpperX);
+    }*/
+
+    if (( !nWorldModel || ( !nWorldModel->GetFunctionType() && !( nWorldModel->GetUseFlags() & nonDiscardUseFlags ) ) ) && mDiscardPassiveObjects )
+    {
+        //if ( gDevDebug )
+        //    Console->Print( "Discarded" );
+        return true;
+    }
+
+    PFurnitureItemTemplate* nItem = new PFurnitureItemTemplate;
+    nItem->mObjectID = DataA.mObjectID;
+
+    // The commented out values are not loaded from dat file atm because they are not used yet.
+    nItem->mPosY = DataA.mPosY; // float pos values are kept 0-centered
+    nItem->mPosZ = DataA.mPosZ;
+    nItem->mPosX = DataA.mPosX;
+//  nItem->mRotY = DataA.mRotY;
+    nItem->mRotZ = DataA.mRotZ;
+//  nItem->mRotX = DataA.mRotX;
+//  nItem->mScale = DataA.mScale;
+//  nItem->mUnknown2 = DataA.mUnknown2;
+    nItem->mModelID = DataA.mModelID;
+//  nItem->mUnknown3 = DataA.mUnknown3;
+//  nItem->mUnknown4 = DataA.mUnknown4;
+    nItem->mWorldmodelID = DataA.mWorldmodelID;
+//  nItem->mUnknown5 = DataA.mUnknown5;
+
+//  nItem->mBoxLowerY = DataB.mBoxLowerY;
+//  nItem->mBoxLowerZ = DataB.mBoxLowerZ;
+//  nItem->mBoxLowerX = DataB.mBoxLowerX;
+//  nItem->mBoxUpperY = DataB.mBoxUpperY;
+//  nItem->mBoxUpperZ = DataB.mBoxUpperZ;
+//  nItem->mBoxUpperX = DataB.mBoxUpperX;
+
+    nItem->mDefWorldModel = nWorldModel;
+    /*uint16_t func=nWorldModel->GetFunctionType();
+    if((func==18) || (func==20) || (func==29))
+    Console->Print("gate model: %d", DataA.mWorldmodelID);*/
+
+    float Angle = ( 180 + DataA.mRotZ ) * 3.14159 / 180;
+    float Radius = abs(( int )(( DataB.mBoxUpperX - DataB.mBoxLowerX ) / 2 ) );
+    if ( Radius == 0 )
+    {
+        Radius = 10;
+    }
+    Radius *= DataA.mScale;
+    Radius += 5;
+
+    // int pos values are change to match char pos scale (32000 centered)
+    nItem->mFrontPosY = ( uint16_t )( 32000 + DataA.mPosY + Radius * sinf( Angle ) );
+    nItem->mFrontPosZ = ( uint16_t )( 32000 + DataA.mPosZ );
+    nItem->mFrontPosX = ( uint16_t )( 32000 + DataA.mPosX + Radius * cosf( Angle ) );
+    nItem->mFrontLR = ( uint8_t )( 0.5 * ( DataA.mRotZ + ( DataA.mRotZ < 0 ? 360 : 0 ) ) );
+
+    mWorld->AddFurnitureItem( nItem );
+
+    return true;
+}
+
+bool PWorldDatParser::ProcessSec2ElemType5( uint32_t nSize ) // doors
+{
+    PSec2ElemType5Start Data;
+    char StringData[64];
+
+    const PDefWorldModel* nWorldModel;
+    std::string nName;
+    char* ActorString;
+    char* ParamString;
+
+    const uint32_t sza = sizeof( PSec2ElemType5Start );
+
+    if (( nSize < sza ) )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Wrong size for Sec2ElemType5 (%d read vs %d needed", nSize, sza );
+        return false;
+    }
+    if (( uint32_t )( f->Read( &Data, sza ) ) < sza )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType5start" );
+        return false;
+    }
+    uint32_t szb = Data.mActorStringSize  + Data.mParamStringSize;
+
+    if ( nSize != ( sza + szb ) )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Wrong size for Sec2ElemType5 (%d read vs %d needed", nSize, sza + szb );
+        return false;
+    }
+    else
+    {
+        if ( szb > 64 )
+        {
+            Console->Print( RED, BLACK, "[Warning] String data too long in Sec2ElemType5 End String. End will be ignored" );
+            szb = 64;
+        }
+        if (( uint32_t )( f->Read( StringData, szb ) ) < szb )
+        {
+            Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in Sec2ElemType5 End Strings" );
+            return false;
+        }
+    }
+
+    if ( Data.mWorldmodelID )
+    {
+        nWorldModel = GameDefs->WorldModels()->GetDef( Data.mWorldmodelID );
+        if ( nWorldModel )
+            nName = nWorldModel->GetName();
+        else
+            nName = "UNKNOWN";
+    }
+    else
+    {
+        nName = "PASSIVE";
+        nWorldModel = NULL;
+    }
+
+    StringData[Data.mActorStringSize - 1] = 0;
+    ActorString = StringData;
+    StringData[szb - 1] = 0;
+    ParamString = StringData + Data.mActorStringSize;
+    /*
+        if ( gDevDebug )
+        {
+            Console->Print( "-------------------------------------------------------" );
+            Console->Print( "Door %s (%d) : ID %d", nName.c_str(), Data.mWorldmodelID, Data.mDoorID );
+            Console->Print( "y:%f z:%f x:%f", Data.mPosY , Data.mPosZ, Data.mPosX );
+            Console->Print( "Uk1:0x%04x Uk1bis:0x%04x Uk5:0x%04x", Data.mUnknown1, Data.mUnknown1bis, Data.mUnknown5 );
+            Console->Print( "Type=%s Param=%s", ActorString, ParamString );
+        }
+    */
+// Let's keep knowledge of doors even without models !
+    /*  if ((!nWorldModel || (!nWorldModel->GetFunctionType() && !(nWorldModel->GetUseFlags() & nonDiscardUseFlags))) && mDiscardPassiveObjects)
+      {
+    if (gDevDebug) Console->Print("Discarded");
+    if (gDevDebug)
+    {
+    Console->Print("Door %s (%d) : ID %d", nName.c_str(), Data.mWorldmodelID, Data.mDoorID);
+    Console->Print("Type=%s Param=%s", ActorString, ParamString);
+    }
+        return true;
+      }*/
+
+    PDoorTemplate* nDoor = new PDoorTemplate;
+    nDoor->mDoorID = Data.mDoorID;
+
+    //nDoor->mUnknown1 = Data.mUnknown1; //18 00
+    //nDoor->mUnknown1bis = Data.mUnknown1bis; //00 00 ? varies
+    nDoor->mPosY = Data.mPosY;
+    nDoor->mPosZ = Data.mPosZ;
+    nDoor->mPosX = Data.mPosX;
+    //nDoor->mUnknown5 = Data.mUnknown5; //00 00 ? second byte varies
+    nDoor->mWorldmodelID = Data.mWorldmodelID; //door type from worldmodel.def
+    nDoor->mDefWorldModel = nWorldModel;
+
+    nDoor->SetDoorTypeName( ActorString );
+    nDoor->SetDoorParameters( ParamString );
+
+    mWorld->AddDoor( nDoor );
+
+    return true;
+}
+
+bool PWorldDatParser::ProcessSec2NPCEntry( uint32_t nSize )
+{
+    PSec2NPC_EntryPart1         tNPCPartA;
+    PSec2NPC_EntryPart2         tNPCPartB;
+    std::string                 tActorName;
+    std::string                 tAngle;
+    char                        tStrBuffer[64];
+
+    uint32_t tSizeOfA = sizeof(tNPCPartA);
+    uint32_t tSizeOfB = sizeof(tNPCPartB);
+
+    // Are we able to read enough bytes from the file? means: CAN we safely read our entire struct from the file?
+    if ( nSize < tSizeOfA )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Wrong size for PSec2NPC_EntryPart1 (%d read vs %d needed", nSize, tSizeOfA );
+        return false;
+    }
+    // yes we can! So read it now. If we reach EOF, break
+    if (( uint32_t )( f->Read( &tNPCPartA, tSizeOfA ) ) < tSizeOfA )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry" );
+        return false;
+    }
+    // Now we have the header. lets check if we have some waypoints for this NPC
+    // Size of entire NPC entry in file
+    uint32_t tCompleteNPCSize = tSizeOfA + tNPCPartA.mActorStringSize + tNPCPartA.mAngleStringSize;
+    if ( tNPCPartA.mHasAdditionalCoords > 0 )
+    {
+        // It has additional coords, add 'em
+        tCompleteNPCSize += tSizeOfB*tNPCPartA.mHasAdditionalCoords;
+    }
+
+    // Do a last check if we're on the correct size
+    if ( nSize != tCompleteNPCSize )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Wrong size for PSec2NPC_Entry (%d available vs %d expected", nSize, tCompleteNPCSize );
+        Console->Print( RED, BLACK, "NPC ID was: %d", tNPCPartA.mNpcID);
+        return false;
+    }
+    // We are. Continue reading!
+    // Assign the 2 strings and watch out for EOF!
+    memset(tStrBuffer, 0, 64);
+    if (( uint32_t )( f->Read( tStrBuffer, tNPCPartA.mActorStringSize ) ) < tNPCPartA.mActorStringSize )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry mActorStringSize" );
+        return false;
+    }
+    tActorName = tStrBuffer;
+
+    memset(tStrBuffer, 0, 64);
+    if (( uint32_t )( f->Read( tStrBuffer, tNPCPartA.mAngleStringSize ) ) < tNPCPartA.mAngleStringSize )
+    {
+        Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry mAngleStringSize" );
+        return false;
+    }
+    tAngle = tStrBuffer;
+
+    // We're done. Now create new NPC entry
+    PNPCTemplate* tNPC = new PNPCTemplate;
+
+    // and assing all that stuff
+    tNPC->SetUnknown1(tNPCPartA.mUnknown1);
+    tNPC->SetPosX(tNPCPartA.mPosX);
+    tNPC->SetPosY(tNPCPartA.mPosY);
+    tNPC->SetPosZ(tNPCPartA.mPosZ);
+    tNPC->SetNPCTypeID(tNPCPartA.mNPCTypeID);
+    tNPC->SetActorStrSize(tNPCPartA.mActorStringSize);
+    tNPC->SetAngleStrSize(tNPCPartA.mAngleStringSize);
+    tNPC->SetNpcID(tNPCPartA.mNpcID);
+    tNPC->SetUnknown2a(tNPCPartA.mUnknown2a);
+    tNPC->SetUnknown2b(tNPCPartA.mUnknown2b);
+    tNPC->SetUnknown2c(tNPCPartA.mUnknown2c);
+    tNPC->SetTradeID/*SetUnknown3*/(tNPCPartA.mTradeID/*mUnknown3*/);
+    tNPC->SetUnknown4(tNPCPartA.mUnknown4);
+
+    tNPC->SetActorName(tActorName);
+    tNPC->SetAngle(tAngle);
+
+    // Read additional Waypoints if available
+    uint8_t tCurrWayP = 0;
+    if ( tNPCPartA.mHasAdditionalCoords > 0 )
+    {
+        while ( tCurrWayP < tNPCPartA.mHasAdditionalCoords )
+        {
+            memset(&tNPCPartB, 0, tSizeOfB);
+            if (( uint32_t )( f->Read( &tNPCPartB, tSizeOfB ) ) < tSizeOfB )
+            {
+                Console->Print( RED, BLACK, "[ERROR] Unexpected end of file in ProcessSec2NPCEntry while reading WayPoints" );
+                return false;
+            }
+            tNPC->AddWayPoint(tNPCPartB.mPosX, tNPCPartB.mPosY, tNPCPartB.mPosZ, tCurrWayP);
+            tCurrWayP++;
+        }
+    }
+
+    if (gDevDebug) Console->Print("Added NPC ID %d", tNPCPartA.mNpcID);
+
+    mWorld->AddNPC(tNPC);
+    return true;
+}
index dfe60bd..136b408 100644 (file)
@@ -1,26 +1,26 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-\r
-class PFile;\r
-class PWorldDataTemplate;\r
-\r
-class PWorldDatParser {\r
-private:\r
-    PFile* f;\r
-    std::string mNCDataPath;\r
-\r
-    PWorldDataTemplate* mWorld;\r
-    bool mDiscardPassiveObjects;\r
-\r
-    bool ProcessSec2ElemType3(uint32_t nSize);\r
-    bool ProcessSec2ElemType5(uint32_t nSize);\r
-    bool ProcessSec2NPCEntry(uint32_t nSize);\r
-\r
-public:\r
-    PWorldDatParser();\r
-    ~PWorldDatParser();\r
-\r
-    int32_t LoadDatFile(const std::string& nFilename, PWorldDataTemplate* nWorld, const bool nDiscardPassiveObjects = true, const bool nTestAccesOnly = false);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+class PFile;
+class PWorldDataTemplate;
+
+class PWorldDatParser {
+private:
+    PFile* f;
+    std::string mNCDataPath;
+
+    PWorldDataTemplate* mWorld;
+    bool mDiscardPassiveObjects;
+
+    bool ProcessSec2ElemType3(uint32_t nSize);
+    bool ProcessSec2ElemType5(uint32_t nSize);
+    bool ProcessSec2NPCEntry(uint32_t nSize);
+
+public:
+    PWorldDatParser();
+    ~PWorldDatParser();
+
+    int32_t LoadDatFile(const std::string& nFilename, PWorldDataTemplate* nWorld, const bool nDiscardPassiveObjects = true, const bool nTestAccesOnly = false);
+};
index 0d1d4a1..57f92c7 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-struct PWorldFileHeader {\r
-    uint32_t mHeaderSize; // must be 08 00 00 00, = header size after this field\r
-    uint32_t mHeaderSig; // must be CF CF 0F 00\r
-    uint32_t mSection; // must be 01 00 00 00\r
-};\r
-\r
-struct PSectionHeader {\r
-    uint32_t mHeaderSize; // must be 0C 00 00 00\r
-    uint32_t mHeaderSig; // must be CF FF 00 00\r
-    uint32_t mSection; // 00 00 00 00 means end\r
-    uint32_t mDataSize;\r
-};\r
-\r
-struct PSec2ElemHeader {\r
-    uint32_t mHeaderSize; // must be 0C 00 00 00\r
-    uint32_t mHeaderSig; // must be F1 FE FE 0F\r
-    uint32_t mElementType; // 1000003, 1000005 or 1000014\r
-    uint32_t mDataSize;\r
-};\r
-\r
-struct PSec2ElemType3a { //static object ?\r
-    float mPosY; //= uint32_t16_t PosY - 32000\r
-    float mPosZ;\r
-    float mPosX;\r
-    float mRotY;\r
-    float mRotZ;\r
-    float mRotX;\r
-    float mScale; //00 00 80 3F ? = float(1.000000) !!! => scale factor ?????\r
-    uint32_t mUnknown2; //01 00 00 00 ?\r
-    uint16_t mModelID; // point32_ts to models.ini\r
-    uint32_t mUnknown3; //00 00 00 00 ?\r
-    uint32_t mUnknown4; //00 00 00 00 ?\r
-    uint16_t mWorldmodelID; // point32_ts to worldmodel.def\r
-    uint16_t mUnknown5; //12 00 ?\r
-    uint32_t mObjectID;\r
-};\r
-\r
-struct PSec2ElemType3b { //this part is optional\r
-    float mBoxLowerY; //Bounding box, for useflag "64 - selfconstructing colisionbox"\r
-    float mBoxLowerZ; // int32_t32_t or uint32_t32_t ?\r
-    float mBoxLowerX;\r
-    float mBoxUpperY;\r
-    float mBoxUpperZ;\r
-    float mBoxUpperX;\r
-};\r
-\r
-struct PSec2ElemType5Start { //door\r
-    uint16_t mUnknown1; //18 00\r
-    uint16_t mUnknown1bis; //00 00 ? varies\r
-    float mPosY;\r
-    float mPosZ;\r
-    float mPosX;\r
-    uint8_t mActorStringSize; //string size with ending 0\r
-    uint8_t mParamStringSize; //string size with ending 0\r
-    uint16_t mUnknown5; //00 00 ? second byte varies\r
-    uint16_t mDoorID; // but what is the link with ObjectID sent in Use message (can't find the base offset .. or 0x80 for doors ???)\r
-    uint16_t mWorldmodelID; //door type from worldmodel.def\r
-};\r
-//Actor As String //null terminated string\r
-//Params As String //null terminated string - for DDOOR, 2nd param is the ID of the other (half)door (*)\r
-//param1 = 2 => simple lateral move ?, 3 => door frontal+lateral move (as at Typherra memorial) ?\r
-//last param = 0/1 for lateral move direction ? no ...\r
-//(*) here is the bug(?) that makes open only one half of a double door\r
-\r
-/*\r
-struct PSec2ElemType6Start //npc\r
-{\r
-  uint16_t mUnknown1; //20 00 ?\r
-  uint16_t mUnknown2; //12 00 ?\r
-  float mPosY;\r
-  float mPosZ;\r
-  float mPosX;\r
-  uint32_t mNPCTypeID; //npc type in npc.def\r
-  uint8_t mActorStringSize; //string size with ending 0\r
-  uint8_t mParamStringSize; //string size with ending 0\r
-  uint16_t mNpcID; // kind of ?\r
-  uint32_t mUnknown3; //01 00 00 00 ?\r
-  uint16_t mUnknown4; //00 00 ?\r
-  uint16_t mUnknown5; //04 00 ?\r
-};\r
-  //Actor As String //null terminated string\r
-  //Params As String //null terminated string - Seem to be the facing angle in degres\r
-struct PSec2ElemType6End\r
-{\r
-  float mPosY2; //second position for movement ?\r
-  float mPosZ2; //\r
-  float mPosX2; //\r
-};\r
-*/\r
-struct PSec2NPC_EntryPart1 {\r
-    uint32_t       mUnknown1; // Is always 0x20001200, in every log. maybe header for NPCs?\r
-    float       mPosY;\r
-    float       mPosZ;\r
-    float       mPosX;\r
-    uint32_t       mNPCTypeID; //npc type in npc.def\r
-    uint8_t        mActorStringSize; //string size with ending 0\r
-    uint8_t        mAngleStringSize; //string size with ending 0\r
-    uint16_t       mNpcID;\r
-    uint8_t        mHasAdditionalCoords;\r
-    uint8_t        mUnknown2a;\r
-    uint8_t        mUnknown2b;\r
-    uint8_t        mUnknown2c;\r
-    uint16_t       mTradeID; //mUnknown3; //00 00 ?\r
-    uint16_t       mUnknown4; //04 00 ?\r
-};\r
-\r
-//    uint32_t8_t    mActorName[mActorStringSize];\r
-//    uint32_t8_t    mAngle[mAngleStringSize];\r
-\r
-struct PSec2NPC_EntryPart2 { // Waypoint32_ts! or something like that...\r
-    float       mPosY;\r
-    float       mPosZ;\r
-    float       mPosX;\r
-};\r
-\r
-//  uint32_t16_t mStrSize; //non-zero terminated string size\r
-//  Name As String //non-zero terminated string\r
-struct PSec2ElemType15End { //area definition/sound ?\r
-    float mUnknown1;\r
-    float mUnknown2;\r
-    float mUnknown3;\r
-    float mUnknown4;\r
-    float mUnknown5;\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+struct PWorldFileHeader {
+    uint32_t mHeaderSize; // must be 08 00 00 00, = header size after this field
+    uint32_t mHeaderSig; // must be CF CF 0F 00
+    uint32_t mSection; // must be 01 00 00 00
+};
+
+struct PSectionHeader {
+    uint32_t mHeaderSize; // must be 0C 00 00 00
+    uint32_t mHeaderSig; // must be CF FF 00 00
+    uint32_t mSection; // 00 00 00 00 means end
+    uint32_t mDataSize;
+};
+
+struct PSec2ElemHeader {
+    uint32_t mHeaderSize; // must be 0C 00 00 00
+    uint32_t mHeaderSig; // must be F1 FE FE 0F
+    uint32_t mElementType; // 1000003, 1000005 or 1000014
+    uint32_t mDataSize;
+};
+
+struct PSec2ElemType3a { //static object ?
+    float mPosY; //= uint32_t16_t PosY - 32000
+    float mPosZ;
+    float mPosX;
+    float mRotY;
+    float mRotZ;
+    float mRotX;
+    float mScale; //00 00 80 3F ? = float(1.000000) !!! => scale factor ?????
+    uint32_t mUnknown2; //01 00 00 00 ?
+    uint16_t mModelID; // point32_ts to models.ini
+    uint32_t mUnknown3; //00 00 00 00 ?
+    uint32_t mUnknown4; //00 00 00 00 ?
+    uint16_t mWorldmodelID; // point32_ts to worldmodel.def
+    uint16_t mUnknown5; //12 00 ?
+    uint32_t mObjectID;
+};
+
+struct PSec2ElemType3b { //this part is optional
+    float mBoxLowerY; //Bounding box, for useflag "64 - selfconstructing colisionbox"
+    float mBoxLowerZ; // int32_t32_t or uint32_t32_t ?
+    float mBoxLowerX;
+    float mBoxUpperY;
+    float mBoxUpperZ;
+    float mBoxUpperX;
+};
+
+struct PSec2ElemType5Start { //door
+    uint16_t mUnknown1; //18 00
+    uint16_t mUnknown1bis; //00 00 ? varies
+    float mPosY;
+    float mPosZ;
+    float mPosX;
+    uint8_t mActorStringSize; //string size with ending 0
+    uint8_t mParamStringSize; //string size with ending 0
+    uint16_t mUnknown5; //00 00 ? second byte varies
+    uint16_t mDoorID; // but what is the link with ObjectID sent in Use message (can't find the base offset .. or 0x80 for doors ???)
+    uint16_t mWorldmodelID; //door type from worldmodel.def
+};
+//Actor As String //null terminated string
+//Params As String //null terminated string - for DDOOR, 2nd param is the ID of the other (half)door (*)
+//param1 = 2 => simple lateral move ?, 3 => door frontal+lateral move (as at Typherra memorial) ?
+//last param = 0/1 for lateral move direction ? no ...
+//(*) here is the bug(?) that makes open only one half of a double door
+
+/*
+struct PSec2ElemType6Start //npc
+{
+  uint16_t mUnknown1; //20 00 ?
+  uint16_t mUnknown2; //12 00 ?
+  float mPosY;
+  float mPosZ;
+  float mPosX;
+  uint32_t mNPCTypeID; //npc type in npc.def
+  uint8_t mActorStringSize; //string size with ending 0
+  uint8_t mParamStringSize; //string size with ending 0
+  uint16_t mNpcID; // kind of ?
+  uint32_t mUnknown3; //01 00 00 00 ?
+  uint16_t mUnknown4; //00 00 ?
+  uint16_t mUnknown5; //04 00 ?
+};
+  //Actor As String //null terminated string
+  //Params As String //null terminated string - Seem to be the facing angle in degres
+struct PSec2ElemType6End
+{
+  float mPosY2; //second position for movement ?
+  float mPosZ2; //
+  float mPosX2; //
+};
+*/
+struct PSec2NPC_EntryPart1 {
+    uint32_t       mUnknown1; // Is always 0x20001200, in every log. maybe header for NPCs?
+    float       mPosY;
+    float       mPosZ;
+    float       mPosX;
+    uint32_t       mNPCTypeID; //npc type in npc.def
+    uint8_t        mActorStringSize; //string size with ending 0
+    uint8_t        mAngleStringSize; //string size with ending 0
+    uint16_t       mNpcID;
+    uint8_t        mHasAdditionalCoords;
+    uint8_t        mUnknown2a;
+    uint8_t        mUnknown2b;
+    uint8_t        mUnknown2c;
+    uint16_t       mTradeID; //mUnknown3; //00 00 ?
+    uint16_t       mUnknown4; //04 00 ?
+};
+
+//    uint32_t8_t    mActorName[mActorStringSize];
+//    uint32_t8_t    mAngle[mAngleStringSize];
+
+struct PSec2NPC_EntryPart2 { // Waypoint32_ts! or something like that...
+    float       mPosY;
+    float       mPosZ;
+    float       mPosX;
+};
+
+//  uint32_t16_t mStrSize; //non-zero terminated string size
+//  Name As String //non-zero terminated string
+struct PSec2ElemType15End { //area definition/sound ?
+    float mUnknown1;
+    float mUnknown2;
+    float mUnknown3;
+    float mUnknown4;
+    float mUnknown5;
+};
index 66e1762..18bb141 100644 (file)
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "GameServer/Includes.hxx"\r
-\r
-/*\r
-    NOTA: Some entries in worlds.ini share the same Id ...\r
-          e.g: 505: techtown_enter 1/1a/1b/2\r
-          As we don't know what it means & how it is supposed to be handled,\r
-          we keep the first one for the moment. (this is managed in gamedef.cpp)\r
-    TODO: Add a config entry to select the Nth entry for each such case,\r
-          as well as a config entry to select the default entry to be kept (first/last)\r
-*/\r
-\r
-PDefWorldFile::PDefWorldFile()\r
-{\r
-    mFileInWorldsDir = false;\r
-}\r
-\r
-bool PDefWorldFile::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    int StartPos = 0;\r
-    int TailLen = 0;\r
-    int Len;\r
-\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0: // setentry\r
-                continue;\r
-\r
-            case 1: // index\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2: // name\r
-            {\r
-              Len = (*i).length();\r
-\r
-        while((StartPos = (*i).find("\\",StartPos))>-1)\r
-          (*i)[StartPos]='/';\r
-        StartPos = 0;\r
-\r
-        if ((*i)[0] == '\"')\r
-          StartPos = 1;\r
-\r
-              if ( (*i).substr(StartPos,9) == "./worlds/" )\r
-              {\r
-                mFileInWorldsDir = true;\r
-                StartPos += 9;\r
-              }\r
-              else if ( (*i).substr(StartPos,2) == "./" )\r
-          StartPos += 2;\r
-\r
-        if ((*i)[Len-1] == '\"')\r
-          TailLen = 1;\r
-              if ( (Len > (StartPos+TailLen+4)) && ((*i)[Len-TailLen-4] == '.') )\r
-                TailLen += 4;\r
-\r
-              mName = (*i).substr(StartPos,Len-StartPos-TailLen); // remove prefix, extension and doublequotes\r
-\r
-                break;\r
-            }\r
-        }\r
-    }\r
-\r
-    return (Idx == 3);\r
-}\r
-\r
-// class PDefWorldFileMap defined in gamedefs.h\r
-bool PDefWorldFilesMap::Load(const char* nName, const char* nFilename)\r
-{\r
-  mName = nName;\r
-  if(mName.empty())\r
-  {\r
-    Console->Print( "%s Defs name not defined", Console->ColorText( RED, BLACK, "[ERROR]" ) );\r
-    return (false);\r
-  }\r
-\r
-  if(! *nFilename)\r
-  {\r
-    Console->Print( "%s Filename not defined for %s defs", Console->ColorText( RED, BLACK, "[ERROR]" ), mName.c_str() );\r
-    return (false);\r
-  }\r
-\r
-  PDefParser parser;\r
-  int nDefs = 0, nErrors = 0, nDup = 0;\r
-\r
-  if ( parser.Parse( nFilename ) )\r
-  {\r
-    const PDefTokenList &t = parser.GetTokens();\r
-\r
-    for ( PDefTokenList::const_iterator i = t.begin(); i != t.end(); i++ )\r
-    {\r
-      PDefWorldFile *it = new PDefWorldFile();\r
-      bool loadfail = !it->LoadFromDef( *i ), insertfail = false;\r
-\r
-      if ( !loadfail )\r
-        insertfail = !mDefs.insert( std::make_pair( it->GetIndex(), it ) ).second;\r
-      if ( loadfail || insertfail )\r
-      {\r
-        if ( insertfail )\r
-        {\r
-          ++nDup;\r
-          if ( gDevDebug ) Console->Print( "%s ini error (new duplicate id %i discarded)", mName.c_str(), it->GetIndex(), it->GetName().c_str() );\r
-        }\r
-        else\r
-        {\r
-          Console->Print( "%s ini load error @ %i", mName.c_str(), nDefs + nErrors );\r
-          ++nErrors;\r
-        }\r
-        delete it;\r
-      }\r
-      else\r
-        ++nDefs;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Console->Print( "%s Error loading %s ini defs", Console->ColorText( RED, BLACK, "[ERROR]" ), mName.c_str() );\r
-    return ( false );\r
-  }\r
-\r
-  if ( nErrors > 0 )\r
-    Console->Print( "%s Loaded %i %s ini defs, %i error(s).", Console->ColorText( RED, BLACK, "[ERROR]" ), nDefs, mName.c_str(), nErrors );\r
-  else\r
-    Console->Print( "%s Loaded %i %s ini defs, %i error(s).", Console->ColorText( GREEN, BLACK, "[Success]" ), nDefs, mName.c_str(), nErrors );\r
-\r
-  if ( nDup )\r
-    Console->Print( "%s %d duplicate entries ignored in %s ini defs.", Console->ColorText( YELLOW, BLACK, "[Notice]" ), nDup, mName.c_str() );\r
-\r
-  return ( true );\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+#include "GameServer/Includes.hxx"
+
+/*
+    NOTA: Some entries in worlds.ini share the same Id ...
+          e.g: 505: techtown_enter 1/1a/1b/2
+          As we don't know what it means & how it is supposed to be handled,
+          we keep the first one for the moment. (this is managed in gamedef.cpp)
+    TODO: Add a config entry to select the Nth entry for each such case,
+          as well as a config entry to select the default entry to be kept (first/last)
+*/
+
+PDefWorldFile::PDefWorldFile()
+{
+    mFileInWorldsDir = false;
+}
+
+bool PDefWorldFile::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    int StartPos = 0;
+    int TailLen = 0;
+    int Len;
+
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0: // setentry
+                continue;
+
+            case 1: // index
+                mIndex = atoi(i->c_str()); break;
+
+            case 2: // name
+            {
+              Len = (*i).length();
+
+        while((StartPos = (*i).find("\\",StartPos))>-1)
+          (*i)[StartPos]='/';
+        StartPos = 0;
+
+        if ((*i)[0] == '\"')
+          StartPos = 1;
+
+              if ( (*i).substr(StartPos,9) == "./worlds/" )
+              {
+                mFileInWorldsDir = true;
+                StartPos += 9;
+              }
+              else if ( (*i).substr(StartPos,2) == "./" )
+          StartPos += 2;
+
+        if ((*i)[Len-1] == '\"')
+          TailLen = 1;
+              if ( (Len > (StartPos+TailLen+4)) && ((*i)[Len-TailLen-4] == '.') )
+                TailLen += 4;
+
+              mName = (*i).substr(StartPos,Len-StartPos-TailLen); // remove prefix, extension and doublequotes
+
+                break;
+            }
+        }
+    }
+
+    return (Idx == 3);
+}
+
+// class PDefWorldFileMap defined in gamedefs.h
+bool PDefWorldFilesMap::Load(const char* nName, const char* nFilename)
+{
+  mName = nName;
+  if(mName.empty())
+  {
+    Console->Print( "%s Defs name not defined", Console->ColorText( RED, BLACK, "[ERROR]" ) );
+    return (false);
+  }
+
+  if(! *nFilename)
+  {
+    Console->Print( "%s Filename not defined for %s defs", Console->ColorText( RED, BLACK, "[ERROR]" ), mName.c_str() );
+    return (false);
+  }
+
+  PDefParser parser;
+  int nDefs = 0, nErrors = 0, nDup = 0;
+
+  if ( parser.Parse( nFilename ) )
+  {
+    const PDefTokenList &t = parser.GetTokens();
+
+    for ( PDefTokenList::const_iterator i = t.begin(); i != t.end(); i++ )
+    {
+      PDefWorldFile *it = new PDefWorldFile();
+      bool loadfail = !it->LoadFromDef( *i ), insertfail = false;
+
+      if ( !loadfail )
+        insertfail = !mDefs.insert( std::make_pair( it->GetIndex(), it ) ).second;
+      if ( loadfail || insertfail )
+      {
+        if ( insertfail )
+        {
+          ++nDup;
+          if ( gDevDebug ) Console->Print( "%s ini error (new duplicate id %i discarded)", mName.c_str(), it->GetIndex(), it->GetName().c_str() );
+        }
+        else
+        {
+          Console->Print( "%s ini load error @ %i", mName.c_str(), nDefs + nErrors );
+          ++nErrors;
+        }
+        delete it;
+      }
+      else
+        ++nDefs;
+    }
+  }
+  else
+  {
+    Console->Print( "%s Error loading %s ini defs", Console->ColorText( RED, BLACK, "[ERROR]" ), mName.c_str() );
+    return ( false );
+  }
+
+  if ( nErrors > 0 )
+    Console->Print( "%s Loaded %i %s ini defs, %i error(s).", Console->ColorText( RED, BLACK, "[ERROR]" ), nDefs, mName.c_str(), nErrors );
+  else
+    Console->Print( "%s Loaded %i %s ini defs, %i error(s).", Console->ColorText( GREEN, BLACK, "[Success]" ), nDefs, mName.c_str(), nErrors );
+
+  if ( nDup )
+    Console->Print( "%s %d duplicate entries ignored in %s ini defs.", Console->ColorText( YELLOW, BLACK, "[Notice]" ), nDup, mName.c_str() );
+
+  return ( true );
+}
index ea2c788..4c05954 100644 (file)
@@ -1,30 +1,30 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefWorldFile : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName; // dat filename with ending extension and starting ./ or ./worlds/ REMOVED\r
-    bool mFileInWorldsDir; // TRUE if worlds/ must be appendend before mName to get real file name (dat file at least)\r
-\r
-public:\r
-    PDefWorldFile();\r
-    //~PDefWorldFile();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline const std::string GetBasicFileName() const { return (mFileInWorldsDir ? (std::string("worlds/") + mName) : mName); };\r
-};\r
-\r
-\r
-class PDefWorldFilesMap : public PDefMap<PDefWorldFile> {\r
-public:\r
-    bool Load(const char* nName, const char* nFilename);\r
-    inline std::map<int32_t, PDefWorldFile*>::const_iterator ConstIteratorBegin() const { return mDefs.begin(); }\r
-    inline std::map<int32_t, PDefWorldFile*>::const_iterator ConstIteratorEnd() const { return mDefs.end(); }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefWorldFile : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName; // dat filename with ending extension and starting ./ or ./worlds/ REMOVED
+    bool mFileInWorldsDir; // TRUE if worlds/ must be appendend before mName to get real file name (dat file at least)
+
+public:
+    PDefWorldFile();
+    //~PDefWorldFile();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline const std::string GetBasicFileName() const { return (mFileInWorldsDir ? (std::string("worlds/") + mName) : mName); };
+};
+
+
+class PDefWorldFilesMap : public PDefMap<PDefWorldFile> {
+public:
+    bool Load(const char* nName, const char* nFilename);
+    inline std::map<int32_t, PDefWorldFile*>::const_iterator ConstIteratorBegin() const { return mDefs.begin(); }
+    inline std::map<int32_t, PDefWorldFile*>::const_iterator ConstIteratorEnd() const { return mDefs.end(); }
+};
index 68a3c7f..15aeb72 100644 (file)
@@ -1,41 +1,41 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefWorldModel::PDefWorldModel()\r
-{\r
-}\r
-\r
-bool PDefWorldModel::LoadFromDef(PTokenList *Tokens)\r
-{\r
-    int Idx=0;\r
-    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)\r
-    {\r
-        switch(Idx)\r
-        {\r
-            case 0: // setentry\r
-                    continue;\r
-\r
-            case 1: // index\r
-                mIndex = atoi(i->c_str()); break;\r
-\r
-            case 2: // name\r
-                mName = *i; break;\r
-\r
-            case 3: // use flag\r
-                mUseFlags = atoi(i->c_str()); break;\r
-\r
-            case 4: // function type\r
-                mFunctionType = atoi(i->c_str()); break;\r
-\r
-            case 5: // function value\r
-                mFunctionValue = atoi(i->c_str()); break;\r
-\r
-            case 6: // hack difficulty\r
-                mHackDifficulty = atoi(i->c_str()); break;\r
-\r
-            case 7: // hack penalty\r
-                mHackPenalty = atoi(i->c_str()); break;\r
-        }\r
-    }\r
-\r
-    return true;\r
-}\r
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefWorldModel::PDefWorldModel()
+{
+}
+
+bool PDefWorldModel::LoadFromDef(PTokenList *Tokens)
+{
+    int Idx=0;
+    for(PTokenList::iterator i=Tokens->begin(); i!=Tokens->end(); i++, Idx++)
+    {
+        switch(Idx)
+        {
+            case 0: // setentry
+                    continue;
+
+            case 1: // index
+                mIndex = atoi(i->c_str()); break;
+
+            case 2: // name
+                mName = *i; break;
+
+            case 3: // use flag
+                mUseFlags = atoi(i->c_str()); break;
+
+            case 4: // function type
+                mFunctionType = atoi(i->c_str()); break;
+
+            case 5: // function value
+                mFunctionValue = atoi(i->c_str()); break;
+
+            case 6: // hack difficulty
+                mHackDifficulty = atoi(i->c_str()); break;
+
+            case 7: // hack penalty
+                mHackPenalty = atoi(i->c_str()); break;
+        }
+    }
+
+    return true;
+}
index 11cb111..2b500e8 100644 (file)
@@ -1,30 +1,30 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefWorldModel : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    int32_t mUseFlags;\r
-    int32_t mFunctionType;\r
-    int32_t mFunctionValue;\r
-    int32_t mHackDifficulty;\r
-    int32_t mHackPenalty;\r
-\r
-public:\r
-    PDefWorldModel();\r
-    //~PDefWorldModel();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline int32_t GetID() const { return mIndex; }\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline int32_t GetUseFlags() const { return mUseFlags; }\r
-    inline int32_t GetFunctionType() const { return mFunctionType; }\r
-    inline int32_t GetFunctionValue() const { return mFunctionValue; }\r
-    inline int32_t GetHackDifficulty() const { return mHackDifficulty; }\r
-    inline int32_t GetHackPenalty() const { return mHackPenalty; }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefWorldModel : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName;
+    int32_t mUseFlags;
+    int32_t mFunctionType;
+    int32_t mFunctionValue;
+    int32_t mHackDifficulty;
+    int32_t mHackPenalty;
+
+public:
+    PDefWorldModel();
+    //~PDefWorldModel();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline int32_t GetID() const { return mIndex; }
+    inline const std::string &GetName() const { return mName; }
+    inline int32_t GetUseFlags() const { return mUseFlags; }
+    inline int32_t GetFunctionType() const { return mFunctionType; }
+    inline int32_t GetFunctionValue() const { return mFunctionValue; }
+    inline int32_t GetHackDifficulty() const { return mHackDifficulty; }
+    inline int32_t GetHackPenalty() const { return mHackPenalty; }
+};
index fdb13eb..84c3342 100644 (file)
@@ -1,88 +1,88 @@
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PDefWorld::PDefWorld()\r
-{\r
-}\r
-\r
-bool PDefWorld::LoadFromDef( PTokenList *Tokens )\r
-{\r
-  int Idx = 0;\r
-  int StartPos = 0;\r
-  int TailLen = 0;\r
-  int Len;\r
-\r
-  for ( PTokenList::iterator i = Tokens->begin(); i != Tokens->end(); i++, Idx++ )\r
-  {\r
-    switch ( Idx )\r
-    {\r
-      case 0: // setentry\r
-        continue;\r
-      case 3: // music\r
-        continue;\r
-\r
-      case 1: // index\r
-        mIndex = atoi( i->c_str() ); break;\r
-\r
-      case 2: // name\r
-      {\r
-        Len = ( *i ).length();\r
-\r
-        if (( *i )[0] == '\"' )\r
-          StartPos = 1;\r
-\r
-        while (( *i )[StartPos] == ' ' )\r
-          ++StartPos;\r
-\r
-        if (( *i )[Len-1] == '\"' )\r
-          TailLen = 1;\r
-\r
-        while (( Len - TailLen > 0 ) && (( *i )[Len-TailLen-1] == ' ' ) )\r
-          ++TailLen;\r
-\r
-        if ( StartPos >= Len - TailLen )\r
-          mName = "";\r
-        else\r
-          mName = ( *i ).substr( StartPos, Len - StartPos - TailLen );\r
-\r
-        break;\r
-      }\r
-\r
-      case 4: // datfile\r
-      {\r
-        Len = ( *i ).length();\r
-\r
-        while (( StartPos = ( *i ).find( "\\", StartPos ) ) > -1 )\r
-          ( *i )[StartPos] = '/';\r
-        StartPos = 0;\r
-\r
-        if (( *i )[0] == '\"' )\r
-          StartPos = 1;\r
-\r
-        while (( *i )[StartPos] == ' ' )\r
-          ++StartPos;\r
-\r
-        if (( StartPos <= Len - 2 ) && (( *i ).substr( StartPos, 2 ) == "./" ) )\r
-          StartPos += 2;\r
-\r
-        if (( *i )[Len-1] == '\"' )\r
-          TailLen = 1;\r
-\r
-        while (( Len - TailLen > 0 ) && (( *i )[Len-TailLen-1] == ' ' ) )\r
-          ++TailLen;\r
-\r
-        if ( StartPos >= Len - TailLen )\r
-          mDatFile = "";\r
-        else\r
-          mDatFile = ( *i ).substr( StartPos, Len - StartPos - TailLen );\r
-\r
-        break;\r
-      }\r
-\r
-      case 5:\r
-        mFlags = atoi( i->c_str() ); break;\r
-    }\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
+#include "GameServer/Definitions/Includes.hxx"
+
+PDefWorld::PDefWorld()
+{
+}
+
+bool PDefWorld::LoadFromDef( PTokenList *Tokens )
+{
+  int Idx = 0;
+  int StartPos = 0;
+  int TailLen = 0;
+  int Len;
+
+  for ( PTokenList::iterator i = Tokens->begin(); i != Tokens->end(); i++, Idx++ )
+  {
+    switch ( Idx )
+    {
+      case 0: // setentry
+        continue;
+      case 3: // music
+        continue;
+
+      case 1: // index
+        mIndex = atoi( i->c_str() ); break;
+
+      case 2: // name
+      {
+        Len = ( *i ).length();
+
+        if (( *i )[0] == '\"' )
+          StartPos = 1;
+
+        while (( *i )[StartPos] == ' ' )
+          ++StartPos;
+
+        if (( *i )[Len-1] == '\"' )
+          TailLen = 1;
+
+        while (( Len - TailLen > 0 ) && (( *i )[Len-TailLen-1] == ' ' ) )
+          ++TailLen;
+
+        if ( StartPos >= Len - TailLen )
+          mName = "";
+        else
+          mName = ( *i ).substr( StartPos, Len - StartPos - TailLen );
+
+        break;
+      }
+
+      case 4: // datfile
+      {
+        Len = ( *i ).length();
+
+        while (( StartPos = ( *i ).find( "\\", StartPos ) ) > -1 )
+          ( *i )[StartPos] = '/';
+        StartPos = 0;
+
+        if (( *i )[0] == '\"' )
+          StartPos = 1;
+
+        while (( *i )[StartPos] == ' ' )
+          ++StartPos;
+
+        if (( StartPos <= Len - 2 ) && (( *i ).substr( StartPos, 2 ) == "./" ) )
+          StartPos += 2;
+
+        if (( *i )[Len-1] == '\"' )
+          TailLen = 1;
+
+        while (( Len - TailLen > 0 ) && (( *i )[Len-TailLen-1] == ' ' ) )
+          ++TailLen;
+
+        if ( StartPos >= Len - TailLen )
+          mDatFile = "";
+        else
+          mDatFile = ( *i ).substr( StartPos, Len - StartPos - TailLen );
+
+        break;
+      }
+
+      case 5:
+        mFlags = atoi( i->c_str() ); break;
+    }
+  }
+
+  return true;
+}
+
index 9129479..3d4eff3 100644 (file)
@@ -1,23 +1,23 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-#include "GameServer/Definitions/Definition.hxx"\r
-\r
-class PDefWorld : public PDef {\r
-private:\r
-    //int32_t mIndex;\r
-    std::string mName;\r
-    std::string mDatFile;\r
-    int32_t mFlags;\r
-\r
-public:\r
-    PDefWorld();\r
-    //~PDefWorld();\r
-\r
-    bool LoadFromDef(PTokenList *Tokens);\r
-\r
-    inline const std::string &GetName() const { return mName; }\r
-    inline const std::string &GetDatFile() const { return mDatFile; }\r
-    inline int32_t GetFlags() const { return mFlags; }\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include "GameServer/Definitions/Definition.hxx"
+
+class PDefWorld : public PDef {
+private:
+    //int32_t mIndex;
+    std::string mName;
+    std::string mDatFile;
+    int32_t mFlags;
+
+public:
+    PDefWorld();
+    //~PDefWorld();
+
+    bool LoadFromDef(PTokenList *Tokens);
+
+    inline const std::string &GetName() const { return mName; }
+    inline const std::string &GetDatFile() const { return mDatFile; }
+    inline int32_t GetFlags() const { return mFlags; }
+};
index 94aa485..43685e7 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-//  TODO: - mem corruption occurs if mDoorParameters[] is given a size of 6, and that 6 max param can be accepted\r
-//          This bug occurs in world 105. Reason not found yet :-x\r
-\r
-const std::string EmptyString;\r
-\r
-PDoorTemplate::PDoorTemplate()\r
-{\r
-  mDoorID = 0;\r
-  mWorldmodelID = 0;\r
-  mDefWorldModel = NULL;\r
-  mIsDoubleDoor = false;\r
-  mIsTriggeredDoor = false;\r
-}\r
-\r
-PDoorTemplate::~PDoorTemplate()\r
-{\r
-}\r
-\r
-uint16_t PDoorTemplate::GetID()\r
-{\r
-    return mDoorID;\r
-}\r
-\r
-uint16_t PDoorTemplate::GetUseFlags()\r
-{\r
-    return (mDefWorldModel ? mDefWorldModel->GetUseFlags() : 0);\r
-}\r
-\r
-uint16_t PDoorTemplate::GetFunctionType()\r
-{\r
-    return (mDefWorldModel ? mDefWorldModel->GetFunctionType() : 0);\r
-}\r
-\r
-int PDoorTemplate::GetFunctionValue()\r
-{\r
-    return (mDefWorldModel ?  mDefWorldModel->GetFunctionValue() : 0);\r
-}\r
-\r
-const std::string& PDoorTemplate::GetName() const\r
-{\r
-    return (mDefWorldModel ?  mDefWorldModel->GetName() : EmptyString );\r
-}\r
-\r
-const PDefWorldModel *PDoorTemplate::GetDefWorldModel() const\r
-{\r
-    return mDefWorldModel;\r
-}\r
-\r
-void PDoorTemplate::GetPos(float *nPosX, float *nPosY, float *nPosZ) const\r
-{\r
-    *nPosY = mPosY;\r
-    *nPosZ = mPosZ;\r
-    *nPosX = mPosX;\r
-}\r
-\r
-uint16_t PDoorTemplate::GetOtherDoorID()\r
-{\r
-    return (mIsDoubleDoor ? mDoorParameters[1] : 0);\r
-}\r
-\r
-bool PDoorTemplate::IsDoubleDoor() const\r
-{\r
-    return mIsDoubleDoor;\r
-}\r
-\r
-bool PDoorTemplate::IsTriggeredDoor() const\r
-{\r
-    return mIsTriggeredDoor;\r
-}\r
-\r
-void PDoorTemplate::SetDoorParameters(char* nDoorParametersString)\r
-{\r
-  char* SepPos;\r
-  int ParamNum = 0;\r
-//Console->Print("door parameter: %s", nDoorParametersString);\r
-  while ( *nDoorParametersString && (SepPos = strchr(nDoorParametersString, ',')) && (ParamNum < 4))\r
-  {\r
-    *SepPos = 0;\r
-    mDoorParameters[ParamNum++] = atoi(nDoorParametersString);\r
-    nDoorParametersString = SepPos + 1;\r
-  }\r
-  if (*nDoorParametersString)\r
-  {\r
-    if (ParamNum < 4)\r
-      mDoorParameters[ParamNum] = atoi(nDoorParametersString);\r
-    //else\r
-    //  Console->Print(RED, BLACK, "[ERROR] More than 4 parameters in Sec2ElemType5 ParamString");\r
-  }\r
-}\r
-\r
-void PDoorTemplate::SetDoorTypeName(char* nDoorTypeName)\r
-{\r
-  mDoorTypeName = nDoorTypeName;\r
-\r
-  if (mDoorTypeName == "DDOOR")\r
-  {\r
-    mIsDoubleDoor = true;\r
-  }\r
-  else if (mDoorTypeName == "TRIGDD")\r
-  {\r
-    mIsDoubleDoor = true;\r
-    mIsTriggeredDoor = true;\r
-  }\r
-  else if (mDoorTypeName == "TRIGDOOR")\r
-  {\r
-    mIsTriggeredDoor = true;\r
-  }\r
-  else if (mDoorTypeName == "NBUTTON")\r
-  {\r
-    mIsTriggeredDoor = false;\r
-  }\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+
+//  TODO: - mem corruption occurs if mDoorParameters[] is given a size of 6, and that 6 max param can be accepted
+//          This bug occurs in world 105. Reason not found yet :-x
+
+const std::string EmptyString;
+
+PDoorTemplate::PDoorTemplate()
+{
+  mDoorID = 0;
+  mWorldmodelID = 0;
+  mDefWorldModel = NULL;
+  mIsDoubleDoor = false;
+  mIsTriggeredDoor = false;
+}
+
+PDoorTemplate::~PDoorTemplate()
+{
+}
+
+uint16_t PDoorTemplate::GetID()
+{
+    return mDoorID;
+}
+
+uint16_t PDoorTemplate::GetUseFlags()
+{
+    return (mDefWorldModel ? mDefWorldModel->GetUseFlags() : 0);
+}
+
+uint16_t PDoorTemplate::GetFunctionType()
+{
+    return (mDefWorldModel ? mDefWorldModel->GetFunctionType() : 0);
+}
+
+int PDoorTemplate::GetFunctionValue()
+{
+    return (mDefWorldModel ?  mDefWorldModel->GetFunctionValue() : 0);
+}
+
+const std::string& PDoorTemplate::GetName() const
+{
+    return (mDefWorldModel ?  mDefWorldModel->GetName() : EmptyString );
+}
+
+const PDefWorldModel *PDoorTemplate::GetDefWorldModel() const
+{
+    return mDefWorldModel;
+}
+
+void PDoorTemplate::GetPos(float *nPosX, float *nPosY, float *nPosZ) const
+{
+    *nPosY = mPosY;
+    *nPosZ = mPosZ;
+    *nPosX = mPosX;
+}
+
+uint16_t PDoorTemplate::GetOtherDoorID()
+{
+    return (mIsDoubleDoor ? mDoorParameters[1] : 0);
+}
+
+bool PDoorTemplate::IsDoubleDoor() const
+{
+    return mIsDoubleDoor;
+}
+
+bool PDoorTemplate::IsTriggeredDoor() const
+{
+    return mIsTriggeredDoor;
+}
+
+void PDoorTemplate::SetDoorParameters(char* nDoorParametersString)
+{
+  char* SepPos;
+  int ParamNum = 0;
+//Console->Print("door parameter: %s", nDoorParametersString);
+  while ( *nDoorParametersString && (SepPos = strchr(nDoorParametersString, ',')) && (ParamNum < 4))
+  {
+    *SepPos = 0;
+    mDoorParameters[ParamNum++] = atoi(nDoorParametersString);
+    nDoorParametersString = SepPos + 1;
+  }
+  if (*nDoorParametersString)
+  {
+    if (ParamNum < 4)
+      mDoorParameters[ParamNum] = atoi(nDoorParametersString);
+    //else
+    //  Console->Print(RED, BLACK, "[ERROR] More than 4 parameters in Sec2ElemType5 ParamString");
+  }
+}
+
+void PDoorTemplate::SetDoorTypeName(char* nDoorTypeName)
+{
+  mDoorTypeName = nDoorTypeName;
+
+  if (mDoorTypeName == "DDOOR")
+  {
+    mIsDoubleDoor = true;
+  }
+  else if (mDoorTypeName == "TRIGDD")
+  {
+    mIsDoubleDoor = true;
+    mIsTriggeredDoor = true;
+  }
+  else if (mDoorTypeName == "TRIGDOOR")
+  {
+    mIsTriggeredDoor = true;
+  }
+  else if (mDoorTypeName == "NBUTTON")
+  {
+    mIsTriggeredDoor = false;
+  }
+}
index e3bbd84..c406471 100644 (file)
@@ -1,47 +1,47 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class PDefWorldModel;\r
-\r
-class PDoorTemplate {\r
-    friend class PWorldDatParser;\r
-\r
-private:\r
-    uint16_t mDoorID;\r
-\r
-    // The commented out values are not loaded from dat file atm because they are not used yet.\r
-    //uint16_t mUnknown1; //18 00\r
-    //uint16_t mUnknown1bis; //00 00 ? varies\r
-    float mPosY;\r
-    float mPosZ;\r
-    float mPosX;\r
-    //uint16_t mUnknown5; //00 00 ? second byte varies\r
-    uint16_t mWorldmodelID; //door type from worldmodel.def\r
-\r
-    std::string mDoorTypeName;\r
-    int mDoorParameters[4];\r
-    bool mIsDoubleDoor;\r
-    bool mIsTriggeredDoor;\r
-\r
-    const PDefWorldModel* mDefWorldModel;\r
-\r
-public:\r
-    PDoorTemplate();\r
-    ~PDoorTemplate();\r
-\r
-    uint16_t GetID();\r
-    uint16_t GetUseFlags();\r
-    uint16_t GetFunctionType();\r
-    int GetFunctionValue();\r
-    const std::string& GetName() const; /// !!!!\r
-    const PDefWorldModel *GetDefWorldModel() const;\r
-\r
-    void GetPos(float *nPosX, float *nPosY, float *nPosZ) const;\r
-    uint16_t GetOtherDoorID();\r
-    bool IsDoubleDoor() const;\r
-    bool IsTriggeredDoor() const;\r
-\r
-    void SetDoorTypeName(char* nDoorTypeName);\r
-    void SetDoorParameters(char* nDoorParametersString);\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+class PDefWorldModel;
+
+class PDoorTemplate {
+    friend class PWorldDatParser;
+
+private:
+    uint16_t mDoorID;
+
+    // The commented out values are not loaded from dat file atm because they are not used yet.
+    //uint16_t mUnknown1; //18 00
+    //uint16_t mUnknown1bis; //00 00 ? varies
+    float mPosY;
+    float mPosZ;
+    float mPosX;
+    //uint16_t mUnknown5; //00 00 ? second byte varies
+    uint16_t mWorldmodelID; //door type from worldmodel.def
+
+    std::string mDoorTypeName;
+    int mDoorParameters[4];
+    bool mIsDoubleDoor;
+    bool mIsTriggeredDoor;
+
+    const PDefWorldModel* mDefWorldModel;
+
+public:
+    PDoorTemplate();
+    ~PDoorTemplate();
+
+    uint16_t GetID();
+    uint16_t GetUseFlags();
+    uint16_t GetFunctionType();
+    int GetFunctionValue();
+    const std::string& GetName() const; /// !!!!
+    const PDefWorldModel *GetDefWorldModel() const;
+
+    void GetPos(float *nPosX, float *nPosY, float *nPosZ) const;
+    uint16_t GetOtherDoorID();
+    bool IsDoubleDoor() const;
+    bool IsTriggeredDoor() const;
+
+    void SetDoorTypeName(char* nDoorTypeName);
+    void SetDoorParameters(char* nDoorParametersString);
+};
index bc29b37..3d1e974 100644 (file)
@@ -1,76 +1,76 @@
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-const std::string EmptyString;\r
-\r
-PFurnitureItemTemplate::PFurnitureItemTemplate()\r
-{\r
-  mObjectID = 0;\r
-  mModelID = 0;\r
-  mWorldmodelID = 0;\r
-  mDefWorldModel = NULL;\r
-  mLinkedObjectID = 0;\r
-}\r
-\r
-PFurnitureItemTemplate::~PFurnitureItemTemplate()\r
-{\r
-}\r
-\r
-uint32_t PFurnitureItemTemplate::GetID() const\r
-{\r
-    return mObjectID;\r
-}\r
-\r
-uint16_t PFurnitureItemTemplate::GetUseFlags() const\r
-{\r
-    return (mDefWorldModel ? mDefWorldModel->GetUseFlags() : 0);\r
-}\r
-\r
-uint16_t PFurnitureItemTemplate::GetFunctionType() const\r
-{\r
-    return (mDefWorldModel ? mDefWorldModel->GetFunctionType() : 0);\r
-}\r
-\r
-int PFurnitureItemTemplate::GetFunctionValue() const\r
-{\r
-    return (mDefWorldModel ? mDefWorldModel->GetFunctionValue() : 0);\r
-}\r
-\r
-const std::string &PFurnitureItemTemplate::GetName() const\r
-{\r
-    return (mDefWorldModel ? mDefWorldModel->GetName() : EmptyString);\r
-}\r
-\r
-const PDefWorldModel *PFurnitureItemTemplate::GetDefWorldModel() const\r
-{\r
-    return mDefWorldModel;\r
-}\r
-\r
-uint8_t PFurnitureItemTemplate::GetFrontLR() const\r
-{\r
-    return mFrontLR;\r
-}\r
-\r
-void PFurnitureItemTemplate::GetFrontPos(uint16_t *nFrontPosX, uint16_t *nFrontPosY, uint16_t *nFrontPosZ) const\r
-{\r
-    *nFrontPosY = mFrontPosY;\r
-    *nFrontPosZ = mFrontPosZ;\r
-    *nFrontPosX = mFrontPosX;\r
-}\r
-\r
-void PFurnitureItemTemplate::GetPos(float *nPosX, float *nPosY, float *nPosZ) const\r
-{\r
-    *nPosY = mPosY;\r
-    *nPosZ = mPosZ;\r
-    *nPosX = mPosX;\r
-}\r
-\r
-void PFurnitureItemTemplate::SetLinkedObjectID(uint32_t nID)\r
-{\r
-    mLinkedObjectID = nID;\r
-}\r
-\r
-uint32_t PFurnitureItemTemplate::GetLinkedObjectID() const\r
-{\r
-    return mLinkedObjectID;\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+
+const std::string EmptyString;
+
+PFurnitureItemTemplate::PFurnitureItemTemplate()
+{
+  mObjectID = 0;
+  mModelID = 0;
+  mWorldmodelID = 0;
+  mDefWorldModel = NULL;
+  mLinkedObjectID = 0;
+}
+
+PFurnitureItemTemplate::~PFurnitureItemTemplate()
+{
+}
+
+uint32_t PFurnitureItemTemplate::GetID() const
+{
+    return mObjectID;
+}
+
+uint16_t PFurnitureItemTemplate::GetUseFlags() const
+{
+    return (mDefWorldModel ? mDefWorldModel->GetUseFlags() : 0);
+}
+
+uint16_t PFurnitureItemTemplate::GetFunctionType() const
+{
+    return (mDefWorldModel ? mDefWorldModel->GetFunctionType() : 0);
+}
+
+int PFurnitureItemTemplate::GetFunctionValue() const
+{
+    return (mDefWorldModel ? mDefWorldModel->GetFunctionValue() : 0);
+}
+
+const std::string &PFurnitureItemTemplate::GetName() const
+{
+    return (mDefWorldModel ? mDefWorldModel->GetName() : EmptyString);
+}
+
+const PDefWorldModel *PFurnitureItemTemplate::GetDefWorldModel() const
+{
+    return mDefWorldModel;
+}
+
+uint8_t PFurnitureItemTemplate::GetFrontLR() const
+{
+    return mFrontLR;
+}
+
+void PFurnitureItemTemplate::GetFrontPos(uint16_t *nFrontPosX, uint16_t *nFrontPosY, uint16_t *nFrontPosZ) const
+{
+    *nFrontPosY = mFrontPosY;
+    *nFrontPosZ = mFrontPosZ;
+    *nFrontPosX = mFrontPosX;
+}
+
+void PFurnitureItemTemplate::GetPos(float *nPosX, float *nPosY, float *nPosZ) const
+{
+    *nPosY = mPosY;
+    *nPosZ = mPosZ;
+    *nPosX = mPosX;
+}
+
+void PFurnitureItemTemplate::SetLinkedObjectID(uint32_t nID)
+{
+    mLinkedObjectID = nID;
+}
+
+uint32_t PFurnitureItemTemplate::GetLinkedObjectID() const
+{
+    return mLinkedObjectID;
+}
index 1e1abbb..35b3429 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-\r
-class PDefWorldModel;\r
-\r
-enum { // Furniture Use flags (cumlative)\r
-  ufTouchable = 1,\r
-  ufUsable = 2,\r
-  ufNoCollision = 4,\r
-  ufChair = 8,\r
-  ufToolTarget = 16,\r
-  ufSelfCollisionBox = 64,\r
-  ufGraphicalEffect = 128,\r
-  ufNoSelectionBox = 256\r
-};\r
-\r
-class PFurnitureItemTemplate {\r
-    friend class PWorldDatParser;\r
-\r
-private:\r
-    uint32_t mObjectID;\r
-\r
-    // The commented out values are not loaded from dat file atm because they are not used yet.\r
-    float mPosY; //= mPosY from dat file + 32000, to be coherent with char Pos scale\r
-    float mPosZ;\r
-    float mPosX;\r
-    //float mRotY;\r
-    float mRotZ;\r
-    //float mRotX;\r
-    //uint32_t mScale; //00 00 80 3F ?  = float(1.0000) scale factor ? // mostly used by holoscreens (passiv object)\r
-    //uint32_t mUnknown2; //01 00 00 00 ?\r
-    uint16_t mModelID; // points to models.ini\r
-    //uint32_t mUnknown3; //00 00 00 00 ?\r
-    //uint32_t mUnknown4; //00 00 00 00 ?\r
-    uint16_t mWorldmodelID; // points to worldmodel.def\r
-    //uint16_t mUnknown5; //12 00 ? // changes sometime (ex: c288 ...)\r
-\r
-    //float mBoxLowerY; //Bounding box, for use when ufSelfCollisionBox is set in mUseFlags.\r
-    //float mBoxLowerZ;\r
-    //float mBoxLowerX;\r
-    //float mBoxUpperY;\r
-    //float mBoxUpperZ;\r
-    //float mBoxUpperX;\r
-\r
-    uint16_t mFrontPosY;\r
-    uint16_t mFrontPosZ;\r
-    uint16_t mFrontPosX;\r
-    uint8_t mFrontLR;\r
-\r
-    const PDefWorldModel* mDefWorldModel;\r
-\r
-    uint32_t mLinkedObjectID; // for buttons, stores the corresponding triggered door\r
-    // fo GR, stores order of the GR entity (spawn point) to later choose from respawn.def data\r
-\r
-  public:\r
-    PFurnitureItemTemplate();\r
-    ~PFurnitureItemTemplate();\r
-\r
-    uint32_t GetID() const;\r
-    uint16_t GetUseFlags() const;\r
-    uint16_t GetFunctionType() const;\r
-    int GetFunctionValue() const;\r
-    const std::string &GetName() const; /// !!!!\r
-    const PDefWorldModel *GetDefWorldModel() const;\r
-    uint8_t GetFrontLR() const;\r
-    void GetFrontPos(uint16_t *nFrontPosX, uint16_t *nFrontPosY, uint16_t *nFrontPosZ) const;\r
-    void GetPos(float *nPosX, float *nPosY, float *nPosZ) const;\r
-\r
-    void SetLinkedObjectID(uint32_t nID);\r
-    uint32_t GetLinkedObjectID() const;\r
-};\r
-\r
-// *** from worldmodel.def ***\r
-\r
-//function Type\r
-// 0 - none\r
-//  1 - Itemcontainer\r
-// 2 - Terminal\r
-// 3 - Outfitter\r
-// 4 - Trader\r
-// 5 - Mineral\r
-// 6 - Respawn Station\r
-// 7 - GoGuardian\r
-// 8 - Hackterminal\r
-// 9 - Appartement Eingang\r
-// 10 - Appartement Ein/Ausgang\r
-// 11 - Appartement Klingel/�ffner\r
-// 12 - Standard Button\r
-// 13 - Hack Button\r
-// 14 - HOLOMATCH ENTRANCE\r
-// 15 - HOLOMATCH EXIT\r
-// 16 - HOLOMATCH REFRESH\r
-// 17 - HOLOMATCH HEAL\r
-// 18 - WORLDCHANGEACTOR\r
-// 19 - CLANTERMINAL\r
-// 20 - DATFILE WORLDCHANGE ACTOR\r
-// 21 - LOCATION FOR 20\r
-// 22 -\r
-// 23 - EINTRITTSGELD BUTTON\r
-// 24- TUTORIALEXIT\r
-// 25 - EXPLOSIVE\r
-// 26 - Outpost Switch\r
-// 27 - Old goguardian\r
-// 28 - Fahrzeug Depot Interface\r
-// 29 - Underground Exit\r
-// 30 - Static FX (Value=Type. 1=Fire 2=Smoke 3=Steam 4=Sparkle)\r
-// 31 - Venture Warp Station\r
-// 32 - functionvalue+100 gibt eine Meldung aus der Text.ini [MISC] an.\r
-//\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+class PDefWorldModel;
+
+enum { // Furniture Use flags (cumlative)
+  ufTouchable = 1,
+  ufUsable = 2,
+  ufNoCollision = 4,
+  ufChair = 8,
+  ufToolTarget = 16,
+  ufSelfCollisionBox = 64,
+  ufGraphicalEffect = 128,
+  ufNoSelectionBox = 256
+};
+
+class PFurnitureItemTemplate {
+    friend class PWorldDatParser;
+
+private:
+    uint32_t mObjectID;
+
+    // The commented out values are not loaded from dat file atm because they are not used yet.
+    float mPosY; //= mPosY from dat file + 32000, to be coherent with char Pos scale
+    float mPosZ;
+    float mPosX;
+    //float mRotY;
+    float mRotZ;
+    //float mRotX;
+    //uint32_t mScale; //00 00 80 3F ?  = float(1.0000) scale factor ? // mostly used by holoscreens (passiv object)
+    //uint32_t mUnknown2; //01 00 00 00 ?
+    uint16_t mModelID; // points to models.ini
+    //uint32_t mUnknown3; //00 00 00 00 ?
+    //uint32_t mUnknown4; //00 00 00 00 ?
+    uint16_t mWorldmodelID; // points to worldmodel.def
+    //uint16_t mUnknown5; //12 00 ? // changes sometime (ex: c288 ...)
+
+    //float mBoxLowerY; //Bounding box, for use when ufSelfCollisionBox is set in mUseFlags.
+    //float mBoxLowerZ;
+    //float mBoxLowerX;
+    //float mBoxUpperY;
+    //float mBoxUpperZ;
+    //float mBoxUpperX;
+
+    uint16_t mFrontPosY;
+    uint16_t mFrontPosZ;
+    uint16_t mFrontPosX;
+    uint8_t mFrontLR;
+
+    const PDefWorldModel* mDefWorldModel;
+
+    uint32_t mLinkedObjectID; // for buttons, stores the corresponding triggered door
+    // fo GR, stores order of the GR entity (spawn point) to later choose from respawn.def data
+
+  public:
+    PFurnitureItemTemplate();
+    ~PFurnitureItemTemplate();
+
+    uint32_t GetID() const;
+    uint16_t GetUseFlags() const;
+    uint16_t GetFunctionType() const;
+    int GetFunctionValue() const;
+    const std::string &GetName() const; /// !!!!
+    const PDefWorldModel *GetDefWorldModel() const;
+    uint8_t GetFrontLR() const;
+    void GetFrontPos(uint16_t *nFrontPosX, uint16_t *nFrontPosY, uint16_t *nFrontPosZ) const;
+    void GetPos(float *nPosX, float *nPosY, float *nPosZ) const;
+
+    void SetLinkedObjectID(uint32_t nID);
+    uint32_t GetLinkedObjectID() const;
+};
+
+// *** from worldmodel.def ***
+
+//function Type
+// 0 - none
+//  1 - Itemcontainer
+// 2 - Terminal
+// 3 - Outfitter
+// 4 - Trader
+// 5 - Mineral
+// 6 - Respawn Station
+// 7 - GoGuardian
+// 8 - Hackterminal
+// 9 - Appartement Eingang
+// 10 - Appartement Ein/Ausgang
+// 11 - Appartement Klingel/�ffner
+// 12 - Standard Button
+// 13 - Hack Button
+// 14 - HOLOMATCH ENTRANCE
+// 15 - HOLOMATCH EXIT
+// 16 - HOLOMATCH REFRESH
+// 17 - HOLOMATCH HEAL
+// 18 - WORLDCHANGEACTOR
+// 19 - CLANTERMINAL
+// 20 - DATFILE WORLDCHANGE ACTOR
+// 21 - LOCATION FOR 20
+// 22 -
+// 23 - EINTRITTSGELD BUTTON
+// 24- TUTORIALEXIT
+// 25 - EXPLOSIVE
+// 26 - Outpost Switch
+// 27 - Old goguardian
+// 28 - Fahrzeug Depot Interface
+// 29 - Underground Exit
+// 30 - Static FX (Value=Type. 1=Fire 2=Smoke 3=Steam 4=Sparkle)
+// 31 - Venture Warp Station
+// 32 - functionvalue+100 gibt eine Meldung aus der Text.ini [MISC] an.
+//
index 235aa0e..05296d6 100644 (file)
@@ -1,94 +1,94 @@
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdban()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 2)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@ban <charID or nickname> <xS(econds)>/<xM(inutes)>/<xH(ours)>/<xD(ays)>");\r
-        return;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == true)\r
-    {\r
-        target = GetClientByID(GetArgInt(1));\r
-    }\r
-    else\r
-    {\r
-        char tmp_destNick[50];\r
-        GetArgText(1, tmp_destNick, 50);\r
-        target = GetClientByNick(tmp_destNick);\r
-    }\r
-\r
-    if(target == nullptr) // If victim isnt found, return error\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "No such player");\r
-        return;\r
-    }\r
-    if(source->GetAccountLevel() <= target->GetAccountLevel())\r
-    {\r
-        char tmpMsg[200];\r
-        snprintf(tmpMsg, 199, "Cant ban %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-        tmpMsg[199] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-        return;\r
-    }\r
-    char tmpTimeVal[10];\r
-    GetArgText(2, tmpTimeVal, 10);\r
-\r
-    int32_t loop_i = 0;\r
-    char tmp_atoi[10];\r
-\r
-    while(isdigit(tmpTimeVal[loop_i]) != 0 && loop_i < 10)\r
-    {\r
-        tmp_atoi[loop_i] = tmpTimeVal[loop_i];\r
-        loop_i++;\r
-    }\r
-    char timefactor[1];\r
-    timefactor[0] = tmpTimeVal[loop_i];\r
-    int32_t timevalue = atoi(tmp_atoi);\r
-    int32_t time_to_ban = 0;\r
-\r
-    if(strcasecmp(timefactor, "s") == 0 )\r
-    {\r
-        time_to_ban = timevalue;\r
-    }\r
-    else if(strcasecmp(timefactor, "m") == 0 )\r
-    {\r
-        time_to_ban = timevalue * 60;\r
-    }\r
-    else if(strcasecmp(timefactor, "h") == 0 )\r
-    {\r
-        time_to_ban = timevalue * 60 * 60;\r
-    }\r
-    else if(strcasecmp(timefactor, "d") == 0 )\r
-    {\r
-        time_to_ban = timevalue * 60 * 60 * 24;\r
-    }\r
-    else\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@ban <charID or nickname> <xS(econds)>/<xM(inutes)>/<xH(ours)>/<xD(ays)>");\r
-        return;\r
-    }\r
-\r
-    int32_t final_bantime = std::time(nullptr) + time_to_ban;\r
-    PAccount Acc(target->GetAccountID());\r
-    Acc.SetBannedUntilTime(final_bantime);\r
-    Acc.Save();\r
-\r
-    target->InitCharVanish();\r
-\r
-    GameServer->ClientDisconnected(target);  // Now kick the player (Hes banned :) )\r
-\r
-    char tmpMsg_success[81];\r
-    snprintf(tmpMsg_success, 80, "Successfully banned %s", target->GetChar()->GetName().c_str());\r
-    tmpMsg_success[80] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpMsg_success);\r
-    return;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdban()
+{
+    bool SyntaxError = false;
+    if(ArgC < 2)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@ban <charID or nickname> <xS(econds)>/<xM(inutes)>/<xH(ours)>/<xD(ays)>");
+        return;
+    }
+
+    if(IsArgNumeric(1) == true)
+    {
+        target = GetClientByID(GetArgInt(1));
+    }
+    else
+    {
+        char tmp_destNick[50];
+        GetArgText(1, tmp_destNick, 50);
+        target = GetClientByNick(tmp_destNick);
+    }
+
+    if(target == nullptr) // If victim isnt found, return error
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "No such player");
+        return;
+    }
+    if(source->GetAccountLevel() <= target->GetAccountLevel())
+    {
+        char tmpMsg[200];
+        snprintf(tmpMsg, 199, "Cant ban %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());
+        tmpMsg[199] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+        return;
+    }
+    char tmpTimeVal[10];
+    GetArgText(2, tmpTimeVal, 10);
+
+    int32_t loop_i = 0;
+    char tmp_atoi[10];
+
+    while(isdigit(tmpTimeVal[loop_i]) != 0 && loop_i < 10)
+    {
+        tmp_atoi[loop_i] = tmpTimeVal[loop_i];
+        loop_i++;
+    }
+    char timefactor[1];
+    timefactor[0] = tmpTimeVal[loop_i];
+    int32_t timevalue = atoi(tmp_atoi);
+    int32_t time_to_ban = 0;
+
+    if(strcasecmp(timefactor, "s") == 0 )
+    {
+        time_to_ban = timevalue;
+    }
+    else if(strcasecmp(timefactor, "m") == 0 )
+    {
+        time_to_ban = timevalue * 60;
+    }
+    else if(strcasecmp(timefactor, "h") == 0 )
+    {
+        time_to_ban = timevalue * 60 * 60;
+    }
+    else if(strcasecmp(timefactor, "d") == 0 )
+    {
+        time_to_ban = timevalue * 60 * 60 * 24;
+    }
+    else
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@ban <charID or nickname> <xS(econds)>/<xM(inutes)>/<xH(ours)>/<xD(ays)>");
+        return;
+    }
+
+    int32_t final_bantime = std::time(nullptr) + time_to_ban;
+    PAccount Acc(target->GetAccountID());
+    Acc.SetBannedUntilTime(final_bantime);
+    Acc.Save();
+
+    target->InitCharVanish();
+
+    GameServer->ClientDisconnected(target);  // Now kick the player (Hes banned :) )
+
+    char tmpMsg_success[81];
+    snprintf(tmpMsg_success, 80, "Successfully banned %s", target->GetChar()->GetName().c_str());
+    tmpMsg_success[80] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", tmpMsg_success);
+    return;
+}
index e285b30..0d3084f 100644 (file)
@@ -1,43 +1,43 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdbrightness()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@brightness -|<head brightness: 0..255> [-|<torso brightness>]  [-|<legs brightness>]");\r
-        return;\r
-    }\r
-\r
-    char tmp_v1[30];\r
-    char tmp_v2[30];\r
-    char tmp_v3[30];\r
-\r
-    GetArgText(1, tmp_v1, 30);\r
-    GetArgText(2, tmp_v2, 30);\r
-    GetArgText(3, tmp_v3, 30);\r
-\r
-    uint8_t val1, val2, val3, val4, val5, val6;\r
-    char effStr[128];\r
-    PMessage* tmpMsg;\r
-\r
-    source->GetChar()->GetCurrentBodyColor(val1, val2, val3, val4, val5, val6);\r
-    if(tmp_v1[0] != '-')\r
-    val4 = (uint8_t)(atoi(tmp_v1) & 0xff);\r
-    if((tmp_v2[0] != '-') && (tmp_v2[0] != '\0'))\r
-    val5 = (uint8_t)(atoi(tmp_v2) & 0xff);\r
-    if((tmp_v3[0] != '-') && (tmp_v3[0] != '\0'))\r
-    val6 = (uint8_t)(atoi(tmp_v3) & 0xff);\r
-    source->GetChar()->SetCurrentBodyColor(val1, val2, val3, val4, val5, val6);\r
-\r
-    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-    ClientManager->UDPBroadcast(tmpMsg, source);\r
-    snprintf(effStr, 127, "Body brightness set to values %d %d %d", val4, val5, val6);\r
-    effStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", effStr);\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdbrightness()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@brightness -|<head brightness: 0..255> [-|<torso brightness>]  [-|<legs brightness>]");
+        return;
+    }
+
+    char tmp_v1[30];
+    char tmp_v2[30];
+    char tmp_v3[30];
+
+    GetArgText(1, tmp_v1, 30);
+    GetArgText(2, tmp_v2, 30);
+    GetArgText(3, tmp_v3, 30);
+
+    uint8_t val1, val2, val3, val4, val5, val6;
+    char effStr[128];
+    PMessage* tmpMsg;
+
+    source->GetChar()->GetCurrentBodyColor(val1, val2, val3, val4, val5, val6);
+    if(tmp_v1[0] != '-')
+    val4 = (uint8_t)(atoi(tmp_v1) & 0xff);
+    if((tmp_v2[0] != '-') && (tmp_v2[0] != '\0'))
+    val5 = (uint8_t)(atoi(tmp_v2) & 0xff);
+    if((tmp_v3[0] != '-') && (tmp_v3[0] != '\0'))
+    val6 = (uint8_t)(atoi(tmp_v3) & 0xff);
+    source->GetChar()->SetCurrentBodyColor(val1, val2, val3, val4, val5, val6);
+
+    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+    ClientManager->UDPBroadcast(tmpMsg, source);
+    snprintf(effStr, 127, "Body brightness set to values %d %d %d", val4, val5, val6);
+    effStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", effStr);
+}
index 2fcf278..556ee62 100644 (file)
@@ -1,13 +1,13 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmdbroadcast()\r
-{\r
-    if(DumbMade == false)\r
-    {\r
-        Console->Print("%s Missing packetdumb in PCommands::doCmdbroadcast for declared broadcast function!", Console->ColorText(RED, BLACK, "[PANIC]"));\r
-        return;\r
-    }\r
-\r
-    Chat->sendBroadcast(OrgPacketDumb+11);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmdbroadcast()
+{
+    if(DumbMade == false)
+    {
+        Console->Print("%s Missing packetdumb in PCommands::doCmdbroadcast for declared broadcast function!", Console->ColorText(RED, BLACK, "[PANIC]"));
+        return;
+    }
+
+    Chat->sendBroadcast(OrgPacketDumb+11);
+}
index f8bad49..d684782 100644 (file)
@@ -1,43 +1,43 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdcolor()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@color -|<head color: 0..255> [-|<torso color>]  [-|<legs color>]");\r
-        return;\r
-    }\r
-\r
-    char tmp_v1[30];\r
-    char tmp_v2[30];\r
-    char tmp_v3[30];\r
-\r
-    GetArgText(1, tmp_v1, 30);\r
-    GetArgText(2, tmp_v2, 30);\r
-    GetArgText(3, tmp_v3, 30);\r
-\r
-    uint8_t val1, val2, val3, val4, val5, val6;\r
-    char effStr[128];\r
-    PMessage* tmpMsg;\r
-\r
-    source->GetChar()->GetCurrentBodyColor(val1, val2, val3, val4, val5, val6);\r
-    if(tmp_v1[0] != '-')\r
-    val1 = (uint8_t)(atoi(tmp_v1) & 0xff);\r
-    if((tmp_v2[0] != '-') && (tmp_v2[0] != '\0'))\r
-    val2 = (uint8_t)(atoi(tmp_v2) & 0xff);\r
-    if((tmp_v3[0] != '-') && (tmp_v3[0] != '\0'))\r
-    val3 = (uint8_t)(atoi(tmp_v3) & 0xff);\r
-    source->GetChar()->SetCurrentBodyColor(val1, val2, val3, val4, val5, val6);\r
-\r
-    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-    ClientManager->UDPBroadcast(tmpMsg, source);\r
-    snprintf(effStr, 127, "Body color set to values %d %d %d", val1, val2, val3);\r
-    effStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", effStr);\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdcolor()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@color -|<head color: 0..255> [-|<torso color>]  [-|<legs color>]");
+        return;
+    }
+
+    char tmp_v1[30];
+    char tmp_v2[30];
+    char tmp_v3[30];
+
+    GetArgText(1, tmp_v1, 30);
+    GetArgText(2, tmp_v2, 30);
+    GetArgText(3, tmp_v3, 30);
+
+    uint8_t val1, val2, val3, val4, val5, val6;
+    char effStr[128];
+    PMessage* tmpMsg;
+
+    source->GetChar()->GetCurrentBodyColor(val1, val2, val3, val4, val5, val6);
+    if(tmp_v1[0] != '-')
+    val1 = (uint8_t)(atoi(tmp_v1) & 0xff);
+    if((tmp_v2[0] != '-') && (tmp_v2[0] != '\0'))
+    val2 = (uint8_t)(atoi(tmp_v2) & 0xff);
+    if((tmp_v3[0] != '-') && (tmp_v3[0] != '\0'))
+    val3 = (uint8_t)(atoi(tmp_v3) & 0xff);
+    source->GetChar()->SetCurrentBodyColor(val1, val2, val3, val4, val5, val6);
+
+    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+    ClientManager->UDPBroadcast(tmpMsg, source);
+    snprintf(effStr, 127, "Body color set to values %d %d %d", val1, val2, val3);
+    effStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", effStr);
+}
index 6b45f67..97dcb2a 100644 (file)
@@ -1,75 +1,75 @@
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmddebug()\r
-{\r
-    PDebugMode nWhat = DBG_ALL;\r
-    int nHow = -1;\r
-    const char* DbgTarget = "all";\r
-    char DbgMessage[80];\r
-    const char* Usage = "@debug [loc[ation] | it[emid] | sub[way]] [0|1]";\r
-\r
-    if(ArgC > 0)\r
-    {\r
-      if(IsArgNumeric(1) == true)\r
-      {\r
-          if(GetArgInt(1) == 0)\r
-          {\r
-              nHow = 0;\r
-          }\r
-          else\r
-          {\r
-              nHow = 1;\r
-          }\r
-      }\r
-      else\r
-      {\r
-          char tmp[10];\r
-          if(GetArgText(1, tmp, 10))\r
-          {\r
-              if(strncmp(tmp, "loc", 3) == 0)\r
-              {\r
-                  nWhat = DBG_LOCATION;\r
-                  DbgTarget = "location";\r
-              }\r
-              else if(strncmp(tmp, "it", 2) == 0)\r
-              {\r
-                  nWhat = DBG_ITEMID;\r
-                  DbgTarget = "itemid";\r
-              }\r
-              else if(strncmp(tmp, "sub", 3) == 0)\r
-              {\r
-                  nWhat = DBG_SUBWAY;\r
-                  DbgTarget = "subway";\r
-              }\r
-          }\r
-      }\r
-\r
-      if (nWhat != DBG_ALL)\r
-      {\r
-          if(ArgC == 1)\r
-          {\r
-              nHow = (source->GetDebugMode(nWhat) ? 0 : 1); // toggle if no arg\r
-          }\r
-          else if(ArgC > 1 && GetArgInt(2) == 0)\r
-          {\r
-              nHow = 0;\r
-          }\r
-          else if(ArgC > 1 && GetArgInt(2) == 1)\r
-          {\r
-              nHow = 1;\r
-          }\r
-      }\r
-    }\r
-\r
-    if (nHow != -1)\r
-    {\r
-        source->SetDebugMode(nWhat, nHow);\r
-        snprintf(DbgMessage, 80, "Debug %s is now %s", DbgTarget, (nHow ? "ENABLED" : "DISABLED"));\r
-        Chat->send(source, CHAT_DIRECT, "System", DbgMessage);\r
-    }\r
-    else\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", Usage);\r
-    }\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmddebug()
+{
+    PDebugMode nWhat = DBG_ALL;
+    int nHow = -1;
+    const char* DbgTarget = "all";
+    char DbgMessage[80];
+    const char* Usage = "@debug [loc[ation] | it[emid] | sub[way]] [0|1]";
+
+    if(ArgC > 0)
+    {
+      if(IsArgNumeric(1) == true)
+      {
+          if(GetArgInt(1) == 0)
+          {
+              nHow = 0;
+          }
+          else
+          {
+              nHow = 1;
+          }
+      }
+      else
+      {
+          char tmp[10];
+          if(GetArgText(1, tmp, 10))
+          {
+              if(strncmp(tmp, "loc", 3) == 0)
+              {
+                  nWhat = DBG_LOCATION;
+                  DbgTarget = "location";
+              }
+              else if(strncmp(tmp, "it", 2) == 0)
+              {
+                  nWhat = DBG_ITEMID;
+                  DbgTarget = "itemid";
+              }
+              else if(strncmp(tmp, "sub", 3) == 0)
+              {
+                  nWhat = DBG_SUBWAY;
+                  DbgTarget = "subway";
+              }
+          }
+      }
+
+      if (nWhat != DBG_ALL)
+      {
+          if(ArgC == 1)
+          {
+              nHow = (source->GetDebugMode(nWhat) ? 0 : 1); // toggle if no arg
+          }
+          else if(ArgC > 1 && GetArgInt(2) == 0)
+          {
+              nHow = 0;
+          }
+          else if(ArgC > 1 && GetArgInt(2) == 1)
+          {
+              nHow = 1;
+          }
+      }
+    }
+
+    if (nHow != -1)
+    {
+        source->SetDebugMode(nWhat, nHow);
+        snprintf(DbgMessage, 80, "Debug %s is now %s", DbgTarget, (nHow ? "ENABLED" : "DISABLED"));
+        Chat->send(source, CHAT_DIRECT, "System", DbgMessage);
+    }
+    else
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", Usage);
+    }
+}
index 926b92d..ab8ff39 100644 (file)
@@ -1,36 +1,36 @@
-#include <cstdint>\r
-#include <cstdio>\r
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdeffect()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == false)\r
-        SyntaxError = true;\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@effect <effect: 0=none, 1 .. 17> [<density: 0=max .. 255=min>]");\r
-        return;\r
-    }\r
-\r
-    uint8_t val1, val2;\r
-    char effStr[128];\r
-    PMessage* tmpMsg;\r
-\r
-    val1 = (uint8_t)(GetArgInt(1) & 0xff);\r
-    val2 = (uint8_t)(GetArgInt(2) & 0xff);\r
-\r
-    source->GetChar()->SetBodyEffect(val1, val2);\r
-\r
-    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-    ClientManager->UDPBroadcast(tmpMsg, source);\r
-    snprintf(effStr, 127, "Body effect set to value %d with density %d (but you can see it yourself)", val1, val2);\r
-    effStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", effStr);\r
-}\r
+#include <cstdint>
+#include <cstdio>
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdeffect()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(IsArgNumeric(1) == false)
+        SyntaxError = true;
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@effect <effect: 0=none, 1 .. 17> [<density: 0=max .. 255=min>]");
+        return;
+    }
+
+    uint8_t val1, val2;
+    char effStr[128];
+    PMessage* tmpMsg;
+
+    val1 = (uint8_t)(GetArgInt(1) & 0xff);
+    val2 = (uint8_t)(GetArgInt(2) & 0xff);
+
+    source->GetChar()->SetBodyEffect(val1, val2);
+
+    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+    ClientManager->UDPBroadcast(tmpMsg, source);
+    snprintf(effStr, 127, "Body effect set to value %d with density %d (but you can see it yourself)", val1, val2);
+    effStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", effStr);
+}
index c39272e..53cbfa5 100644 (file)
@@ -1,55 +1,55 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmd_dev_h()\r
-{\r
-  if(IsAdmin() == false)\r
-    return;\r
-\r
-  if(source->GetAccountLevel() < PAL_ADMIN)\r
-    return;\r
-\r
-\r
-\r
-  PMessage* tmpMsg = MsgBuilder->BuildEntityPositionMsg(source, GetArgInt(1) & 0xffff, GetArgInt(2) & 0xffff, GetArgInt(3) & 0xffff);\r
-  source->SendUDPMessage(tmpMsg);\r
-/*\r
-  u8 val1, val2, val3, val4;\r
-  char tmpStr[128];\r
-\r
-  if(ArgC > 0)\r
-  {\r
-    val1 = (u8)(GetArgInt(1) & 0xff);\r
-    val2 = (u8)(GetArgInt(2) & 0xff);\r
-    val3 = (u8)(GetArgInt(3) & 0xff);\r
-    val4 = (ArgC > 3) ? (u8)(GetArgInt(4) & 0xff) : 0x01;\r
-  }\r
-  else\r
-  {\r
-    val1 = 0xff;\r
-    val2 = 0xff;\r
-    val3 = 0xff;\r
-    val4 = 0x01;\r
-  }\r
-\r
-    PMessage* tmpMsg = new PMessage(14);\r
-\r
-       *tmpMsg << (u8)0x13;\r
-       *tmpMsg << (u16)0x0000; //source->GetUDP_ID(); // just placeholder, must be set outside\r
-       *tmpMsg << (u16)0x0000;  // source->GetSessionID(); // just placeholder, must be set outside\r
-       *tmpMsg << (u8)0x00; // Message length placeholder;\r
-       *tmpMsg << (u8)0x1f;\r
-       *tmpMsg << (u16)source->GetLocalID();\r
-       *tmpMsg << (u8)0x30;\r
-       *tmpMsg << (u8)val1; //Head Heath (% ?) (45%)\r
-       *tmpMsg << (u8)val2; //Body Heath (35%)\r
-       *tmpMsg << (u8)val3; //Feet Heath (20%)\r
-       *tmpMsg << (u8)val4;\r
-\r
-    (*tmpMsg)[5] = (u8)(tmpMsg->GetSize() - 6);\r
-    ClientManager->UDPBroadcast(tmpMsg, source);\r
-\r
-    snprintf(tmpStr, 127, "Data set to values 0x%02x 0x%02x", val1, val2);\r
-    tmpStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpStr);\r
-    */\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmd_dev_h()
+{
+  if(IsAdmin() == false)
+    return;
+
+  if(source->GetAccountLevel() < PAL_ADMIN)
+    return;
+
+
+
+  PMessage* tmpMsg = MsgBuilder->BuildEntityPositionMsg(source, GetArgInt(1) & 0xffff, GetArgInt(2) & 0xffff, GetArgInt(3) & 0xffff);
+  source->SendUDPMessage(tmpMsg);
+/*
+  u8 val1, val2, val3, val4;
+  char tmpStr[128];
+
+  if(ArgC > 0)
+  {
+    val1 = (u8)(GetArgInt(1) & 0xff);
+    val2 = (u8)(GetArgInt(2) & 0xff);
+    val3 = (u8)(GetArgInt(3) & 0xff);
+    val4 = (ArgC > 3) ? (u8)(GetArgInt(4) & 0xff) : 0x01;
+  }
+  else
+  {
+    val1 = 0xff;
+    val2 = 0xff;
+    val3 = 0xff;
+    val4 = 0x01;
+  }
+
+    PMessage* tmpMsg = new PMessage(14);
+
+       *tmpMsg << (u8)0x13;
+       *tmpMsg << (u16)0x0000; //source->GetUDP_ID(); // just placeholder, must be set outside
+       *tmpMsg << (u16)0x0000;  // source->GetSessionID(); // just placeholder, must be set outside
+       *tmpMsg << (u8)0x00; // Message length placeholder;
+       *tmpMsg << (u8)0x1f;
+       *tmpMsg << (u16)source->GetLocalID();
+       *tmpMsg << (u8)0x30;
+       *tmpMsg << (u8)val1; //Head Heath (% ?) (45%)
+       *tmpMsg << (u8)val2; //Body Heath (35%)
+       *tmpMsg << (u8)val3; //Feet Heath (20%)
+       *tmpMsg << (u8)val4;
+
+    (*tmpMsg)[5] = (u8)(tmpMsg->GetSize() - 6);
+    ClientManager->UDPBroadcast(tmpMsg, source);
+
+    snprintf(tmpStr, 127, "Data set to values 0x%02x 0x%02x", val1, val2);
+    tmpStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", tmpStr);
+    */
+}
index c481ad7..92d023c 100644 (file)
@@ -1,97 +1,97 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdinfo()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@info <charID or nickname>");\r
-        return;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == true)\r
-    {\r
-        target = GetClientByID(GetArgInt(1));\r
-    }\r
-    else\r
-    {\r
-        char tmp_destNick[50];\r
-        GetArgText(1, tmp_destNick, 50);\r
-        target = GetClientByNick(tmp_destNick);\r
-    }\r
-\r
-    if(target == NULL) // If victim isnt found, return error\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "No such player");\r
-        return;\r
-    }\r
-    // *************** Checks done, proceed with command\r
-    /*\r
-        DIRECT> System: PlayerInformation\r
-        DIRECT> Info: CharID     : %d     // victim->GetCharID();\r
-        DIRECT> Info: AccountID  : %d     // victim->GetAccount()->GetID();\r
-        DIRECT> Info: LoginName  : %s     // victim->GetAccount()->GetName();\r
-        DIRECT> Info: AccessLevel: %d     // victim->GetAccountLevel();\r
-        DIRECT> Info: Current Loc: %d     // Chars->GetChar(source->GetCharID())->GetLocation();\r
-        DIRECT> Info: IP address : %s     // victim->GetAddress():\r
-\r
-        Maybe for future addons...\r
-        DIRECT> System: CharInformation\r
-        DIRECT> Info: Faction      : %d     // Chars->GetChar(source->GetCharID())->GetFaction();\r
-        DIRECT> Info: Cash         : %d     // Chars->GetChar(source->GetCharID())->GetCash();\r
-        DIRECT> Info: Soullight    : %d     // Chars->GetChar(source->GetCharID())->GetSoullight();\r
-    */\r
-\r
-    PAccount Acc(target->GetAccountID());\r
-\r
-    // If source != target\r
-    if(source->GetAccountID() != target->GetAccountID())\r
-    {\r
-        // Check if accesslevel is lower\r
-        if(source->GetAccountLevel() <= target->GetAccountLevel())\r
-        {\r
-            char tmpMsg[200];\r
-            snprintf(tmpMsg, 199, "Cant display info about %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-            tmpMsg[199] = '\0';\r
-            Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-            return;\r
-        }\r
-    }\r
-\r
-    char tmpInfo_head[151];\r
-    char tmpInfo_cID[151];\r
-    char tmpInfo_aID[151];\r
-    char tmpInfo_Login[151];\r
-    char tmpInfo_AxxLv[151];\r
-    char tmpInfo_Loc[151];\r
-    char tmpInfo_IP[151];\r
-\r
-    snprintf(tmpInfo_head, 150,     "PlayerInformation");\r
-    snprintf(tmpInfo_cID, 150,      "CharID     : %d",  target->GetCharID());\r
-    snprintf(tmpInfo_aID, 150,      "AccountID  : %d",  Acc.GetID());\r
-    snprintf(tmpInfo_Login, 150,    "LoginName  : %s",  Acc.GetName().c_str());\r
-    snprintf(tmpInfo_AxxLv, 150,    "AccessLevel: %d",  Acc.GetLevel());\r
-    snprintf(tmpInfo_Loc, 150,      "Current Loc: %d",  Chars->GetChar(target->GetCharID())->GetLocation());\r
-    snprintf(tmpInfo_IP, 150,       "IP address : %s",  target->GetAddress());\r
-\r
-    tmpInfo_head[150] = '\0';\r
-    tmpInfo_cID[150] = '\0';\r
-    tmpInfo_aID[150] = '\0';\r
-    tmpInfo_Login[150] = '\0';\r
-    tmpInfo_AxxLv[150] = '\0';\r
-    tmpInfo_Loc[150] = '\0';\r
-    tmpInfo_IP[150] = '\0';\r
-\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpInfo_head);\r
-    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_cID);\r
-    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_aID);\r
-    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_Login);\r
-    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_AxxLv);\r
-    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_Loc);\r
-    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_IP);\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdinfo()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@info <charID or nickname>");
+        return;
+    }
+
+    if(IsArgNumeric(1) == true)
+    {
+        target = GetClientByID(GetArgInt(1));
+    }
+    else
+    {
+        char tmp_destNick[50];
+        GetArgText(1, tmp_destNick, 50);
+        target = GetClientByNick(tmp_destNick);
+    }
+
+    if(target == NULL) // If victim isnt found, return error
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "No such player");
+        return;
+    }
+    // *************** Checks done, proceed with command
+    /*
+        DIRECT> System: PlayerInformation
+        DIRECT> Info: CharID     : %d     // victim->GetCharID();
+        DIRECT> Info: AccountID  : %d     // victim->GetAccount()->GetID();
+        DIRECT> Info: LoginName  : %s     // victim->GetAccount()->GetName();
+        DIRECT> Info: AccessLevel: %d     // victim->GetAccountLevel();
+        DIRECT> Info: Current Loc: %d     // Chars->GetChar(source->GetCharID())->GetLocation();
+        DIRECT> Info: IP address : %s     // victim->GetAddress():
+
+        Maybe for future addons...
+        DIRECT> System: CharInformation
+        DIRECT> Info: Faction      : %d     // Chars->GetChar(source->GetCharID())->GetFaction();
+        DIRECT> Info: Cash         : %d     // Chars->GetChar(source->GetCharID())->GetCash();
+        DIRECT> Info: Soullight    : %d     // Chars->GetChar(source->GetCharID())->GetSoullight();
+    */
+
+    PAccount Acc(target->GetAccountID());
+
+    // If source != target
+    if(source->GetAccountID() != target->GetAccountID())
+    {
+        // Check if accesslevel is lower
+        if(source->GetAccountLevel() <= target->GetAccountLevel())
+        {
+            char tmpMsg[200];
+            snprintf(tmpMsg, 199, "Cant display info about %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());
+            tmpMsg[199] = '\0';
+            Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+            return;
+        }
+    }
+
+    char tmpInfo_head[151];
+    char tmpInfo_cID[151];
+    char tmpInfo_aID[151];
+    char tmpInfo_Login[151];
+    char tmpInfo_AxxLv[151];
+    char tmpInfo_Loc[151];
+    char tmpInfo_IP[151];
+
+    snprintf(tmpInfo_head, 150,     "PlayerInformation");
+    snprintf(tmpInfo_cID, 150,      "CharID     : %d",  target->GetCharID());
+    snprintf(tmpInfo_aID, 150,      "AccountID  : %d",  Acc.GetID());
+    snprintf(tmpInfo_Login, 150,    "LoginName  : %s",  Acc.GetName().c_str());
+    snprintf(tmpInfo_AxxLv, 150,    "AccessLevel: %d",  Acc.GetLevel());
+    snprintf(tmpInfo_Loc, 150,      "Current Loc: %d",  Chars->GetChar(target->GetCharID())->GetLocation());
+    snprintf(tmpInfo_IP, 150,       "IP address : %s",  target->GetAddress());
+
+    tmpInfo_head[150] = '\0';
+    tmpInfo_cID[150] = '\0';
+    tmpInfo_aID[150] = '\0';
+    tmpInfo_Login[150] = '\0';
+    tmpInfo_AxxLv[150] = '\0';
+    tmpInfo_Loc[150] = '\0';
+    tmpInfo_IP[150] = '\0';
+
+    Chat->send(source, CHAT_DIRECT, "System", tmpInfo_head);
+    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_cID);
+    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_aID);
+    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_Login);
+    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_AxxLv);
+    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_Loc);
+    Chat->send(source, CHAT_DIRECT, "Info", tmpInfo_IP);
+}
index ffa22d2..c4a6b00 100644 (file)
@@ -1,59 +1,59 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmdkick()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@kick <charID or nickname>");\r
-        return;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == true)\r
-    {\r
-        target = GetClientByID(GetArgInt(1));\r
-    }\r
-    else\r
-    {\r
-        char tmp_destNick[50];\r
-        GetArgText(1, tmp_destNick, 50);\r
-        target = GetClientByNick(tmp_destNick);\r
-    }\r
-\r
-    if(target == NULL) // If victim isnt found, return error\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "No such player");\r
-        return;\r
-    }\r
-\r
-    // Make sure only people with a higher level than victim can kick victim\r
-    if(source->GetAccountLevel() <= target->GetAccountLevel())\r
-    {\r
-        char tmpMsg[200];\r
-        snprintf(tmpMsg, 199, "Cant kick %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-        tmpMsg[199] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-        return;\r
-    }\r
-\r
-// *************** Checks done, proceed with command\r
-    int final_bantime = std::time(NULL) + 60;               // Ban 60 seconds (Anti-Rejoin)\r
-    PAccount Acc(target->GetAccountID());\r
-    Acc.SetBannedUntilTime(final_bantime);\r
-    Acc.Save();\r
-\r
-    target->InitCharVanish();\r
-    GameServer->ClientDisconnected(target);                 // Kick\r
-\r
-    Console->Print("%s %s (Lv %d) kicked %s (Lv %d)", Console->ColorText(YELLOW, BLACK, "[GameCommand]"), Chars->GetChar(source->GetCharID())->GetName().c_str(), source->GetAccountLevel(), Chars->GetChar(target->GetCharID())->GetName().c_str(), target->GetAccountLevel());\r
-    char successmsg[100];\r
-    snprintf(successmsg, 99, "Kicked %s", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-    successmsg[99] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", successmsg);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmdkick()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@kick <charID or nickname>");
+        return;
+    }
+
+    if(IsArgNumeric(1) == true)
+    {
+        target = GetClientByID(GetArgInt(1));
+    }
+    else
+    {
+        char tmp_destNick[50];
+        GetArgText(1, tmp_destNick, 50);
+        target = GetClientByNick(tmp_destNick);
+    }
+
+    if(target == NULL) // If victim isnt found, return error
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "No such player");
+        return;
+    }
+
+    // Make sure only people with a higher level than victim can kick victim
+    if(source->GetAccountLevel() <= target->GetAccountLevel())
+    {
+        char tmpMsg[200];
+        snprintf(tmpMsg, 199, "Cant kick %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());
+        tmpMsg[199] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+        return;
+    }
+
+// *************** Checks done, proceed with command
+    int final_bantime = std::time(NULL) + 60;               // Ban 60 seconds (Anti-Rejoin)
+    PAccount Acc(target->GetAccountID());
+    Acc.SetBannedUntilTime(final_bantime);
+    Acc.Save();
+
+    target->InitCharVanish();
+    GameServer->ClientDisconnected(target);                 // Kick
+
+    Console->Print("%s %s (Lv %d) kicked %s (Lv %d)", Console->ColorText(YELLOW, BLACK, "[GameCommand]"), Chars->GetChar(source->GetCharID())->GetName().c_str(), source->GetAccountLevel(), Chars->GetChar(target->GetCharID())->GetName().c_str(), target->GetAccountLevel());
+    char successmsg[100];
+    snprintf(successmsg, 99, "Kicked %s", Chars->GetChar(target->GetCharID())->GetName().c_str());
+    successmsg[99] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", successmsg);
+}
index 88c5fa5..8c9997b 100644 (file)
@@ -1,8 +1,8 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdlistbans()\r
-{\r
-    Chat->send(source, CHAT_DIRECT, "System", "Sorry, namikon was too lazy to code that ^^");\r
-    Chat->send(source, CHAT_DIRECT, "System", "Please wait until the ban is removed automaticly or edit your sqlDB");\r
-    return;\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdlistbans()
+{
+    Chat->send(source, CHAT_DIRECT, "System", "Sorry, namikon was too lazy to code that ^^");
+    Chat->send(source, CHAT_DIRECT, "System", "Please wait until the ban is removed automaticly or edit your sqlDB");
+    return;
+}
index 096d394..0b12031 100644 (file)
@@ -1,8 +1,8 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmdconlist()\r
-{\r
-    if (gDevDebug) Console->Print("IngameCommand: Sending connected-player-list to charID %d", source->GetCharID());\r
-    Chat->sendConnectedList(source, false);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmdconlist()
+{
+    if (gDevDebug) Console->Print("IngameCommand: Sending connected-player-list to charID %d", source->GetCharID());
+    Chat->sendConnectedList(source, false);
+}
index 0dab13a..d4d176f 100644 (file)
@@ -1,85 +1,85 @@
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmdrawf()\r
-{\r
-    bool SyntaxError = false;\r
-    bool DebugMode = false;\r
-    int Prot = 0;  // 0: Error 1: UDP 2: TCP\r
-\r
-    if(ArgC < 2)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    char file_to_send[50], protocol_to_use[10];\r
-    GetArgText(1, file_to_send, 50);\r
-    GetArgText(2, protocol_to_use, 10);\r
-\r
-    if(strcmp(protocol_to_use, "udp") == 0)\r
-    {\r
-        Prot = 1;\r
-    }\r
-    else if(strcmp(protocol_to_use, "tcp") == 0)\r
-    {\r
-        Prot = 2;\r
-    }\r
-    else if(strcmp(protocol_to_use, "debug") == 0)\r
-    {\r
-        DebugMode = true;\r
-    }\r
-    else\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@rawf <file> <udp/tcp/debug>");\r
-        return;\r
-    }\r
-\r
-    std::ifstream::pos_type size;\r
-    char *buffer;\r
-\r
-    std::ifstream hexdump (file_to_send, std::ios::in | std::ios::binary | std::ios::ate);\r
-    if (hexdump.is_open())\r
-    {\r
-        if (gDevDebug) Console->Print("IngameCommand: Sending packet file %s", file_to_send);\r
-\r
-        size = hexdump.tellg();\r
-        buffer = new char [size];\r
-        hexdump.seekg (0, std::ios::beg);\r
-\r
-        hexdump.read (buffer, size);\r
-        hexdump.close();\r
-        if(DebugMode == true)\r
-        {\r
-            int k;\r
-            Console->Print("Byte dump of %s:", file_to_send);\r
-            for(k=0;k<size;k++)\r
-            {\r
-                Console->Print("Byte %d: %#x", k, buffer[k]);\r
-            }\r
-        }\r
-        else\r
-        {\r
-            if(Prot == 1)\r
-                source->getUDPConn()->write(buffer, size);\r
-            else if(Prot == 2)\r
-                source->getTCPConn()->write(buffer, size);\r
-            else // Should never happen...\r
-                Console->Print("%s unable to determine protocol in PCommands::doCmdrawf", Console->ColorText(RED, BLACK, "[Error]"));\r
-        }\r
-\r
-        delete[] buffer;\r
-    }\r
-    else\r
-    {\r
-        char output[100];\r
-        Console->Print("IngameCommand: Unable to send file %s", file_to_send);\r
-        snprintf(output, 100, "File not found: %s", file_to_send);\r
-        Chat->send(source, CHAT_DIRECT, "System", output);\r
-    }\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmdrawf()
+{
+    bool SyntaxError = false;
+    bool DebugMode = false;
+    int Prot = 0;  // 0: Error 1: UDP 2: TCP
+
+    if(ArgC < 2)
+    {
+        SyntaxError = true;
+    }
+
+    char file_to_send[50], protocol_to_use[10];
+    GetArgText(1, file_to_send, 50);
+    GetArgText(2, protocol_to_use, 10);
+
+    if(strcmp(protocol_to_use, "udp") == 0)
+    {
+        Prot = 1;
+    }
+    else if(strcmp(protocol_to_use, "tcp") == 0)
+    {
+        Prot = 2;
+    }
+    else if(strcmp(protocol_to_use, "debug") == 0)
+    {
+        DebugMode = true;
+    }
+    else
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@rawf <file> <udp/tcp/debug>");
+        return;
+    }
+
+    std::ifstream::pos_type size;
+    char *buffer;
+
+    std::ifstream hexdump (file_to_send, std::ios::in | std::ios::binary | std::ios::ate);
+    if (hexdump.is_open())
+    {
+        if (gDevDebug) Console->Print("IngameCommand: Sending packet file %s", file_to_send);
+
+        size = hexdump.tellg();
+        buffer = new char [size];
+        hexdump.seekg (0, std::ios::beg);
+
+        hexdump.read (buffer, size);
+        hexdump.close();
+        if(DebugMode == true)
+        {
+            int k;
+            Console->Print("Byte dump of %s:", file_to_send);
+            for(k=0;k<size;k++)
+            {
+                Console->Print("Byte %d: %#x", k, buffer[k]);
+            }
+        }
+        else
+        {
+            if(Prot == 1)
+                source->getUDPConn()->write(buffer, size);
+            else if(Prot == 2)
+                source->getTCPConn()->write(buffer, size);
+            else // Should never happen...
+                Console->Print("%s unable to determine protocol in PCommands::doCmdrawf", Console->ColorText(RED, BLACK, "[Error]"));
+        }
+
+        delete[] buffer;
+    }
+    else
+    {
+        char output[100];
+        Console->Print("IngameCommand: Unable to send file %s", file_to_send);
+        snprintf(output, 100, "File not found: %s", file_to_send);
+        Chat->send(source, CHAT_DIRECT, "System", output);
+    }
+}
index d52948a..4f96f9f 100644 (file)
@@ -1,63 +1,63 @@
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdremove()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@remove actor/<raw item id>");\r
-        return;\r
-    }\r
-\r
-    char tmp_v1[30];\r
-    GetArgText(1, tmp_v1, 30);\r
-\r
-    if(strcmp(tmp_v1, "actor") == 0)\r
-    {\r
-        if(source->IsInRemoveActorMode() == false)\r
-        {\r
-            source->SetRemoveActorMode(true);\r
-            Chat->send(source, CHAT_DIRECT, "System", "You are now in REMOVE ACTOR mode. Rightclick an actor to remove it, type command again to disable mode");\r
-        }\r
-        else\r
-        {\r
-            source->SetRemoveActorMode(false);\r
-            Chat->send(source, CHAT_DIRECT, "System", "REMOVE ACTOR mode disabled");\r
-        }\r
-        return;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == true)\r
-    {\r
-        uint32_t tTest = GetArgInt(1);\r
-        if(WorldActors->IsDynamicActor(tTest) == true)\r
-        {\r
-            Chat->send(source, CHAT_DIRECT, "System", "You cannot remove dynamic actors over their ID!");\r
-            return;\r
-        }\r
-        uint32_t TargetID;\r
-        char delStr[128];\r
-        PMessage* tmpMsg;\r
-\r
-        TargetID = (uint32_t)(atoi(tmp_v1) & 0xffffffff);\r
-        tmpMsg = MsgBuilder->BuildFurnitureActivateMsg(source, TargetID, 5);\r
-\r
-        ClientManager->UDPBroadcast(tmpMsg, source);\r
-        tmpMsg = MsgBuilder->BuildFurnitureActivateMsg(source, TargetID, 9);\r
-\r
-        ClientManager->UDPBroadcast(tmpMsg, source);\r
-        snprintf(delStr, 127, "Item %d removed.", TargetID);\r
-        delStr[127] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", delStr);\r
-    }\r
-    else\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "Invalid argument given");\r
-        return;\r
-    }\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdremove()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@remove actor/<raw item id>");
+        return;
+    }
+
+    char tmp_v1[30];
+    GetArgText(1, tmp_v1, 30);
+
+    if(strcmp(tmp_v1, "actor") == 0)
+    {
+        if(source->IsInRemoveActorMode() == false)
+        {
+            source->SetRemoveActorMode(true);
+            Chat->send(source, CHAT_DIRECT, "System", "You are now in REMOVE ACTOR mode. Rightclick an actor to remove it, type command again to disable mode");
+        }
+        else
+        {
+            source->SetRemoveActorMode(false);
+            Chat->send(source, CHAT_DIRECT, "System", "REMOVE ACTOR mode disabled");
+        }
+        return;
+    }
+
+    if(IsArgNumeric(1) == true)
+    {
+        uint32_t tTest = GetArgInt(1);
+        if(WorldActors->IsDynamicActor(tTest) == true)
+        {
+            Chat->send(source, CHAT_DIRECT, "System", "You cannot remove dynamic actors over their ID!");
+            return;
+        }
+        uint32_t TargetID;
+        char delStr[128];
+        PMessage* tmpMsg;
+
+        TargetID = (uint32_t)(atoi(tmp_v1) & 0xffffffff);
+        tmpMsg = MsgBuilder->BuildFurnitureActivateMsg(source, TargetID, 5);
+
+        ClientManager->UDPBroadcast(tmpMsg, source);
+        tmpMsg = MsgBuilder->BuildFurnitureActivateMsg(source, TargetID, 9);
+
+        ClientManager->UDPBroadcast(tmpMsg, source);
+        snprintf(delStr, 127, "Item %d removed.", TargetID);
+        delStr[127] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", delStr);
+    }
+    else
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "Invalid argument given");
+        return;
+    }
+}
index ea23ff9..e0a2a74 100644 (file)
@@ -1,66 +1,66 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdsetlevel()\r
-{\r
-    int destLevel = 0;\r
-    bool SyntaxError = false;\r
-    if (ArgC < 2)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if (IsArgNumeric(2) == false)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-    else\r
-    {\r
-        destLevel = GetArgInt(2);\r
-    }\r
-\r
-    if (SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@setlevel <charID or nickname> <newlevel 1-99>");\r
-        return;\r
-    }\r
-\r
-    if (IsArgNumeric(1) == true)\r
-    {\r
-        target = GetClientByID(GetArgInt(1));\r
-    }\r
-    else\r
-    {\r
-        char tmp_destNick[50];\r
-        GetArgText(1, tmp_destNick, 50);\r
-        target = GetClientByNick(tmp_destNick);\r
-    }\r
-\r
-    if (target == NULL) // If victim isnt found, return error\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "No such player");\r
-        return;\r
-    }\r
-    if (source->GetAccountLevel() <= target->GetAccountLevel())\r
-    {\r
-        char tmpMsg[200];\r
-        snprintf(tmpMsg, 199, "Cant set new level for %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-        tmpMsg[199] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-        return;\r
-    }\r
-\r
-    PAccount Acc(target->GetAccountID());\r
-    Acc.SetLevel(destLevel);\r
-    Acc.Save();\r
-    source->RefreshAccountInfo(&Acc);\r
-\r
-    char tmpMsg[60], tmpMsg2[60];\r
-    snprintf(tmpMsg, 59, "Set level for player %s to %d", Chars->GetChar(target->GetCharID())->GetName().c_str(), destLevel);\r
-    snprintf(tmpMsg2, 59, "**POOF** Your new accesslevel is now %d", destLevel);\r
-\r
-    tmpMsg[59] = '\0';\r
-    tmpMsg2[59] = '\0';\r
-\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-    Chat->send(target, CHAT_DIRECT, "System", tmpMsg2);\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdsetlevel()
+{
+    int destLevel = 0;
+    bool SyntaxError = false;
+    if (ArgC < 2)
+    {
+        SyntaxError = true;
+    }
+
+    if (IsArgNumeric(2) == false)
+    {
+        SyntaxError = true;
+    }
+    else
+    {
+        destLevel = GetArgInt(2);
+    }
+
+    if (SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@setlevel <charID or nickname> <newlevel 1-99>");
+        return;
+    }
+
+    if (IsArgNumeric(1) == true)
+    {
+        target = GetClientByID(GetArgInt(1));
+    }
+    else
+    {
+        char tmp_destNick[50];
+        GetArgText(1, tmp_destNick, 50);
+        target = GetClientByNick(tmp_destNick);
+    }
+
+    if (target == NULL) // If victim isnt found, return error
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "No such player");
+        return;
+    }
+    if (source->GetAccountLevel() <= target->GetAccountLevel())
+    {
+        char tmpMsg[200];
+        snprintf(tmpMsg, 199, "Cant set new level for %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());
+        tmpMsg[199] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+        return;
+    }
+
+    PAccount Acc(target->GetAccountID());
+    Acc.SetLevel(destLevel);
+    Acc.Save();
+    source->RefreshAccountInfo(&Acc);
+
+    char tmpMsg[60], tmpMsg2[60];
+    snprintf(tmpMsg, 59, "Set level for player %s to %d", Chars->GetChar(target->GetCharID())->GetName().c_str(), destLevel);
+    snprintf(tmpMsg2, 59, "**POOF** Your new accesslevel is now %d", destLevel);
+
+    tmpMsg[59] = '\0';
+    tmpMsg2[59] = '\0';
+
+    Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+    Chat->send(target, CHAT_DIRECT, "System", tmpMsg2);
+}
index 0b38078..fdbd528 100644 (file)
@@ -1,17 +1,17 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmdsettime()\r
-{\r
-    if(ArgC < 1 && GetArgInt(1) == 0)\r
-    {\r
-       Chat->send(source, CHAT_DIRECT, "Usage", "@settime <raw timevalue>");\r
-       return;\r
-    }\r
-\r
-    int newtime = 0;\r
-    newtime = GetArgInt(1);\r
-\r
-    GameServer->SetGameTime(newtime);\r
-    Console->Print("IngameCommand: CharID %d set ingametime to %d", source->GetCharID(), newtime);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmdsettime()
+{
+    if(ArgC < 1 && GetArgInt(1) == 0)
+    {
+       Chat->send(source, CHAT_DIRECT, "Usage", "@settime <raw timevalue>");
+       return;
+    }
+
+    int newtime = 0;
+    newtime = GetArgInt(1);
+
+    GameServer->SetGameTime(newtime);
+    Console->Print("IngameCommand: CharID %d set ingametime to %d", source->GetCharID(), newtime);
+}
index c899549..d1447d4 100644 (file)
@@ -1,56 +1,56 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdshun()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@shun <charID or nickname>");\r
-        return;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == true)\r
-    {\r
-        target = GetClientByID(GetArgInt(1));\r
-    }\r
-    else\r
-    {\r
-        char tmp_destNick[50];\r
-        GetArgText(1, tmp_destNick, 50);\r
-        target = GetClientByNick(tmp_destNick);\r
-    }\r
-\r
-    if(target == NULL) // If victim isnt found, return error\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "No such player");\r
-        return;\r
-    }\r
-    if(source->GetAccountLevel() <= target->GetAccountLevel())\r
-    {\r
-        char tmpMsg[200];\r
-        snprintf(tmpMsg, 199, "Cant shun %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-        tmpMsg[199] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-        return;\r
-    }\r
-    if(target->GetChar()->IsShunned() == false)\r
-    {\r
-        target->GetChar()->SetShun(true);\r
-\r
-        char tmpMsg_success[81];\r
-        snprintf(tmpMsg_success, 80, "Successfully shunned %s", target->GetChar()->GetName().c_str());\r
-        tmpMsg_success[80] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg_success);\r
-        return;\r
-    }\r
-    else\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "Player is already shunned");\r
-        return;\r
-    }\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdshun()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@shun <charID or nickname>");
+        return;
+    }
+
+    if(IsArgNumeric(1) == true)
+    {
+        target = GetClientByID(GetArgInt(1));
+    }
+    else
+    {
+        char tmp_destNick[50];
+        GetArgText(1, tmp_destNick, 50);
+        target = GetClientByNick(tmp_destNick);
+    }
+
+    if(target == NULL) // If victim isnt found, return error
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "No such player");
+        return;
+    }
+    if(source->GetAccountLevel() <= target->GetAccountLevel())
+    {
+        char tmpMsg[200];
+        snprintf(tmpMsg, 199, "Cant shun %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());
+        tmpMsg[199] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+        return;
+    }
+    if(target->GetChar()->IsShunned() == false)
+    {
+        target->GetChar()->SetShun(true);
+
+        char tmpMsg_success[81];
+        snprintf(tmpMsg_success, 80, "Successfully shunned %s", target->GetChar()->GetName().c_str());
+        tmpMsg_success[80] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg_success);
+        return;
+    }
+    else
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "Player is already shunned");
+        return;
+    }
+}
index 249fa29..03494f2 100644 (file)
-#include <sstream>\r
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdskin()\r
-{\r
-// -------------------------------------------------------\r
-/*\r
-Usage:  @skin #<chardef idx>\r
-              for use with the index id from characters.def\r
-  or  @skin <model>|-|# [<head>[ <torso>[ <legs>]]]\r
-              <model> is the model id found after the model name in characters.def\r
-              # resets to real char skin (optionnaly modified by following args)\r
-              - means current skin\r
-              incrementaly optional <head>, <torso> and <legs> are values 0-9\r
-*/\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    uint32_t Skinval1, Skinval2, Skinval3, Skinval4;\r
-    PChar *SkinChar = Chars->GetChar(source->GetCharID());\r
-    std::stringstream SkinChat;\r
-    char SkinStr[128];\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@skin ( #<chardef idx> ) | ( <model> | # [<head>[ <torso>[ <legs>]]] )");\r
-        return;\r
-    }\r
-\r
-    char tmpval[30];\r
-    GetArgText(1, tmpval, 30);\r
-    if((tmpval[0] == '#') && (tmpval[1] != '\0'))\r
-    {\r
-        Skinval1 = atoi(tmpval+1);\r
-        SkinChar->SetCurrentLookFromCharType(atoi(tmpval+1));\r
-        SkinChat << "Skin set to the skin of char type ";\r
-        SkinChat << (int)Skinval1;\r
-    }\r
-    else\r
-    {\r
-        if ((tmpval[0] == '#') && (tmpval[1] == '\0'))\r
-        {\r
-            SkinChar->GetRealLook(Skinval1, Skinval2, Skinval3, Skinval4);\r
-        }\r
-        else if ((tmpval[0] == '-') && (tmpval[1] == '\0'))\r
-        {\r
-            SkinChar->GetCurrentLook(Skinval1, Skinval2, Skinval3, Skinval4);\r
-        }\r
-        else\r
-        {\r
-            Skinval1 = GetArgInt(1);\r
-        }\r
-\r
-        char tmp_arg2[30];\r
-        char tmp_arg3[30];\r
-        char tmp_arg4[30];\r
-\r
-        GetArgText(2, tmp_arg2, 30);\r
-        GetArgText(3, tmp_arg3, 30);\r
-        GetArgText(4, tmp_arg4, 30);\r
-\r
-        if(tmp_arg2[0] != '\0')\r
-        {\r
-            if(tmp_arg2[0] != '-')\r
-            {\r
-                tmp_arg2[1] = '\0';\r
-                Skinval2 = GetArgInt(2);\r
-            }\r
-            if(tmp_arg3[0] != '\0')\r
-            {\r
-                if(tmp_arg3[0] != '-')\r
-                {\r
-                    tmp_arg3[1] = '\0';\r
-                    Skinval3 = GetArgInt(3);\r
-                }\r
-                if(tmp_arg4[0] != '\0')\r
-                {\r
-                    if(tmp_arg4[0] != '-')\r
-                    {\r
-                        tmp_arg4[1] = '\0';\r
-                        Skinval4 = GetArgInt(4);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        SkinChar->SetCurrentLook(Skinval1, Skinval2, Skinval3, Skinval4);\r
-\r
-        SkinChat << "Skin set to model ";\r
-        SkinChat << (int)Skinval1 << " with head " << (int)Skinval2 << ", torso " << (int)Skinval3 << ", legs " << (int)Skinval4;\r
-    }\r
-\r
-    snprintf(SkinStr, 127, "%s", SkinChat.str().c_str());\r
-    SkinStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", SkinStr);\r
-\r
-    PMessage* tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-    ClientManager->UDPBroadcast(tmpMsg, source);\r
-}\r
+#include <sstream>
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdskin()
+{
+// -------------------------------------------------------
+/*
+Usage:  @skin #<chardef idx>
+              for use with the index id from characters.def
+  or  @skin <model>|-|# [<head>[ <torso>[ <legs>]]]
+              <model> is the model id found after the model name in characters.def
+              # resets to real char skin (optionnaly modified by following args)
+              - means current skin
+              incrementaly optional <head>, <torso> and <legs> are values 0-9
+*/
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    uint32_t Skinval1, Skinval2, Skinval3, Skinval4;
+    PChar *SkinChar = Chars->GetChar(source->GetCharID());
+    std::stringstream SkinChat;
+    char SkinStr[128];
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@skin ( #<chardef idx> ) | ( <model> | # [<head>[ <torso>[ <legs>]]] )");
+        return;
+    }
+
+    char tmpval[30];
+    GetArgText(1, tmpval, 30);
+    if((tmpval[0] == '#') && (tmpval[1] != '\0'))
+    {
+        Skinval1 = atoi(tmpval+1);
+        SkinChar->SetCurrentLookFromCharType(atoi(tmpval+1));
+        SkinChat << "Skin set to the skin of char type ";
+        SkinChat << (int)Skinval1;
+    }
+    else
+    {
+        if ((tmpval[0] == '#') && (tmpval[1] == '\0'))
+        {
+            SkinChar->GetRealLook(Skinval1, Skinval2, Skinval3, Skinval4);
+        }
+        else if ((tmpval[0] == '-') && (tmpval[1] == '\0'))
+        {
+            SkinChar->GetCurrentLook(Skinval1, Skinval2, Skinval3, Skinval4);
+        }
+        else
+        {
+            Skinval1 = GetArgInt(1);
+        }
+
+        char tmp_arg2[30];
+        char tmp_arg3[30];
+        char tmp_arg4[30];
+
+        GetArgText(2, tmp_arg2, 30);
+        GetArgText(3, tmp_arg3, 30);
+        GetArgText(4, tmp_arg4, 30);
+
+        if(tmp_arg2[0] != '\0')
+        {
+            if(tmp_arg2[0] != '-')
+            {
+                tmp_arg2[1] = '\0';
+                Skinval2 = GetArgInt(2);
+            }
+            if(tmp_arg3[0] != '\0')
+            {
+                if(tmp_arg3[0] != '-')
+                {
+                    tmp_arg3[1] = '\0';
+                    Skinval3 = GetArgInt(3);
+                }
+                if(tmp_arg4[0] != '\0')
+                {
+                    if(tmp_arg4[0] != '-')
+                    {
+                        tmp_arg4[1] = '\0';
+                        Skinval4 = GetArgInt(4);
+                    }
+                }
+            }
+        }
+
+        SkinChar->SetCurrentLook(Skinval1, Skinval2, Skinval3, Skinval4);
+
+        SkinChat << "Skin set to model ";
+        SkinChat << (int)Skinval1 << " with head " << (int)Skinval2 << ", torso " << (int)Skinval3 << ", legs " << (int)Skinval4;
+    }
+
+    snprintf(SkinStr, 127, "%s", SkinChat.str().c_str());
+    SkinStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", SkinStr);
+
+    PMessage* tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+    ClientManager->UDPBroadcast(tmpMsg, source);
+}
index 678a550..9d8407a 100644 (file)
@@ -1,92 +1,92 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdspawnactor()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 2)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == false || IsArgNumeric(2) == false)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    uint16_t tmpActorID = (uint16_t)GetArgInt(1);\r
-    uint16_t tmpFunctionID = (uint16_t)GetArgInt(2);\r
-    uint16_t tmpOption1 = 0;\r
-    uint16_t tmpOption2 = 0;\r
-    uint16_t tmpOption3 = 0;\r
-\r
-    if(ArgC > 2)\r
-    {\r
-        if(IsArgNumeric(3) == false)\r
-        {\r
-            SyntaxError = true;\r
-        }\r
-        else\r
-        {\r
-            tmpOption1 = (uint16_t)GetArgInt(3);\r
-            if(ArgC > 3)\r
-            {\r
-                if(IsArgNumeric(4) == false)\r
-                {\r
-                    SyntaxError = true;\r
-                }\r
-                else\r
-                {\r
-                    tmpOption1 = (uint16_t)GetArgInt(4);\r
-                    if(ArgC > 4)\r
-                    {\r
-                        if(IsArgNumeric(4) == false)\r
-                        {\r
-                            SyntaxError = true;\r
-                        }\r
-                        else\r
-                        {\r
-                            tmpOption1 = (uint16_t)GetArgInt(5);\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    if(tmpActorID == 0)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@spawnactor <actorID> <functionID> [<option1> <option2> <option3>]");\r
-        return;\r
-    }\r
-\r
-    if(WorldActors->IsValidWAFunction(tmpFunctionID) == true)\r
-    {\r
-        if(WorldActors->RequiresLinkedObject(tmpFunctionID == true))\r
-        {\r
-            if(WorldActors->IsValidLinkedObject(source, tmpOption1, tmpFunctionID) == false)\r
-            {\r
-                if(tmpOption1 == 0)\r
-                    Chat->send(source, CHAT_DIRECT, "System", "Error: This functionID requires an linked object");\r
-                else if(tmpOption1 == 18)\r
-                    Chat->send(source, CHAT_DIRECT, "System", "Error: Invalid destination world");\r
-                else\r
-                    Chat->send(source, CHAT_DIRECT, "System", "Error: Invalid worldobjectID to link to");\r
-                return;\r
-            }\r
-        }\r
-        WorldActors->AddWorldActor(source, tmpActorID, tmpFunctionID, tmpOption1, tmpOption2, tmpOption3);\r
-    }\r
-    else\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "Error: This is an invalid function ID");\r
-        return;\r
-    }\r
-    //PMessage* tmpMsg = MsgBuilder->BuiltSpawnObjectMsg(source, tmpActorID, tmpFunctionID, mWOID++);\r
-    //ClientManager->UDPBroadcast(tmpMsg, source);\r
-    //tmpMsg = NULL;\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdspawnactor()
+{
+    bool SyntaxError = false;
+    if(ArgC < 2)
+    {
+        SyntaxError = true;
+    }
+
+    if(IsArgNumeric(1) == false || IsArgNumeric(2) == false)
+    {
+        SyntaxError = true;
+    }
+
+    uint16_t tmpActorID = (uint16_t)GetArgInt(1);
+    uint16_t tmpFunctionID = (uint16_t)GetArgInt(2);
+    uint16_t tmpOption1 = 0;
+    uint16_t tmpOption2 = 0;
+    uint16_t tmpOption3 = 0;
+
+    if(ArgC > 2)
+    {
+        if(IsArgNumeric(3) == false)
+        {
+            SyntaxError = true;
+        }
+        else
+        {
+            tmpOption1 = (uint16_t)GetArgInt(3);
+            if(ArgC > 3)
+            {
+                if(IsArgNumeric(4) == false)
+                {
+                    SyntaxError = true;
+                }
+                else
+                {
+                    tmpOption1 = (uint16_t)GetArgInt(4);
+                    if(ArgC > 4)
+                    {
+                        if(IsArgNumeric(4) == false)
+                        {
+                            SyntaxError = true;
+                        }
+                        else
+                        {
+                            tmpOption1 = (uint16_t)GetArgInt(5);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if(tmpActorID == 0)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@spawnactor <actorID> <functionID> [<option1> <option2> <option3>]");
+        return;
+    }
+
+    if(WorldActors->IsValidWAFunction(tmpFunctionID) == true)
+    {
+        if(WorldActors->RequiresLinkedObject(tmpFunctionID == true))
+        {
+            if(WorldActors->IsValidLinkedObject(source, tmpOption1, tmpFunctionID) == false)
+            {
+                if(tmpOption1 == 0)
+                    Chat->send(source, CHAT_DIRECT, "System", "Error: This functionID requires an linked object");
+                else if(tmpOption1 == 18)
+                    Chat->send(source, CHAT_DIRECT, "System", "Error: Invalid destination world");
+                else
+                    Chat->send(source, CHAT_DIRECT, "System", "Error: Invalid worldobjectID to link to");
+                return;
+            }
+        }
+        WorldActors->AddWorldActor(source, tmpActorID, tmpFunctionID, tmpOption1, tmpOption2, tmpOption3);
+    }
+    else
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "Error: This is an invalid function ID");
+        return;
+    }
+    //PMessage* tmpMsg = MsgBuilder->BuiltSpawnObjectMsg(source, tmpActorID, tmpFunctionID, mWOID++);
+    //ClientManager->UDPBroadcast(tmpMsg, source);
+    //tmpMsg = NULL;
+}
index 8b86daa..6dee3f2 100644 (file)
@@ -1,35 +1,35 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdspeed()\r
-{\r
-// Speed override setting.\r
-// Usage: @speed <newspeed> | #\r
-//  with <speed> = 0 (no move).. 254 , 255 or # meaning "no speed override"\r
-\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@speed <newspeed: 0 .. 254 > | 255 | #");\r
-        return;\r
-    }\r
-    char tmpval[30];\r
-    GetArgText(1, tmpval, 30);\r
-\r
-    uint8_t val1;\r
-    char effStr[128];\r
-    PMessage* tmpMsg;\r
-\r
-    val1 = ((tmpval[0] == '#') ? 255 : (uint8_t)(atoi(tmpval) & 0xff));\r
-    source->GetChar()->SetSpeedOverride(val1);\r
-\r
-    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-    ClientManager->UDPBroadcast(tmpMsg, source);\r
-    snprintf(effStr, 127, "Speed override set to value %d ", val1);\r
-    effStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", effStr);\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdspeed()
+{
+// Speed override setting.
+// Usage: @speed <newspeed> | #
+//  with <speed> = 0 (no move).. 254 , 255 or # meaning "no speed override"
+
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@speed <newspeed: 0 .. 254 > | 255 | #");
+        return;
+    }
+    char tmpval[30];
+    GetArgText(1, tmpval, 30);
+
+    uint8_t val1;
+    char effStr[128];
+    PMessage* tmpMsg;
+
+    val1 = ((tmpval[0] == '#') ? 255 : (uint8_t)(atoi(tmpval) & 0xff));
+    source->GetChar()->SetSpeedOverride(val1);
+
+    tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+    ClientManager->UDPBroadcast(tmpMsg, source);
+    snprintf(effStr, 127, "Speed override set to value %d ", val1);
+    effStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", effStr);
+}
index 8c463a5..051b2fb 100644 (file)
-#include <chrono>\r
-#include <thread>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmd_dev_t()\r
-{\r
-  const char* usage = "Usage: @t r <rawid> (to remove object) | @t d <rawid> [<v1=74> [<v2=29>]] (to send death packet to object with args v1 v2)";\r
-  char tmpStr[128];\r
-  const char* textMsg = usage;\r
-  PMessage* tmpMsg = NULL;\r
-  char Arg1[30];\r
-\r
-  if ( IsAdmin() == false )\r
-    return;\r
-\r
-  Arg1[0] = tmpStr[0] = '\0';\r
-\r
-  if ( ArgC >= 2 )\r
-  {\r
-    GetArgText( 1, Arg1, 30 );\r
-    uint32_t targetObjectId = GetArgInt( 2 ) & 0xffffffff;\r
-    if ( Arg1[0] == 't' )\r
-    {\r
-      uint8_t val1;\r
-      if ( ArgC >= 3 )\r
-      {\r
-        int val2 = GetArgInt( 3 );\r
-        tmpMsg = new PMessage( 32 );\r
-        source->IncreaseUDP_ID();\r
-        *tmpMsg << ( uint8_t )0x13;\r
-        *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-        *tmpMsg << ( uint16_t )source->GetSessionID();\r
-        *tmpMsg << ( uint8_t )0x00; // Message length\r
-        *tmpMsg << ( uint8_t )0x03;\r
-        *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-        *tmpMsg << ( uint8_t )0x2d;\r
-        *tmpMsg << ( uint32_t )targetObjectId;\r
-        *tmpMsg << ( uint8_t )0x01;\r
-        *tmpMsg << ( uint32_t )val2;\r
-\r
-        ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
-        source->SendUDPMessage( tmpMsg );\r
-        snprintf( tmpStr, 127, "Sent 13/03/2d msg to object id 0x%08x with values 6/%d", targetObjectId, val2 );\r
-        textMsg = tmpStr;\r
-      }\r
-      else for(val1 = 2; val1 < 255; ++val1)\r
-      {\r
-        if(val1 == 6) continue;\r
-        tmpMsg = new PMessage( 15 );\r
-        source->IncreaseUDP_ID();\r
-        *tmpMsg << ( uint8_t )0x13;\r
-        *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-        *tmpMsg << ( uint16_t )source->GetSessionID();\r
-        *tmpMsg << ( uint8_t )0x00; // Message length\r
-        *tmpMsg << ( uint8_t )0x03;\r
-        *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-        *tmpMsg << ( uint8_t )0x2d;\r
-        *tmpMsg << ( uint32_t )targetObjectId;\r
-        *tmpMsg << ( uint8_t )val1;\r
-\r
-        ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
-        source->SendUDPMessage( tmpMsg );\r
-        snprintf( tmpStr, 127, "Sent 13/03/2d msg to object id 0x%08x with value %d", targetObjectId, val1 );\r
-        textMsg = tmpStr;\r
-        tmpStr[127] = '\0';\r
-        Chat->send( source, CHAT_DIRECT, "System", textMsg );\r
-        source->getUDPConn()->update();\r
-        source->getTCPConn()->update();\r
-        //sleep(1);\r
-        std::this_thread::sleep_for(std::chrono::seconds(1));\r
-      }\r
-      tmpMsg = NULL;\r
-    }\r
-    else if ( Arg1[0] == 'd' )\r
-    {\r
-      uint8_t val1 = 0x4a; // default values\r
-      uint8_t val2 = 0x1e;\r
-\r
-      if ( ArgC >= 3 )\r
-        val1 = GetArgInt( 3 ) & 0xff;\r
-      if ( ArgC >= 4 )\r
-        val2 = GetArgInt( 4 ) & 0xff;\r
-      tmpMsg = MsgBuilder->BuildNpcDeathMsg( source, targetObjectId, val1, val2 );\r
-      snprintf( tmpStr, 127, "Sending Death update to object id 0x%08x with values 0x%02x 0x%02x", targetObjectId, val1, val2 );\r
-      textMsg = tmpStr;\r
-    }\r
-    else if ( Arg1[0] == 'm' )\r
-    {\r
-      uint8_t nTxtGroupID = targetObjectId & 0xff;\r
-      uint16_t nTxtID = 10;\r
-      //uint32_t nVal = 0;\r
-      if ( ArgC >= 3 )\r
-        nTxtID = GetArgInt( 3 ) & 0xffff;\r
-      //if(ArgC >= 4)\r
-      //  val2 = GetArgInt(4) & 0xff;\r
-\r
-      tmpMsg = new PMessage( 20 );\r
-\r
-      source->IncreaseUDP_ID();\r
-      *tmpMsg << ( uint8_t )0x13;\r
-      *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-      *tmpMsg << ( uint16_t )source->GetSessionID();\r
-      *tmpMsg << ( uint8_t )0x0e; // Message length\r
-      *tmpMsg << ( uint8_t )0x03;\r
-      *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-      *tmpMsg << ( uint8_t )0x1f;\r
-      *tmpMsg << ( uint16_t )source->GetLocalID();\r
-      *tmpMsg << ( uint8_t )0x25; // ??\r
-      *tmpMsg << ( uint8_t )0x15; // ??\r
-      *tmpMsg << nTxtGroupID;\r
-      *tmpMsg << nTxtID;\r
-      *tmpMsg << ( uint16_t )0x00; // ??\r
-      *tmpMsg << ( uint8_t )0x01;\r
-      *tmpMsg << ( uint8_t )0x04;\r
-      *tmpMsg << ( uint32_t )0x00;\r
-      //*tmpMsg << (uint8_t)0x00; // ??\r
-      //*tmpMsg << (uint8_t)0x00; // ??\r
-      //*tmpMsg << (uint32_t)nVal;\r
-\r
-      ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
-      snprintf( tmpStr, 127, "Using msg n %d from group %d", nTxtID, nTxtGroupID );\r
-      textMsg = tmpStr;\r
-\r
-      source->SendUDPMessage( tmpMsg );\r
-      tmpMsg = NULL;\r
-    }\r
-    else if ( Arg1[0] == 'e' )\r
-    {\r
-      targetObjectId = 1004; //target=int\r
-      uint16_t nval = 5;\r
-      uint8_t nType = 1; // 1=+ 2=-\r
-      uint16_t nDur = 20;\r
-      uint8_t nparam = 1;\r
-\r
-        nparam = GetArgInt( 2 ) & 0xff;\r
-\r
-        tmpMsg = new PMessage( 32 );\r
-\r
-        source->IncreaseUDP_ID();\r
-        *tmpMsg << ( uint8_t )0x13;\r
-        *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-        *tmpMsg << ( uint16_t )source->GetSessionID();\r
-        *tmpMsg << ( uint8_t )0x0e; // Message length\r
-        *tmpMsg << ( uint8_t )0x03;\r
-        *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-        *tmpMsg << ( uint8_t )0x1f;\r
-        *tmpMsg << ( uint16_t )source->GetLocalID();\r
-        *tmpMsg << ( uint8_t )0x25; // ??\r
-        *tmpMsg << ( uint8_t )0x06; // ??\r
-        *tmpMsg << ( uint8_t )0x01; // 1 effect\r
-        *tmpMsg << ( uint8_t )0x01; // effect on intox level ????\r
-        *tmpMsg << ( uint16_t )nDur;\r
-        *tmpMsg << ( uint16_t )(700+(targetObjectId % 100)); //item id Thyronol\r
-        *tmpMsg << ( uint8_t )nType;\r
-        *tmpMsg << ( uint16_t )(nval*100); //uint32_t in nc2.2\r
-        *tmpMsg << ( uint16_t )targetObjectId;\r
-\r
-\r
-        ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
-        snprintf( tmpStr, 127, "Sendind drug mod to stat %d, %s %d", targetObjectId, (nType == 1 ? "inc" : "dec"), nval );\r
-        textMsg = tmpStr;\r
-\r
-        source->SendUDPMessage( tmpMsg );\r
-        tmpMsg = NULL;\r
-    }\r
-    else if ( Arg1[0] == 'w' )\r
-    {\r
-      /*targetObjectId &= 0xffff;\r
-      uint16_t val1 = 0;\r
-      if ( ArgC >= 3 )\r
-        val1 = GetArgInt( 3 ) & 0xffff;\r
-*/\r
-      tmpMsg = new PMessage( 15 );\r
-\r
-      source->IncreaseUDP_ID();\r
-\r
-      *tmpMsg << ( uint8_t )0x13;\r
-      *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-      *tmpMsg << ( uint16_t )source->GetSessionID();\r
-      *tmpMsg << ( uint8_t )0x0a; // Message length place;\r
-      *tmpMsg << ( uint8_t )0x03;\r
-      *tmpMsg << ( uint16_t )source->GetUDP_ID();\r
-      *tmpMsg << ( uint8_t )0x23;\r
-      *tmpMsg << ( uint16_t )0x0012; // cmd = ?\r
-      *tmpMsg << ( uint16_t )0x0007;\r
-      *tmpMsg << ( uint32_t )0x00000000;\r
-\r
-      ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
-\r
-      snprintf( tmpStr, 127, "Sending w msg " );\r
-      textMsg = tmpStr;\r
-\r
-      source->SendUDPMessage( tmpMsg );\r
-      tmpMsg = NULL;\r
-    }\r
-    else if ( Arg1[0] == 'x' )\r
-    {\r
-      uint8_t val1 = targetObjectId &= 0xff;\r
-\r
-      tmpMsg = MsgBuilder->BuildUndefineduseMsg( source, val1 );\r
-\r
-      snprintf( tmpStr, 127, "Sending x msg with param %d (0x%2x)", val1, val1 );\r
-      textMsg = tmpStr;\r
-\r
-      source->SendUDPMessage( tmpMsg );\r
-      tmpMsg = NULL;\r
-    }\r
-  }\r
-\r
-  tmpStr[127] = '\0';\r
-  Chat->send( source, CHAT_DIRECT, "System", textMsg );\r
-\r
-  if ( tmpMsg )\r
-    ClientManager->UDPBroadcast( tmpMsg, source );\r
-}\r
-\r
-/*** Packet fields testing. Please do not delete (Hammag)\r
-void PCommands::doCmd_dev_t()\r
-{\r
-    if(IsAdmin() == false)\r
-        return;\r
-\r
-    char Arg1[30], Arg2[30];\r
-\r
-    Arg1[0] = '\0';\r
-    Arg2[0] = '\0';\r
-\r
-    if(ArgC > 0)\r
-    {\r
-        GetArgText(1, Arg1, 30);\r
-        if(ArgC > 1)\r
-        {\r
-            GetArgText(2, Arg2, 30);\r
-        }\r
-    }\r
-\r
-    uint32_t val1;\r
-    uint8_t val2;\r
-    char tmpStr[128];\r
-    static PMessage* tmpMsg = NULL;\r
-    bool SetUDP_IDNeeded = true;\r
-    PChar* nChar = source->GetChar();\r
-    (nChar->Coords).mY += 20;\r
-    (nChar->Coords).mZ += 20;\r
-    (nChar->Coords).mX += 20;\r
-\r
-    if (!tmpMsg)\r
-    {\r
-      tmpMsg = MsgBuilder->BuildPacket0Msg(source);\r
-      //tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-      SetUDP_IDNeeded = false;\r
-    }\r
-\r
-    if(Arg1[0] != '\0' && Arg2[0] != '\0')\r
-    {\r
-        val1 = atoi(Arg1);\r
-        val2 = (uint8_t)(atoi(Arg2) & 0xff);\r
-        //tmpMsg->U8Data(16 + val1) = val2;\r
-        tmpMsg->U8Data(10 + val1) = val2;\r
-        snprintf(tmpStr, 127, "Data #%d set to value 0x%02x", val1, val2);\r
-    }\r
-    else\r
-    {\r
-      if (tmpMsg)\r
-        delete tmpMsg;\r
-      //tmpMsg = MsgBuilder->BuildCharHelloMsg(source);\r
-      tmpMsg = MsgBuilder->BuildPacket0Msg(source);\r
-      SetUDP_IDNeeded = false;\r
-      snprintf(tmpStr, 127, "Data reset to normal values");\r
-    }\r
-\r
-    tmpStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpStr);\r
-\r
-    PMessage* SendMsg = new PMessage(*tmpMsg);\r
-    if(SetUDP_IDNeeded) {\r
-      source->FillInUDP_ID(SendMsg);\r
-    }\r
-    SendMsg->Dump();\r
-    //ClientManager->UDPBroadcast(SendMsg, source);\r
-    source->SendUDPMessage(SendMsg);\r
-}\r
-***/\r
-\r
-/*** Subwy testing. Please do not delete (Hammag)\r
-void PCommands::doCmd_dev_t()\r
-{\r
-  if(IsAdmin() == false)\r
-      return;\r
-\r
-  char tmpStr[128];\r
- uint8_t SubWay[] = {0x13, 0x71, 0x00, 0x9b, 0xde,\r
-  //Subway 1 (fc 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xfc, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xfc, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 2 (fb 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xfb, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0xf0, 0x41, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xfb, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 3 (fa 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xfa, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x70, 0x42, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xfa, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 4 (f9 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf9, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0xb4, 0x42, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf9, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 5 (f8 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf8, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0xf0, 0x42, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf8, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 6 (f7 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf7, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x16, 0x43, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf7, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00};\r
-\r
- uint8_t SubWay2[] = {0x13, 0x71, 0x00, 0x9b, 0xde,\r
-  //Subway 7 (f6 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf6, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x34, 0x43, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf6, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 8 (f5 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf5, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x52, 0x43, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf5, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 9 (f4 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf4, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x70, 0x43, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf4, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 10 (f3 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf3, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x87, 0x43, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf3, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00,\r
-  //Subway 11 (f2 03)\r
-  0x11,\r
-  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf2, 0x03, 0x00, 0x00,\r
-  0x00, 0x00, 0x00, 0x96, 0x43, 0x00, 0x01,\r
-  0x0d,\r
-  0x03, 0x71, 0x00, 0x2d, 0xf2, 0x03, 0x00, 0x00, 0x0a, 0x00,\r
-  0x00, 0x00, 0x00};\r
-\r
- if (source->GetChar()->GetLocation() != 1000)\r
-  return;\r
-\r
- //SubWay List\r
- //Subway 1\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[7] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[25] = source->GetUDP_ID();\r
-\r
- //Subway 2\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[39] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[57] = source->GetUDP_ID();\r
-\r
- //Subway 3\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[71] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[89] = source->GetUDP_ID();\r
-\r
- //Subway 4\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[103] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[121] = source->GetUDP_ID();\r
-\r
- //Subway 5\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[135] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[153] = source->GetUDP_ID();\r
-\r
- //Subway 6\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[167] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay[185] = source->GetUDP_ID();\r
-\r
- //Subway 7\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[7] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[25] = source->GetUDP_ID();\r
-\r
- //Subway 8\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[39] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[57] = source->GetUDP_ID();\r
-\r
- //Subway 9\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[71] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[89] = source->GetUDP_ID();\r
-\r
- //Subway 10\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[103] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[121] = source->GetUDP_ID();\r
-\r
- //Subway 11\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[135] = source->GetUDP_ID();\r
- source->IncreaseUDP_ID();\r
- *(uint16_t*)&SubWay2[153] = source->GetUDP_ID();\r
-\r
- *(uint16_t*)&SubWay[1] = source->GetUDP_ID();\r
- *(uint16_t*)&SubWay[3] = source->GetSessionID();\r
-\r
- PMessage* msg;\r
- msg = new PMessage(197);\r
- msg->Write(SubWay, sizeof(SubWay));\r
-Console->Print("---- Working 1 ----");\r
-msg->Dump();\r
-  source->SendUDPMessage(msg);\r
-msg = MsgBuilder->BuildSubwaySpawnMsg(source, false);\r
-Console->Print("---- Not Working 1 ----");\r
-msg->Dump();\r
-source->SendUDPMessage(msg);\r
-\r
- *(uint16_t*)&SubWay2[1] = source->GetUDP_ID();\r
- *(uint16_t*)&SubWay2[3] = source->GetSessionID();\r
-\r
- msg = new PMessage(197);\r
- msg->Write(SubWay2, sizeof(SubWay2));\r
-Console->Print("---- Working 2 ----");\r
-msg->Dump();\r
-  source->SendUDPMessage(msg);\r
-msg = MsgBuilder->BuildSubwaySpawnMsg(source, true);\r
-Console->Print("---- Not Working 2 ----");\r
-msg->Dump();\r
-source->SendUDPMessage(msg);\r
-\r
-  snprintf(tmpStr, 127, "Initial subway data sent");\r
-  tmpStr[127] = '\0';\r
-  Chat->send(source, CHAT_DIRECT, "System", tmpStr);\r
-}\r
-***/\r
+#include <chrono>
+#include <thread>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmd_dev_t()
+{
+  const char* usage = "Usage: @t r <rawid> (to remove object) | @t d <rawid> [<v1=74> [<v2=29>]] (to send death packet to object with args v1 v2)";
+  char tmpStr[128];
+  const char* textMsg = usage;
+  PMessage* tmpMsg = NULL;
+  char Arg1[30];
+
+  if ( IsAdmin() == false )
+    return;
+
+  Arg1[0] = tmpStr[0] = '\0';
+
+  if ( ArgC >= 2 )
+  {
+    GetArgText( 1, Arg1, 30 );
+    uint32_t targetObjectId = GetArgInt( 2 ) & 0xffffffff;
+    if ( Arg1[0] == 't' )
+    {
+      uint8_t val1;
+      if ( ArgC >= 3 )
+      {
+        int val2 = GetArgInt( 3 );
+        tmpMsg = new PMessage( 32 );
+        source->IncreaseUDP_ID();
+        *tmpMsg << ( uint8_t )0x13;
+        *tmpMsg << ( uint16_t )source->GetUDP_ID();
+        *tmpMsg << ( uint16_t )source->GetSessionID();
+        *tmpMsg << ( uint8_t )0x00; // Message length
+        *tmpMsg << ( uint8_t )0x03;
+        *tmpMsg << ( uint16_t )source->GetUDP_ID();
+        *tmpMsg << ( uint8_t )0x2d;
+        *tmpMsg << ( uint32_t )targetObjectId;
+        *tmpMsg << ( uint8_t )0x01;
+        *tmpMsg << ( uint32_t )val2;
+
+        ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+        source->SendUDPMessage( tmpMsg );
+        snprintf( tmpStr, 127, "Sent 13/03/2d msg to object id 0x%08x with values 6/%d", targetObjectId, val2 );
+        textMsg = tmpStr;
+      }
+      else for(val1 = 2; val1 < 255; ++val1)
+      {
+        if(val1 == 6) continue;
+        tmpMsg = new PMessage( 15 );
+        source->IncreaseUDP_ID();
+        *tmpMsg << ( uint8_t )0x13;
+        *tmpMsg << ( uint16_t )source->GetUDP_ID();
+        *tmpMsg << ( uint16_t )source->GetSessionID();
+        *tmpMsg << ( uint8_t )0x00; // Message length
+        *tmpMsg << ( uint8_t )0x03;
+        *tmpMsg << ( uint16_t )source->GetUDP_ID();
+        *tmpMsg << ( uint8_t )0x2d;
+        *tmpMsg << ( uint32_t )targetObjectId;
+        *tmpMsg << ( uint8_t )val1;
+
+        ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+        source->SendUDPMessage( tmpMsg );
+        snprintf( tmpStr, 127, "Sent 13/03/2d msg to object id 0x%08x with value %d", targetObjectId, val1 );
+        textMsg = tmpStr;
+        tmpStr[127] = '\0';
+        Chat->send( source, CHAT_DIRECT, "System", textMsg );
+        source->getUDPConn()->update();
+        source->getTCPConn()->update();
+        //sleep(1);
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+      }
+      tmpMsg = NULL;
+    }
+    else if ( Arg1[0] == 'd' )
+    {
+      uint8_t val1 = 0x4a; // default values
+      uint8_t val2 = 0x1e;
+
+      if ( ArgC >= 3 )
+        val1 = GetArgInt( 3 ) & 0xff;
+      if ( ArgC >= 4 )
+        val2 = GetArgInt( 4 ) & 0xff;
+      tmpMsg = MsgBuilder->BuildNpcDeathMsg( source, targetObjectId, val1, val2 );
+      snprintf( tmpStr, 127, "Sending Death update to object id 0x%08x with values 0x%02x 0x%02x", targetObjectId, val1, val2 );
+      textMsg = tmpStr;
+    }
+    else if ( Arg1[0] == 'm' )
+    {
+      uint8_t nTxtGroupID = targetObjectId & 0xff;
+      uint16_t nTxtID = 10;
+      //uint32_t nVal = 0;
+      if ( ArgC >= 3 )
+        nTxtID = GetArgInt( 3 ) & 0xffff;
+      //if(ArgC >= 4)
+      //  val2 = GetArgInt(4) & 0xff;
+
+      tmpMsg = new PMessage( 20 );
+
+      source->IncreaseUDP_ID();
+      *tmpMsg << ( uint8_t )0x13;
+      *tmpMsg << ( uint16_t )source->GetUDP_ID();
+      *tmpMsg << ( uint16_t )source->GetSessionID();
+      *tmpMsg << ( uint8_t )0x0e; // Message length
+      *tmpMsg << ( uint8_t )0x03;
+      *tmpMsg << ( uint16_t )source->GetUDP_ID();
+      *tmpMsg << ( uint8_t )0x1f;
+      *tmpMsg << ( uint16_t )source->GetLocalID();
+      *tmpMsg << ( uint8_t )0x25; // ??
+      *tmpMsg << ( uint8_t )0x15; // ??
+      *tmpMsg << nTxtGroupID;
+      *tmpMsg << nTxtID;
+      *tmpMsg << ( uint16_t )0x00; // ??
+      *tmpMsg << ( uint8_t )0x01;
+      *tmpMsg << ( uint8_t )0x04;
+      *tmpMsg << ( uint32_t )0x00;
+      //*tmpMsg << (uint8_t)0x00; // ??
+      //*tmpMsg << (uint8_t)0x00; // ??
+      //*tmpMsg << (uint32_t)nVal;
+
+      ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+      snprintf( tmpStr, 127, "Using msg n %d from group %d", nTxtID, nTxtGroupID );
+      textMsg = tmpStr;
+
+      source->SendUDPMessage( tmpMsg );
+      tmpMsg = NULL;
+    }
+    else if ( Arg1[0] == 'e' )
+    {
+      targetObjectId = 1004; //target=int
+      uint16_t nval = 5;
+      uint8_t nType = 1; // 1=+ 2=-
+      uint16_t nDur = 20;
+      uint8_t nparam = 1;
+
+        nparam = GetArgInt( 2 ) & 0xff;
+
+        tmpMsg = new PMessage( 32 );
+
+        source->IncreaseUDP_ID();
+        *tmpMsg << ( uint8_t )0x13;
+        *tmpMsg << ( uint16_t )source->GetUDP_ID();
+        *tmpMsg << ( uint16_t )source->GetSessionID();
+        *tmpMsg << ( uint8_t )0x0e; // Message length
+        *tmpMsg << ( uint8_t )0x03;
+        *tmpMsg << ( uint16_t )source->GetUDP_ID();
+        *tmpMsg << ( uint8_t )0x1f;
+        *tmpMsg << ( uint16_t )source->GetLocalID();
+        *tmpMsg << ( uint8_t )0x25; // ??
+        *tmpMsg << ( uint8_t )0x06; // ??
+        *tmpMsg << ( uint8_t )0x01; // 1 effect
+        *tmpMsg << ( uint8_t )0x01; // effect on intox level ????
+        *tmpMsg << ( uint16_t )nDur;
+        *tmpMsg << ( uint16_t )(700+(targetObjectId % 100)); //item id Thyronol
+        *tmpMsg << ( uint8_t )nType;
+        *tmpMsg << ( uint16_t )(nval*100); //uint32_t in nc2.2
+        *tmpMsg << ( uint16_t )targetObjectId;
+
+
+        ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+        snprintf( tmpStr, 127, "Sendind drug mod to stat %d, %s %d", targetObjectId, (nType == 1 ? "inc" : "dec"), nval );
+        textMsg = tmpStr;
+
+        source->SendUDPMessage( tmpMsg );
+        tmpMsg = NULL;
+    }
+    else if ( Arg1[0] == 'w' )
+    {
+      /*targetObjectId &= 0xffff;
+      uint16_t val1 = 0;
+      if ( ArgC >= 3 )
+        val1 = GetArgInt( 3 ) & 0xffff;
+*/
+      tmpMsg = new PMessage( 15 );
+
+      source->IncreaseUDP_ID();
+
+      *tmpMsg << ( uint8_t )0x13;
+      *tmpMsg << ( uint16_t )source->GetUDP_ID();
+      *tmpMsg << ( uint16_t )source->GetSessionID();
+      *tmpMsg << ( uint8_t )0x0a; // Message length place;
+      *tmpMsg << ( uint8_t )0x03;
+      *tmpMsg << ( uint16_t )source->GetUDP_ID();
+      *tmpMsg << ( uint8_t )0x23;
+      *tmpMsg << ( uint16_t )0x0012; // cmd = ?
+      *tmpMsg << ( uint16_t )0x0007;
+      *tmpMsg << ( uint32_t )0x00000000;
+
+      ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+
+      snprintf( tmpStr, 127, "Sending w msg " );
+      textMsg = tmpStr;
+
+      source->SendUDPMessage( tmpMsg );
+      tmpMsg = NULL;
+    }
+    else if ( Arg1[0] == 'x' )
+    {
+      uint8_t val1 = targetObjectId &= 0xff;
+
+      tmpMsg = MsgBuilder->BuildUndefineduseMsg( source, val1 );
+
+      snprintf( tmpStr, 127, "Sending x msg with param %d (0x%2x)", val1, val1 );
+      textMsg = tmpStr;
+
+      source->SendUDPMessage( tmpMsg );
+      tmpMsg = NULL;
+    }
+  }
+
+  tmpStr[127] = '\0';
+  Chat->send( source, CHAT_DIRECT, "System", textMsg );
+
+  if ( tmpMsg )
+    ClientManager->UDPBroadcast( tmpMsg, source );
+}
+
+/*** Packet fields testing. Please do not delete (Hammag)
+void PCommands::doCmd_dev_t()
+{
+    if(IsAdmin() == false)
+        return;
+
+    char Arg1[30], Arg2[30];
+
+    Arg1[0] = '\0';
+    Arg2[0] = '\0';
+
+    if(ArgC > 0)
+    {
+        GetArgText(1, Arg1, 30);
+        if(ArgC > 1)
+        {
+            GetArgText(2, Arg2, 30);
+        }
+    }
+
+    uint32_t val1;
+    uint8_t val2;
+    char tmpStr[128];
+    static PMessage* tmpMsg = NULL;
+    bool SetUDP_IDNeeded = true;
+    PChar* nChar = source->GetChar();
+    (nChar->Coords).mY += 20;
+    (nChar->Coords).mZ += 20;
+    (nChar->Coords).mX += 20;
+
+    if (!tmpMsg)
+    {
+      tmpMsg = MsgBuilder->BuildPacket0Msg(source);
+      //tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+      SetUDP_IDNeeded = false;
+    }
+
+    if(Arg1[0] != '\0' && Arg2[0] != '\0')
+    {
+        val1 = atoi(Arg1);
+        val2 = (uint8_t)(atoi(Arg2) & 0xff);
+        //tmpMsg->U8Data(16 + val1) = val2;
+        tmpMsg->U8Data(10 + val1) = val2;
+        snprintf(tmpStr, 127, "Data #%d set to value 0x%02x", val1, val2);
+    }
+    else
+    {
+      if (tmpMsg)
+        delete tmpMsg;
+      //tmpMsg = MsgBuilder->BuildCharHelloMsg(source);
+      tmpMsg = MsgBuilder->BuildPacket0Msg(source);
+      SetUDP_IDNeeded = false;
+      snprintf(tmpStr, 127, "Data reset to normal values");
+    }
+
+    tmpStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", tmpStr);
+
+    PMessage* SendMsg = new PMessage(*tmpMsg);
+    if(SetUDP_IDNeeded) {
+      source->FillInUDP_ID(SendMsg);
+    }
+    SendMsg->Dump();
+    //ClientManager->UDPBroadcast(SendMsg, source);
+    source->SendUDPMessage(SendMsg);
+}
+***/
+
+/*** Subwy testing. Please do not delete (Hammag)
+void PCommands::doCmd_dev_t()
+{
+  if(IsAdmin() == false)
+      return;
+
+  char tmpStr[128];
+ uint8_t SubWay[] = {0x13, 0x71, 0x00, 0x9b, 0xde,
+  //Subway 1 (fc 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xfc, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xfc, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 2 (fb 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xfb, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x41, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xfb, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 3 (fa 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xfa, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x42, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xfa, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 4 (f9 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf9, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xb4, 0x42, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf9, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 5 (f8 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf8, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x42, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf8, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 6 (f7 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf7, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x16, 0x43, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf7, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00};
+
+ uint8_t SubWay2[] = {0x13, 0x71, 0x00, 0x9b, 0xde,
+  //Subway 7 (f6 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf6, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x34, 0x43, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf6, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 8 (f5 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf5, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x52, 0x43, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf5, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 9 (f4 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf4, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x43, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf4, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 10 (f3 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf3, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x87, 0x43, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf3, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00,
+  //Subway 11 (f2 03)
+  0x11,
+  0x03, 0x6d, 0x00, 0x28, 0x27, 0x00, 0xf2, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x96, 0x43, 0x00, 0x01,
+  0x0d,
+  0x03, 0x71, 0x00, 0x2d, 0xf2, 0x03, 0x00, 0x00, 0x0a, 0x00,
+  0x00, 0x00, 0x00};
+
+ if (source->GetChar()->GetLocation() != 1000)
+  return;
+
+ //SubWay List
+ //Subway 1
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[7] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[25] = source->GetUDP_ID();
+
+ //Subway 2
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[39] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[57] = source->GetUDP_ID();
+
+ //Subway 3
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[71] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[89] = source->GetUDP_ID();
+
+ //Subway 4
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[103] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[121] = source->GetUDP_ID();
+
+ //Subway 5
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[135] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[153] = source->GetUDP_ID();
+
+ //Subway 6
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[167] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay[185] = source->GetUDP_ID();
+
+ //Subway 7
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[7] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[25] = source->GetUDP_ID();
+
+ //Subway 8
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[39] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[57] = source->GetUDP_ID();
+
+ //Subway 9
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[71] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[89] = source->GetUDP_ID();
+
+ //Subway 10
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[103] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[121] = source->GetUDP_ID();
+
+ //Subway 11
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[135] = source->GetUDP_ID();
+ source->IncreaseUDP_ID();
+ *(uint16_t*)&SubWay2[153] = source->GetUDP_ID();
+
+ *(uint16_t*)&SubWay[1] = source->GetUDP_ID();
+ *(uint16_t*)&SubWay[3] = source->GetSessionID();
+
+ PMessage* msg;
+ msg = new PMessage(197);
+ msg->Write(SubWay, sizeof(SubWay));
+Console->Print("---- Working 1 ----");
+msg->Dump();
+  source->SendUDPMessage(msg);
+msg = MsgBuilder->BuildSubwaySpawnMsg(source, false);
+Console->Print("---- Not Working 1 ----");
+msg->Dump();
+source->SendUDPMessage(msg);
+
+ *(uint16_t*)&SubWay2[1] = source->GetUDP_ID();
+ *(uint16_t*)&SubWay2[3] = source->GetSessionID();
+
+ msg = new PMessage(197);
+ msg->Write(SubWay2, sizeof(SubWay2));
+Console->Print("---- Working 2 ----");
+msg->Dump();
+  source->SendUDPMessage(msg);
+msg = MsgBuilder->BuildSubwaySpawnMsg(source, true);
+Console->Print("---- Not Working 2 ----");
+msg->Dump();
+source->SendUDPMessage(msg);
+
+  snprintf(tmpStr, 127, "Initial subway data sent");
+  tmpStr[127] = '\0';
+  Chat->send(source, CHAT_DIRECT, "System", tmpStr);
+}
+***/
index beaf4fe..8755110 100644 (file)
@@ -3,59 +3,59 @@
 
 void PCommands::doCmdtest()
 {
-    if (GetArgInt(1) == 1)\r
-    {\r
-        if(ArgC < 5)\r
-            return;\r
-\r
-        PNPC* targetNPC = NULL;\r
-        PNPCWorld* currentNPCWorld = NULL;\r
-        currentNPCWorld = NPCManager->GetWorld( source->GetChar()->GetLocation() );\r
-        if ( currentNPCWorld )\r
-        {\r
-            targetNPC = currentNPCWorld->GetNPC( GetArgInt(2) );\r
-            if(!targetNPC)\r
-                return;\r
-            // @test 15 <npcID> <target_to_attack> <unknown uint8_t value>\r
-            targetNPC->Attack(GetArgInt(3), (uint8_t)GetArgInt(5), (uint8_t)GetArgInt(4));\r
-        }\r
-    }\r
-    else if (GetArgInt(1) == 2)\r
-    {\r
-        if(ArgC < 3)\r
-            return;\r
-\r
-        int tF1 = GetArgInt(2);\r
-        int tF2 = GetArgInt(3);\r
-        const PDefFaction* tFactionA = NULL;\r
-        const PDefFaction* tFactionB = NULL;\r
-\r
-        if(tF1 > tF2)\r
-        {\r
-            tFactionA = GameDefs->Factions()->GetDef(tF1);\r
-            tFactionB = GameDefs->Factions()->GetDef(tF2);\r
-        }\r
-        else\r
-        {\r
-            tFactionA = GameDefs->Factions()->GetDef(tF2);\r
-            tFactionB = GameDefs->Factions()->GetDef(tF1);\r
-        }\r
-\r
-        if(tFactionA && tFactionB)\r
-        {\r
-            int tRel = -99;\r
-            if(tF1 > tF2)\r
-                tRel = tFactionA->GetRelation(tF2);\r
-            else\r
-                tRel = tFactionA->GetRelation(tF1);\r
-\r
-            char buff[150];\r
-            snprintf(buff, 150, "Relation between <%s> and <%s> is: %d", tFactionA->GetName().c_str(), tFactionB->GetName().c_str(), tRel);\r
-            Chat->send(source, CHAT_DIRECT, "Relations", buff);\r
-        }\r
-        else\r
-            Chat->send(source, CHAT_DIRECT, "Relations", "Invalid faction");\r
-    }\r
+    if (GetArgInt(1) == 1)
+    {
+        if(ArgC < 5)
+            return;
+
+        PNPC* targetNPC = NULL;
+        PNPCWorld* currentNPCWorld = NULL;
+        currentNPCWorld = NPCManager->GetWorld( source->GetChar()->GetLocation() );
+        if ( currentNPCWorld )
+        {
+            targetNPC = currentNPCWorld->GetNPC( GetArgInt(2) );
+            if(!targetNPC)
+                return;
+            // @test 15 <npcID> <target_to_attack> <unknown uint8_t value>
+            targetNPC->Attack(GetArgInt(3), (uint8_t)GetArgInt(5), (uint8_t)GetArgInt(4));
+        }
+    }
+    else if (GetArgInt(1) == 2)
+    {
+        if(ArgC < 3)
+            return;
+
+        int tF1 = GetArgInt(2);
+        int tF2 = GetArgInt(3);
+        const PDefFaction* tFactionA = NULL;
+        const PDefFaction* tFactionB = NULL;
+
+        if(tF1 > tF2)
+        {
+            tFactionA = GameDefs->Factions()->GetDef(tF1);
+            tFactionB = GameDefs->Factions()->GetDef(tF2);
+        }
+        else
+        {
+            tFactionA = GameDefs->Factions()->GetDef(tF2);
+            tFactionB = GameDefs->Factions()->GetDef(tF1);
+        }
+
+        if(tFactionA && tFactionB)
+        {
+            int tRel = -99;
+            if(tF1 > tF2)
+                tRel = tFactionA->GetRelation(tF2);
+            else
+                tRel = tFactionA->GetRelation(tF1);
+
+            char buff[150];
+            snprintf(buff, 150, "Relation between <%s> and <%s> is: %d", tFactionA->GetName().c_str(), tFactionB->GetName().c_str(), tRel);
+            Chat->send(source, CHAT_DIRECT, "Relations", buff);
+        }
+        else
+            Chat->send(source, CHAT_DIRECT, "Relations", "Invalid faction");
+    }
 
 
 
index 4b83971..081c47c 100644 (file)
@@ -1,6 +1,6 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdunban()\r
-{\r
-    Chat->send(source, CHAT_DIRECT, "System", "Unban is not yet possible, sorry.");\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdunban()
+{
+    Chat->send(source, CHAT_DIRECT, "System", "Unban is not yet possible, sorry.");
+}
index 1754aeb..aa6ec77 100644 (file)
@@ -1,56 +1,56 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmdunshun()\r
-{\r
-    bool SyntaxError = false;\r
-    if(ArgC < 1)\r
-    {\r
-        SyntaxError = true;\r
-    }\r
-\r
-    if(SyntaxError == true)\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "Usage", "@shun <charID or nickname>");\r
-        return;\r
-    }\r
-\r
-    if(IsArgNumeric(1) == true)\r
-    {\r
-        target = GetClientByID(GetArgInt(1));\r
-    }\r
-    else\r
-    {\r
-        char tmp_destNick[50];\r
-        GetArgText(1, tmp_destNick, 50);\r
-        target = GetClientByNick(tmp_destNick);\r
-    }\r
-\r
-    if(target == NULL) // If victim isnt found, return error\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "No such player");\r
-        return;\r
-    }\r
-    if(source->GetAccountLevel() <= target->GetAccountLevel())\r
-    {\r
-        char tmpMsg[200];\r
-        snprintf(tmpMsg, 199, "Cant unshun %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());\r
-        tmpMsg[199] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);\r
-        return;\r
-    }\r
-    if(target->GetChar()->IsShunned() == true)\r
-    {\r
-        target->GetChar()->SetShun(false);\r
-\r
-        char tmpMsg_success[81];\r
-        snprintf(tmpMsg_success, 80, "Successfully unshunned %s", target->GetChar()->GetName().c_str());\r
-        tmpMsg_success[80] = '\0';\r
-        Chat->send(source, CHAT_DIRECT, "System", tmpMsg_success);\r
-        return;\r
-    }\r
-    else\r
-    {\r
-        Chat->send(source, CHAT_DIRECT, "System", "Player is not shunned");\r
-        return;\r
-    }\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmdunshun()
+{
+    bool SyntaxError = false;
+    if(ArgC < 1)
+    {
+        SyntaxError = true;
+    }
+
+    if(SyntaxError == true)
+    {
+        Chat->send(source, CHAT_DIRECT, "Usage", "@shun <charID or nickname>");
+        return;
+    }
+
+    if(IsArgNumeric(1) == true)
+    {
+        target = GetClientByID(GetArgInt(1));
+    }
+    else
+    {
+        char tmp_destNick[50];
+        GetArgText(1, tmp_destNick, 50);
+        target = GetClientByNick(tmp_destNick);
+    }
+
+    if(target == NULL) // If victim isnt found, return error
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "No such player");
+        return;
+    }
+    if(source->GetAccountLevel() <= target->GetAccountLevel())
+    {
+        char tmpMsg[200];
+        snprintf(tmpMsg, 199, "Cant unshun %s, target level is higher or equal to yours!", Chars->GetChar(target->GetCharID())->GetName().c_str());
+        tmpMsg[199] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg);
+        return;
+    }
+    if(target->GetChar()->IsShunned() == true)
+    {
+        target->GetChar()->SetShun(false);
+
+        char tmpMsg_success[81];
+        snprintf(tmpMsg_success, 80, "Successfully unshunned %s", target->GetChar()->GetName().c_str());
+        tmpMsg_success[80] = '\0';
+        Chat->send(source, CHAT_DIRECT, "System", tmpMsg_success);
+        return;
+    }
+    else
+    {
+        Chat->send(source, CHAT_DIRECT, "System", "Player is not shunned");
+        return;
+    }
+}
index 281e369..479d036 100644 (file)
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmduptime()\r
-{\r
-    // get difference between var uptime and current time\r
-    time_t Uptime = GameServer->GetStartTime();\r
-    uint32_t TimeDiff = std::time(NULL) - Uptime;\r
-    uint32_t UpYears = 0, UpMonths = 0, UpWeeks = 0, UpDays = 0, UpHours = 0, UpMinutes = 0, UpSeconds = 0;\r
-    char tmpY[21], tmpM[21], tmpW[21], tmpD[21], tmpH[21], tmpMi[21], tmpS[21];\r
-\r
-    // 1 min = 60 sec                           = 60\r
-    // 1 hour = 60 * 60 sec                     = 3600\r
-    // 1 day = 24 * 60 * 60 sec                 = 86400\r
-    // 1 week = 7 * 24 * 60 * 60 sec            = 604800\r
-    // 1 month = 30 * 7 * 24 * 60 * 60 sec      = 18144000\r
-    // 1 year = 12 * 30 * 7 * 24 * 60 * 60 sec  = 217728000\r
-\r
-    // Split Years\r
-    while(TimeDiff >= 217728000)\r
-    {\r
-        TimeDiff = TimeDiff - 217728000;\r
-        UpYears++;\r
-    }\r
-\r
-    // Split Months\r
-    while(TimeDiff >= 18144000)\r
-    {\r
-        TimeDiff = TimeDiff - 18144000;\r
-        UpMonths++;\r
-    }\r
-\r
-    // Split Weeks\r
-    while(TimeDiff >= 604800)\r
-    {\r
-        TimeDiff = TimeDiff - 604800;\r
-        UpWeeks++;\r
-    }\r
-\r
-    // Split Days\r
-    while(TimeDiff >= 86400)\r
-    {\r
-        TimeDiff = TimeDiff - 86400;\r
-        UpDays++;\r
-    }\r
-\r
-    // Split Hours\r
-    while(TimeDiff >= 3600)\r
-    {\r
-        TimeDiff = TimeDiff - 3600;\r
-        UpHours++;\r
-    }\r
-\r
-    // Split Minutes\r
-    while(TimeDiff >= 60)\r
-    {\r
-        TimeDiff = TimeDiff - 60;\r
-        UpMinutes++;\r
-    }\r
-\r
-    // What's left are seconds\r
-    UpSeconds = TimeDiff;\r
-\r
-    // Now create output strings. Add 's' if > 1\r
-    // Years\r
-    if(UpYears > 1)\r
-        snprintf(tmpY, 20, "%d years ", UpYears);\r
-    else if(UpYears > 0)\r
-        snprintf(tmpY, 20, "%d year ", UpYears);\r
-    else\r
-        tmpY[0] = '\0';\r
-\r
-    // Months\r
-    if(UpMonths > 1)\r
-        snprintf(tmpM, 20, "%d months ", UpMonths);\r
-    else if(UpMonths > 0)\r
-        snprintf(tmpM, 20, "%d month ", UpMonths);\r
-    else\r
-        tmpM[0] = '\0';\r
-\r
-    // Weeks\r
-    if(UpWeeks > 1)\r
-        snprintf(tmpW, 20, "%d weeks ", UpWeeks);\r
-    else if(UpWeeks > 0)\r
-        snprintf(tmpW, 20, "%d week ", UpWeeks);\r
-    else\r
-        tmpW[0] = '\0';\r
-\r
-    // Days\r
-    if(UpDays > 1)\r
-        snprintf(tmpD, 20, "%d days ", UpDays);\r
-    else if(UpDays > 0)\r
-        snprintf(tmpD, 20, "%d day ", UpDays);\r
-    else\r
-        tmpD[0] = '\0';\r
-\r
-    // Hours\r
-    if(UpHours > 1)\r
-        snprintf(tmpH, 20, "%d hours ", UpHours);\r
-    else if(UpHours > 0)\r
-        snprintf(tmpH, 20, "%d hour ", UpHours);\r
-    else\r
-        tmpH[0] = '\0';\r
-\r
-    // Minutes\r
-    if(UpMinutes > 1)\r
-        snprintf(tmpMi, 20, "%d minutes and ", UpMinutes);\r
-    else if(UpMinutes > 0)\r
-        snprintf(tmpMi, 20, "%d minute and ", UpMinutes);\r
-    else\r
-        tmpMi[0] = '\0';\r
-\r
-    // Seconds\r
-    if(UpSeconds > 1 || UpSeconds == 0)\r
-        snprintf(tmpS, 20, "%d seconds.", UpSeconds);\r
-    else\r
-        snprintf(tmpS, 20, "%d second.", UpSeconds);\r
-\r
-    // Terminate all chars, just to be sure\r
-    tmpY[20] = '\0';\r
-    tmpM[20] = '\0';\r
-    tmpW[20] = '\0';\r
-    tmpD[20] = '\0';\r
-    tmpH[20] = '\0';\r
-    tmpMi[20] = '\0';\r
-    tmpS[20] = '\0';\r
-\r
-    //Copy the single msg's into one\r
-    char tmpChatMsg[300];\r
-    snprintf(tmpChatMsg, 299, "The server has been running for %s%s%s%s%s%s%s", tmpY, tmpM, tmpW, tmpD, tmpH, tmpMi, tmpS);\r
-    tmpChatMsg[299] = '\0';\r
-\r
-    // Send it out\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpChatMsg);\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmduptime()
+{
+    // get difference between var uptime and current time
+    time_t Uptime = GameServer->GetStartTime();
+    uint32_t TimeDiff = std::time(NULL) - Uptime;
+    uint32_t UpYears = 0, UpMonths = 0, UpWeeks = 0, UpDays = 0, UpHours = 0, UpMinutes = 0, UpSeconds = 0;
+    char tmpY[21], tmpM[21], tmpW[21], tmpD[21], tmpH[21], tmpMi[21], tmpS[21];
+
+    // 1 min = 60 sec                           = 60
+    // 1 hour = 60 * 60 sec                     = 3600
+    // 1 day = 24 * 60 * 60 sec                 = 86400
+    // 1 week = 7 * 24 * 60 * 60 sec            = 604800
+    // 1 month = 30 * 7 * 24 * 60 * 60 sec      = 18144000
+    // 1 year = 12 * 30 * 7 * 24 * 60 * 60 sec  = 217728000
+
+    // Split Years
+    while(TimeDiff >= 217728000)
+    {
+        TimeDiff = TimeDiff - 217728000;
+        UpYears++;
+    }
+
+    // Split Months
+    while(TimeDiff >= 18144000)
+    {
+        TimeDiff = TimeDiff - 18144000;
+        UpMonths++;
+    }
+
+    // Split Weeks
+    while(TimeDiff >= 604800)
+    {
+        TimeDiff = TimeDiff - 604800;
+        UpWeeks++;
+    }
+
+    // Split Days
+    while(TimeDiff >= 86400)
+    {
+        TimeDiff = TimeDiff - 86400;
+        UpDays++;
+    }
+
+    // Split Hours
+    while(TimeDiff >= 3600)
+    {
+        TimeDiff = TimeDiff - 3600;
+        UpHours++;
+    }
+
+    // Split Minutes
+    while(TimeDiff >= 60)
+    {
+        TimeDiff = TimeDiff - 60;
+        UpMinutes++;
+    }
+
+    // What's left are seconds
+    UpSeconds = TimeDiff;
+
+    // Now create output strings. Add 's' if > 1
+    // Years
+    if(UpYears > 1)
+        snprintf(tmpY, 20, "%d years ", UpYears);
+    else if(UpYears > 0)
+        snprintf(tmpY, 20, "%d year ", UpYears);
+    else
+        tmpY[0] = '\0';
+
+    // Months
+    if(UpMonths > 1)
+        snprintf(tmpM, 20, "%d months ", UpMonths);
+    else if(UpMonths > 0)
+        snprintf(tmpM, 20, "%d month ", UpMonths);
+    else
+        tmpM[0] = '\0';
+
+    // Weeks
+    if(UpWeeks > 1)
+        snprintf(tmpW, 20, "%d weeks ", UpWeeks);
+    else if(UpWeeks > 0)
+        snprintf(tmpW, 20, "%d week ", UpWeeks);
+    else
+        tmpW[0] = '\0';
+
+    // Days
+    if(UpDays > 1)
+        snprintf(tmpD, 20, "%d days ", UpDays);
+    else if(UpDays > 0)
+        snprintf(tmpD, 20, "%d day ", UpDays);
+    else
+        tmpD[0] = '\0';
+
+    // Hours
+    if(UpHours > 1)
+        snprintf(tmpH, 20, "%d hours ", UpHours);
+    else if(UpHours > 0)
+        snprintf(tmpH, 20, "%d hour ", UpHours);
+    else
+        tmpH[0] = '\0';
+
+    // Minutes
+    if(UpMinutes > 1)
+        snprintf(tmpMi, 20, "%d minutes and ", UpMinutes);
+    else if(UpMinutes > 0)
+        snprintf(tmpMi, 20, "%d minute and ", UpMinutes);
+    else
+        tmpMi[0] = '\0';
+
+    // Seconds
+    if(UpSeconds > 1 || UpSeconds == 0)
+        snprintf(tmpS, 20, "%d seconds.", UpSeconds);
+    else
+        snprintf(tmpS, 20, "%d second.", UpSeconds);
+
+    // Terminate all chars, just to be sure
+    tmpY[20] = '\0';
+    tmpM[20] = '\0';
+    tmpW[20] = '\0';
+    tmpD[20] = '\0';
+    tmpH[20] = '\0';
+    tmpMi[20] = '\0';
+    tmpS[20] = '\0';
+
+    //Copy the single msg's into one
+    char tmpChatMsg[300];
+    snprintf(tmpChatMsg, 299, "The server has been running for %s%s%s%s%s%s%s", tmpY, tmpM, tmpW, tmpD, tmpH, tmpMi, tmpS);
+    tmpChatMsg[299] = '\0';
+
+    // Send it out
+    Chat->send(source, CHAT_DIRECT, "System", tmpChatMsg);
+}
index 4eea77b..4b375b6 100644 (file)
@@ -1,46 +1,46 @@
-#include "GameServer/Includes.hxx"\r
-\r
-void PCommands::doCmd_dev_v()\r
-{\r
-    if(IsAdmin() == false)\r
-      return;\r
-\r
-    char Arg1[30];\r
-\r
-    Arg1[0] = '\0';\r
-\r
-    if(ArgC > 0)\r
-    {\r
-        GetArgText(1, Arg1, 30);\r
-    }\r
-\r
-    char tmpStr[128];\r
-    int testmode = 1; // change here only for uint8_t/uint16_t/uint32_t testvalue use\r
-\r
-    if(Arg1[0] != '\0')\r
-    {\r
-        switch(testmode)\r
-        {\r
-            case 0: source->testval8 = (uint8_t)(atoi(Arg1) & 0xff); break;\r
-            case 1: source->testval16 = (uint16_t)(atoi(Arg1) & 0xffff); break;\r
-            case 2: source->testval32 = (uint32_t)(atoi(Arg1) & 0xffffffff); break;\r
-        }\r
-    }\r
-    else\r
-    {\r
-        source->testval8 = 0;\r
-        source->testval16 = 0;\r
-        source->testval32 = 0;\r
-    }\r
-\r
-    switch(testmode)\r
-    {\r
-        case 0: snprintf(tmpStr, 127, "Test value uint8_t set to 0x%02x (%d)", source->testval8, source->testval8); break;\r
-        case 1: snprintf(tmpStr, 127, "Test value uint16_t set to 0x%04x (%d)", source->testval16, source->testval16); break;\r
-        case 2: snprintf(tmpStr, 127, "Test value uint32_t set to 0x%08x (%d)", source->testval32, source->testval32); break;\r
-        default: tmpStr[0] = '\0';\r
-    }\r
-    tmpStr[127] = '\0';\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpStr);\r
-\r
-}\r
+#include "GameServer/Includes.hxx"
+
+void PCommands::doCmd_dev_v()
+{
+    if(IsAdmin() == false)
+      return;
+
+    char Arg1[30];
+
+    Arg1[0] = '\0';
+
+    if(ArgC > 0)
+    {
+        GetArgText(1, Arg1, 30);
+    }
+
+    char tmpStr[128];
+    int testmode = 1; // change here only for uint8_t/uint16_t/uint32_t testvalue use
+
+    if(Arg1[0] != '\0')
+    {
+        switch(testmode)
+        {
+            case 0: source->testval8 = (uint8_t)(atoi(Arg1) & 0xff); break;
+            case 1: source->testval16 = (uint16_t)(atoi(Arg1) & 0xffff); break;
+            case 2: source->testval32 = (uint32_t)(atoi(Arg1) & 0xffffffff); break;
+        }
+    }
+    else
+    {
+        source->testval8 = 0;
+        source->testval16 = 0;
+        source->testval32 = 0;
+    }
+
+    switch(testmode)
+    {
+        case 0: snprintf(tmpStr, 127, "Test value uint8_t set to 0x%02x (%d)", source->testval8, source->testval8); break;
+        case 1: snprintf(tmpStr, 127, "Test value uint16_t set to 0x%04x (%d)", source->testval16, source->testval16); break;
+        case 2: snprintf(tmpStr, 127, "Test value uint32_t set to 0x%08x (%d)", source->testval32, source->testval32); break;
+        default: tmpStr[0] = '\0';
+    }
+    tmpStr[127] = '\0';
+    Chat->send(source, CHAT_DIRECT, "System", tmpStr);
+
+}
index c694545..8b79309 100644 (file)
@@ -1,11 +1,11 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void PCommands::doCmdversion()\r
-{\r
-    char tmpChatMsg[300];\r
-    snprintf(tmpChatMsg, 299, "You are on TinNS server %s runnig version %s - SVN Rev. %s", Config->GetOption("server_name").c_str(), ServerVersion, SVNRevision);\r
-    tmpChatMsg[299] = '\0';\r
-\r
-    Chat->send(source, CHAT_DIRECT, "System", tmpChatMsg);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void PCommands::doCmdversion()
+{
+    char tmpChatMsg[300];
+    snprintf(tmpChatMsg, 299, "You are on TinNS server %s runnig version %s - SVN Rev. %s", Config->GetOption("server_name").c_str(), ServerVersion, SVNRevision);
+    tmpChatMsg[299] = '\0';
+
+    Chat->send(source, CHAT_DIRECT, "System", tmpChatMsg);
+}
index e16caa7..6cd26e7 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-#if 0\r
-PGameScript::PGameScript()\r
-{\r
-}\r
-\r
-PGameScript::~PGameScript()\r
-{\r
-    for(HookMap::iterator it = mHooks.begin(); it != mHooks.end(); it++)\r
-        delete it->second;\r
-}\r
-\r
-bool PGameScript::LoadScripts()\r
-{\r
-}\r
-\r
-bool PGameScript::Rehash()\r
-{\r
-    Console->LPrint("Rehashing GameMonkey Scripts...");\r
-    for(HookMap::iterator it = mHooks.end(); it != mHooks.begin(); it--)\r
-        mHooks.erase(it);\r
-\r
-    if(LoadScripts() == true)\r
-    {\r
-        Console->LPrint(GREEN, BLACK, "Done");\r
-        Console->LClose();\r
-        return true;\r
-    }\r
-    else\r
-    {\r
-        Console->LPrint(RED, BLACK, "Failed");\r
-        Console->LClose();\r
-        return false;\r
-    }\r
-}\r
-\r
-void PGameScript::TriggerHook(PHookTypes hook)\r
-{\r
-}\r
-\r
-\r
-bool PGameScript::ExecuteFile(const char* a_fileName)\r
-{\r
-  FILE* scriptFile = NULL;\r
-  char* fileString = NULL;\r
-  int fileSize = 0;\r
-\r
-  GM_ASSERT(m_machine);\r
-\r
-  if( !(scriptFile = fopen(a_fileName, "rb")) )\r
-  {\r
-    return false;\r
-  }\r
-\r
-  fseek(scriptFile, 0, SEEK_END);\r
-  fileSize = ftell(scriptFile);\r
-  fseek(scriptFile, 0, SEEK_SET);\r
-  fileString = new char [fileSize+1];\r
-  fread(fileString, fileSize, 1, scriptFile);\r
-  fileString[fileSize] = 0; // Terminating null\r
-  fclose(scriptFile);\r
-\r
-  int threadId = GM_INVALID_THREAD;\r
-  int errors = m_machine->ExecuteString(fileString, &threadId, true, a_fileName);\r
-  if(errors)\r
-  {\r
-    LogAnyMachineErrorMessages();\r
-  }\r
-\r
-  delete [] fileString;\r
-\r
-  return true;\r
-}\r
-\r
-\r
-int GM_CDECL PGameScript::AddHook(gmThread *a_thread)\r
-{\r
-    GM_CHECK_NUM_PARAMS(2);\r
-    GM_CHECK_STRING_PARAM(tmphooktype, 0);\r
-    GM_CHECK_STRING_PARAM(tmpfunction, 1);\r
-\r
-    mHooks.insert(std::make_pair(tmphooktype, tmpfunction));\r
-\r
-    return GM_OK;\r
-}\r
-\r
-int PGameScript::AddTwoIntegers(int valueA, int valueB)\r
-{\r
-  int resultInt = 0;\r
-\r
-  gmCall call;\r
-\r
-  if(call.BeginGlobalFunction(&machine, "Add"))\r
-  {\r
-    call.AddParamInt(valueA);\r
-    call.AddParamInt(valueB);\r
-    call.End();\r
-    call.GetReturnedInt(resultInt);\r
-  }\r
-\r
-  return resultInt;\r
-}\r
-#endif\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+#if 0
+PGameScript::PGameScript()
+{
+}
+
+PGameScript::~PGameScript()
+{
+    for(HookMap::iterator it = mHooks.begin(); it != mHooks.end(); it++)
+        delete it->second;
+}
+
+bool PGameScript::LoadScripts()
+{
+}
+
+bool PGameScript::Rehash()
+{
+    Console->LPrint("Rehashing GameMonkey Scripts...");
+    for(HookMap::iterator it = mHooks.end(); it != mHooks.begin(); it--)
+        mHooks.erase(it);
+
+    if(LoadScripts() == true)
+    {
+        Console->LPrint(GREEN, BLACK, "Done");
+        Console->LClose();
+        return true;
+    }
+    else
+    {
+        Console->LPrint(RED, BLACK, "Failed");
+        Console->LClose();
+        return false;
+    }
+}
+
+void PGameScript::TriggerHook(PHookTypes hook)
+{
+}
+
+
+bool PGameScript::ExecuteFile(const char* a_fileName)
+{
+  FILE* scriptFile = NULL;
+  char* fileString = NULL;
+  int fileSize = 0;
+
+  GM_ASSERT(m_machine);
+
+  if( !(scriptFile = fopen(a_fileName, "rb")) )
+  {
+    return false;
+  }
+
+  fseek(scriptFile, 0, SEEK_END);
+  fileSize = ftell(scriptFile);
+  fseek(scriptFile, 0, SEEK_SET);
+  fileString = new char [fileSize+1];
+  fread(fileString, fileSize, 1, scriptFile);
+  fileString[fileSize] = 0; // Terminating null
+  fclose(scriptFile);
+
+  int threadId = GM_INVALID_THREAD;
+  int errors = m_machine->ExecuteString(fileString, &threadId, true, a_fileName);
+  if(errors)
+  {
+    LogAnyMachineErrorMessages();
+  }
+
+  delete [] fileString;
+
+  return true;
+}
+
+
+int GM_CDECL PGameScript::AddHook(gmThread *a_thread)
+{
+    GM_CHECK_NUM_PARAMS(2);
+    GM_CHECK_STRING_PARAM(tmphooktype, 0);
+    GM_CHECK_STRING_PARAM(tmpfunction, 1);
+
+    mHooks.insert(std::make_pair(tmphooktype, tmpfunction));
+
+    return GM_OK;
+}
+
+int PGameScript::AddTwoIntegers(int valueA, int valueB)
+{
+  int resultInt = 0;
+
+  gmCall call;
+
+  if(call.BeginGlobalFunction(&machine, "Add"))
+  {
+    call.AddParamInt(valueA);
+    call.AddParamInt(valueB);
+    call.End();
+    call.GetReturnedInt(resultInt);
+  }
+
+  return resultInt;
+}
+#endif
index 7df8946..89831b9 100644 (file)
@@ -1,27 +1,27 @@
-#pragma once\r
-\r
-#if 0\r
-#include <map>\r
-#include <string>\r
-\r
-enum PHookTypes {\r
-    HOOK_CHAT,\r
-    HOOK_TRADE,\r
-    HOOK_ZONE\r
-};\r
-\r
-class PGameScript {\r
-private:\r
-    typedef std::map<PHookTypes, std::string> HookMap;\r
-    HookMap mHooks;\r
-\r
-public:\r
-    PGameScript();\r
-    ~PGameScript();\r
-\r
-    bool LoadScripts();\r
-    bool Rehash();\r
-    void TriggerHook(PHookTypes hook);\r
-    bool ExecuteFile(const char* a_fileName);\r
-};\r
-#endif\r
+#pragma once
+
+#if 0
+#include <map>
+#include <string>
+
+enum PHookTypes {
+    HOOK_CHAT,
+    HOOK_TRADE,
+    HOOK_ZONE
+};
+
+class PGameScript {
+private:
+    typedef std::map<PHookTypes, std::string> HookMap;
+    HookMap mHooks;
+
+public:
+    PGameScript();
+    ~PGameScript();
+
+    bool LoadScripts();
+    bool Rehash();
+    void TriggerHook(PHookTypes hook);
+    bool ExecuteFile(const char* a_fileName);
+};
+#endif
index 9fbc426..73ce9a4 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Decoder/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// TODO:\r
-// - Deny login if char is already online (More information about the login procedure is necessary to do that)\r
-// - Take main loop timeout setting from config file\r
-// - Add Regex control to new char name validation\r
-// - Add Check of Char offline (and unloaded) before deleting (from the char choosing i/f) if multiple login\r
-//   allowed for the same account\r
-//  - Check if adding to Client to Client manager shouldn't be done only one UDP connection done ?\r
-//    => Risk of sending UDP chat on non-socket ????\r
-\r
-PGameServer::PGameServer()\r
-{\r
-  mServerStartupTime = std::time( NULL );\r
-  mNumClients = 0;\r
-  MsgDecoder = new PUdpMsgDecoder();\r
-}\r
-\r
-PGameServer::~PGameServer()\r
-{\r
-  ServerSock->closeServer();\r
-  delete MsgDecoder;\r
-}\r
-\r
-void PGameServer::Start()\r
-{\r
-  uint16_t Port = Config->GetOptionInt( "gameserver_port" );\r
-  Console->LPrint( "Starting gameserver on port %i...", Port );\r
-\r
-  if ( ServerSock->open( Port ) )\r
-  {\r
-    Console->LPrint( GREEN, BLACK, "Success" );\r
-  }\r
-  else\r
-  {\r
-    Console->LPrint( RED, BLACK, "Failed" );\r
-  }\r
-  Console->LClose();\r
-  ServerSock->settimeout( 0, 10000 );\r
-\r
-  SetGameTime(( 1000 / 10 )*3600*12 ); //Set initial time to 12:00 on 7 Jul 2789\r
-\r
-  // Init random generator\r
-  struct timespec tmpTime;\r
-  if ( !clock_gettime( CLOCK_REALTIME, &tmpTime ) )\r
-  {\r
-    srandom(( uint32_t )tmpTime.tv_sec );\r
-    InitRandom( tmpTime.tv_sec );\r
-//Console->Print("Initializing random generator. First value is %d", random());\r
-  }\r
-\r
-  if ( Config->GetOptionInt( "gameserver_udpport_max" ) - Config->GetOptionInt( "gameserver_udpport_min" ) + 1 < Config->GetOptionInt( "maxclients" ) )\r
-  {\r
-    Console->Print( "%s UDP port range setting doesn't allow for the simultaneous max clients set in config", Console->ColorText( YELLOW, BLACK, "[Warning]" ) );\r
-  }\r
-\r
-}\r
-\r
-void PGameServer::SetGameTime( uint32_t newtime )\r
-{\r
-  if ( clock_gettime( CLOCK_REALTIME, &mStartTime ) )\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Clock unavailable !!!" );\r
-    perror( "clock_gettime CLOCK_REALTIME" );\r
-    mStartTime.tv_sec = 0;\r
-    mStartTime.tv_nsec = 0;\r
-  }\r
-  mBaseGameTime = newtime;\r
-}\r
-\r
-uint32_t PGameServer::GetGameTime()\r
-{\r
-  //const uint32_t TimeFactor = 375;\r
-  const uint32_t TimeFactor = 1000;\r
-  const uint32_t nsTimeFactor = 1000000000 / TimeFactor;\r
-\r
-  struct timespec tmpTime;\r
-\r
-  if ( mStartTime.tv_sec )\r
-  {\r
-    clock_gettime( CLOCK_REALTIME, &tmpTime );\r
-    return ( mBaseGameTime + (( tmpTime.tv_sec - mStartTime.tv_sec ) * TimeFactor ) + ( tmpTime.tv_nsec / nsTimeFactor ) - ( mStartTime.tv_nsec / nsTimeFactor ) );\r
-  }\r
-  else\r
-    return 0;\r
-}\r
-\r
-void PGameServer::Update()\r
-{\r
-  if ( ServerSock->newConnection() )\r
-  {\r
-    int clid = Server->NewClient();\r
-    if ( clid != -1 )\r
-    {\r
-      Console->Print( GREEN, BLACK, "[Info] Gameserver: client [%i] connected", clid );\r
-      PClient *Client = Server->GetClient( clid );\r
-      if ( Client->getTCPConn() ) Console->Print( RED, BLACK, "WARNING: Client %d : TCP Socket NOT NULL before allocation.", Client->GetID() );\r
-      ConnectionTCP* tcpConn = ServerSock->getTCPConnection();\r
-      Client->setTCPConnection( tcpConn );\r
-\r
-      //ConnectionUDP* udpConn = ServerSock->getUDPConnection();\r
-      //Client->setUDPConnection(udpConn);\r
-\r
-      Console->Print( "Client address: %s", Client->GetAddress() );\r
-      ++mNumClients;\r
-\r
-      PGameState *state = new PGameState();\r
-      ClientStates.insert( std::make_pair( Client, state ) );\r
-      state->TCP.mState = PGameState::TCP::GS_CONNECTED;\r
-\r
-      // add the new connected client to the global clientmanager for further use in chat, etc...\r
-      ClientManager->addClientToList( Client );\r
-    }\r
-    else\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Notice] Gameserver: Client connection refused (server full?)" );\r
-    }\r
-  }\r
-\r
-  /*** temp check ***/\r
-  for ( PClientMap::iterator it = ClientManager->getClientListBegin(); it != ClientManager->getClientListEnd(); it++ )\r
-  {\r
-    if ( !it->second )\r
-    {\r
-      Console->Print( RED, BLACK, "PANIC: NULL Client found in ClientManager Clients Map." );\r
-    }\r
-  }\r
-  /*** end temp check ***/\r
-\r
-  for ( GameStateMap::iterator i = ClientStates.begin(); i != ClientStates.end(); )\r
-  {\r
-    PClient *Client = i->first;\r
-    PGameState *State = i->second;\r
-    // node gets erased in FinalizeClient, increment iterator now\r
-    ++i;\r
-    if ( !ProcessClient( Client, State ) )\r
-      FinalizeClient( Client, State );\r
-  }\r
-}\r
-\r
-bool PGameServer::HandleHandshake( PGameState *State, const uint8_t *Packet, int PacketSize )\r
-{\r
-  //static const uint8_t HANDSHAKE1A[6]={0xfe, 0x03, 0x00, 0x80, 0x03, 0x68};\r
-  //PGameSocket *Socket = Client->GetGameSocket();\r
-\r
-  switch ( State->TCP.mState )\r
-  {\r
-    case PGameState::TCP::GS_HANDSHAKE0 :\r
-    {\r
-      if ( PacketSize == 6 && *( uint16_t* )&Packet[3] == 0x0080 && Packet[5] == 0x78 )\r
-      {\r
-        //FIXME: this packet seems to be unnecessary,\r
-        // although it appears in traffic dumps\r
-        // (causes clientside "Wrong protocol" errors)\r
-\r
-        //Socket->Write(HANDSHAKE1A, 6);\r
-        State->TCP.mState = PGameState::TCP::GS_AUTHENTICATE;\r
-      }\r
-      else\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Notice] Gameserver protocol error (GS_HANDSHAKE0): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-        return ( false );\r
-      }\r
-\r
-      break;\r
-    }\r
-    default:\r
-    {\r
-      break;\r
-    }\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-bool PGameServer::HandleAuthenticate( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize )\r
-{\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-  if ( PacketSize > 20 && *( uint16_t* )&Packet[3] == 0x8084 )\r
-  {\r
-    // authentication method #1\r
-    const uint8_t *Key = &Packet[5];  // password key\r
-    uint16_t ULen = *( uint16_t* ) & Packet[16];  // username length\r
-    uint16_t PLen = *( uint16_t* ) & Packet[18];  // password length\r
-    char *UserName = ( char* ) & Packet[20]; // account name\r
-    const uint8_t *PW = &Packet[20+ULen]; // encoded password\r
-\r
-    // Safety controls\r
-    if ( 15 + ULen + PLen > PacketSize )\r
-    {\r
-      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): Exessive internal size fields" );\r
-      return false;\r
-    }\r
-    if ( strnlen( UserName, ULen ) == ULen )\r
-    {\r
-      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): non-terminated username field" );\r
-      return false;\r
-    }\r
-\r
-    bool Failed = false;\r
-\r
-    PAccount Account( UserName );\r
-    if ( Account.GetID() == 0 )\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Info] Gameserver: Unknown user %s", UserName );\r
-      Failed = true;\r
-    }\r
-    else if ( !Account.Authenticate( PW, PLen, Key ) )\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Info] Gameserver: User '%s': authentication failed", UserName );\r
-      Failed = true;\r
-    }\r
-\r
-    if ( !Failed )\r
-    {\r
-      Console->Print( GREEN, BLACK, "[Info] Gameserver: User '%s' authentication successful", UserName );\r
-      if ( Account.GetLevel() == PAL_BANNED )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Info] User %s is banned, connection refused", UserName );\r
-        // TODO: ban ip for an adjustable time span?\r
-        Failed = true; // player is banned\r
-      }\r
-\r
-      if ( Account.GetLevel() == PAL_UNREGPLAYER || Account.GetLevel() == PAL_REGPLAYER )\r
-      {\r
-        if ( Server->GetNumClients() > Server->GetMaxClients() )\r
-        {\r
-          Console->Print( YELLOW, BLACK, "[Info] Server full, refusing connection from user '%s'", UserName );\r
-          Failed = true; // server full\r
-        }\r
-      }\r
-    }\r
-\r
-    if ( Failed )\r
-    {\r
-      // TODO: is this packet correct here?\r
-      uint8_t AUTHFAILED[15] = {0xfe, 0x0c, 0x00, 0x83, 0x86, 0x05, 0x00, 0x06, 0x00, 'E', 'R',\r
-                           'R', 'O', 'R', 0\r
-                          };\r
-      // TODO: send actual reason instead of ERROR\r
-      Socket->write( AUTHFAILED, 15 );\r
-      FinalizeClientDelayed( Client, State );\r
-      State->TCP.mState = PGameState::TCP::GS_UNKNOWN;\r
-      Console->Print( YELLOW, BLACK, "[Info] Gameserver: User '%s' login refused", UserName );\r
-    }\r
-    else\r
-    {\r
-      Client->LoggedIn( &Account );\r
-      uint8_t AUTHOK[28] = {0xfe, 0x19, 0x00, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\r
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
-                      };\r
-      *( uint32_t* )&AUTHOK[5] = Account.GetID();\r
-      Socket->write( AUTHOK, 28 );\r
-      State->TCP.mState = PGameState::TCP::GS_GAMEDATA;\r
-      Console->Print( GREEN, BLACK, "[Info] Gameserver: User '%s' logged in", UserName );\r
-    }\r
-  }\r
-  else if ( PacketSize > 29 && *( uint16_t* )&Packet[3] == 0x0183 )\r
-  {\r
-    // authentication method #2, sent when game starts\r
-    const uint8_t *Key = &Packet[13];  // password key\r
-    uint16_t PLen = *( uint16_t* ) & Packet[25];  // password length\r
-    uint16_t ULen = *( uint16_t* ) & Packet[27];  // username length\r
-    char *UserName = ( char* ) & Packet[29]; // account name\r
-    const uint8_t *PW = &Packet[29+ULen]; // encoded password\r
-\r
-    // Safety controls\r
-    if ( 24 + ULen + PLen > PacketSize )\r
-    {\r
-      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): Exessive internal size fields" );\r
-      return false;\r
-    }\r
-    if ( strnlen( UserName, ULen ) == ULen )\r
-    {\r
-      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): non-terminated username field" );\r
-      return false;\r
-    }\r
-\r
-    bool Failed = false;\r
-\r
-    PAccount Account( UserName );\r
-    if ( Account.GetID() == 0 )\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Info] Gameserver: Unknown user %s", UserName );\r
-      Failed = true;\r
-    }\r
-    else if ( !Account.Authenticate( PW, PLen, Key ) )\r
-    {\r
-      Console->Print( YELLOW, BLACK, "[Info] Gameserver: User '%s': authentication failed", UserName );\r
-      Failed = true;\r
-    }\r
-\r
-    if ( !Failed )\r
-    {\r
-      if ( Account.GetLevel() == PAL_BANNED )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Info] User %s is banned, connection refused", UserName );\r
-        // TODO: ban ip for an adjustable time span?\r
-        Failed = true; // player is banned\r
-      }\r
-\r
-      if ( Account.GetLevel() == PAL_UNREGPLAYER || Account.GetLevel() == PAL_REGPLAYER )\r
-      {\r
-        if ( Server->GetNumClients() > ( Server->GetMaxClients() - Server->GetGMSlots() ) )\r
-        {\r
-          Console->Print( YELLOW, BLACK, "[Info] Server full, refusing connection from regular user '%s'", UserName );\r
-          Failed = true; // server full for non-GM users\r
-        }\r
-      }\r
-      else if ( Config->GetOptionInt( "require_validation" ) == 1 && Account.GetLevel() == PAL_UNREGPLAYER )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Info] Rejecting connection from regular user '%s', account not activated yet", UserName );\r
-        Failed = true;\r
-      }\r
-      else if ( Config->GetOptionInt( "minlevel" ) > Account.GetLevel() )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Info] Rejecting connection from regular user '%s', insufficient level %d vs %d required", UserName, Account.GetLevel(), Config->GetOptionInt( "minlevel" ) );\r
-        Failed = true;\r
-      }\r
-      else if ( Server->GetNumClients() > Server->GetMaxClients() )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Info] Server full, refusing connection from privileged user '%s'", UserName );\r
-        Failed = true; // server full even for GM users\r
-      }\r
-    }\r
-\r
-\r
-    if ( !Failed )\r
-    {\r
-      int value = *( uint32_t* ) & Packet[21];//i think here we must read uint32_t instead of uint8_t\r
-      uint32_t CharID = Account.GetCharIdBySlot( value );\r
-\r
-      if ( Chars->LoadChar( CharID ) )\r
-      {\r
-        Client->SetCharID( CharID );\r
-      }\r
-      else\r
-      {\r
-        Failed = true;\r
-      }\r
-    }\r
-\r
-    if ( Failed ) // something strange happened\r
-      FinalizeClientDelayed( Client, State );\r
-    else\r
-    {\r
-      Client->LoggedIn( &Account );\r
-      /*uint8_t AUTHOK[28]={0xfe, 0x19, 0x00, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\r
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
-      *(uint32_t*)&AUTHOK[5]=Account->GetID();\r
-      Socket->Write(AUTHOK, 28);*/\r
-      //Client->SetRemoteUDPAddr(*(uint32_t*)&Packet[5], *(uint16_t*)&Packet[9]);\r
-      State->TCP.mState = PGameState::TCP::GS_GETSTATUS;\r
-      Console->Print( "Gameserver: User '%s' entered game (%08x:%04x)", UserName, *( uint32_t* )&Packet[5], *( uint16_t* )&Packet[9] );\r
-      Client->SetRemoteUDPPort( *( int* )&Packet[9] );\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-    return ( false );\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-bool PGameServer::HandleGameData( PClient *Client, PGameState *State, const uint8_t *Packet )\r
-{\r
-  static const uint8_t GAMEDATA[5] = {0xfe, 0x02, 0x00, 0x87, 0x3a};\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-  if ( *( uint16_t* )&Packet[3] == 0x3787 )\r
-  {\r
-    Socket->write( GAMEDATA, 5 );\r
-    State->TCP.mState = PGameState::TCP::GS_REQUESTCHARS;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_GAMEDATA): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-    return ( false );\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-bool PGameServer::HandleRequestChars( PClient *Client, PGameState *State, const uint8_t *Packet )\r
-{\r
-  PAccount Account( Client->GetAccountID() );\r
-\r
-  if ( !Account.GetID() )\r
-    return false;\r
-\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-  struct PCharList\r
-  {\r
-    uint16_t Unknown1;\r
-    uint16_t NumSlots;\r
-    uint16_t Unknown2;\r
-  } CharList;\r
-\r
-  PCharProfile CharEntry[MAX_CHARS_PER_ACCOUNT];\r
-\r
-  const int CHARBASESIZE = 28;\r
-\r
-  if ( *( uint16_t* )&Packet[3] == 0x8284 )\r
-  {\r
-    CharList.NumSlots = MAX_CHARS_PER_ACCOUNT;\r
-    int NameLengths = 0;\r
-\r
-    for ( int i = 0; i < MAX_CHARS_PER_ACCOUNT; i++ )\r
-    {\r
-      CharEntry[i].CharID = 0;\r
-      CharEntry[i].Type = 0;\r
-      CharEntry[i].Color0 = 0;\r
-      CharEntry[i].Location = 1;\r
-      CharEntry[i].Unknown1 = 0;\r
-      CharEntry[i].Head = 0;\r
-      CharEntry[i].Torso = 0;\r
-      CharEntry[i].Legs = 0;\r
-      CharEntry[i].Unknown3 = 1;\r
-      CharEntry[i].Unknown4 = 1;\r
-      CharEntry[i].Unknown5 = 1;\r
-      CharEntry[i].Unknown6 = 1;\r
-      CharEntry[i].Unknown7 = 1;\r
-      CharEntry[i].Unknown8 = 0;\r
-      CharEntry[i].Unknown9 = 0;\r
-      CharEntry[i].Unknown10 = 0;\r
-      CharEntry[i].Unknown11 = 0;\r
-      CharEntry[i].Unknown12 = 0;\r
-\r
-      CharEntry[i].in_use = false;\r
-    }\r
-\r
-    Chars->GetCharProfiles( Account.GetID(), CharEntry, MAX_CHARS_PER_ACCOUNT );\r
-\r
-    for ( int i = 0; i < MAX_CHARS_PER_ACCOUNT; i++ )\r
-    {\r
-      if ( CharEntry[i].in_use )\r
-      {\r
-        NameLengths += CharEntry[i].NameLen;\r
-      }\r
-      else\r
-      {\r
-        CharEntry[i].CharID = 0xffffffff;\r
-        CharEntry[i].NameLen = 0;\r
-      }\r
-    }\r
-\r
-    uint8_t PacketHeader[5] = {0xfe, 0x00, 0x00, 0x83, 0x85};\r
-    *( uint16_t* )&PacketHeader[1] = sizeof( uint16_t ) * 3 + ( MAX_CHARS_PER_ACCOUNT * CHARBASESIZE ) + NameLengths + 2;\r
-    Socket->write( PacketHeader, 5 );\r
-\r
-    CharList.Unknown1 = 0x0000;\r
-    CharList.Unknown2 = CHARBASESIZE;\r
-    Socket->write( CharList.Unknown1 );\r
-    Socket->write( CharList.NumSlots );\r
-    Socket->write( CharList.Unknown2 );\r
-\r
-    for ( int i = 0; i < MAX_CHARS_PER_ACCOUNT; i++ )\r
-    {\r
-      Socket->write( CharEntry[i].CharID );\r
-      Socket->write( CharEntry[i].Type );\r
-      Socket->write( CharEntry[i].Color0 );\r
-      Socket->write( CharEntry[i].Unknown1 );\r
-      Socket->write( CharEntry[i].Head );\r
-      Socket->write( CharEntry[i].Torso );\r
-      Socket->write( CharEntry[i].Legs );\r
-      Socket->write( CharEntry[i].Location );\r
-      Socket->write( CharEntry[i].NameLen );\r
-      Socket->write( CharEntry[i].Unknown3 );\r
-      Socket->write( CharEntry[i].Unknown4 );\r
-      Socket->write( CharEntry[i].Unknown5 );\r
-      Socket->write( CharEntry[i].Unknown6 );\r
-      Socket->write( CharEntry[i].Unknown7 );\r
-      Socket->write( CharEntry[i].Unknown8 );\r
-      Socket->write( CharEntry[i].Unknown9 );\r
-      Socket->write( CharEntry[i].Unknown10 );\r
-      Socket->write( CharEntry[i].Unknown11 );\r
-      Socket->write( CharEntry[i].Unknown12 );\r
-\r
-      if ( CharEntry[i].Name.length() > 0 )\r
-      {\r
-        Socket->write( CharEntry[i].Name.c_str() );\r
-        Socket->write(( uint8_t )0 );\r
-      }\r
-    }\r
-\r
-    State->TCP.mState = PGameState::TCP::GS_CHARLIST;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "Gameserver protocol error (GS_REQUESTCHARS): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-    return ( false );\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-bool PGameServer::HandleCharList( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize )\r
-{\r
-  static uint8_t Answer[10] = {0xfe, 0x07, 0x00, 0x83, 0x86, 0, 0, 0, 0, 0};\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-  if ( PacketSize > 9 && *( uint16_t* )&Packet[3] == 0x8284 )\r
-  {\r
-    uint8_t Mode = Packet[9];\r
-\r
-    switch ( Mode )\r
-    {\r
-      case 6: // request list\r
-        return ( HandleRequestChars( Client, State, Packet ) );\r
-\r
-      case 5: // validate name\r
-      {\r
-        if ( PacketSize < 31 )\r
-          return ( false );\r
-\r
-        // check for valid name string\r
-        bool ValidString = false;\r
-\r
-        for ( int i = 30; i < PacketSize; i++ )\r
-          if ( Packet[i] == 0 )\r
-          {\r
-            ValidString = true;\r
-            break;\r
-          }\r
-\r
-        const char *Name = ( char* ) & Packet[30];\r
-        if ( ValidString )\r
-        {\r
-          ValidString = PChar::IsCharnameWellFormed( Name );\r
-        }\r
-\r
-        if ( ValidString )\r
-        {\r
-          if ( Chars->CharExist( std::string( Name ) ) )\r
-          {\r
-            ValidString = false;\r
-          }\r
-        }\r
-\r
-        if ( ValidString )\r
-          Answer[5] = 1; // ok\r
-        else\r
-          Answer[5] = 2; // 2..6 => 'char name already in use!'\r
-\r
-        // Answer[5] = 0; // => 'unknown error'\r
-        Socket->write( Answer, 10 );\r
-        return ( true );\r
-      }\r
-\r
-      case 3: // delete char\r
-      {\r
-        PAccount Acc( Client->GetAccountID() );\r
-        uint8_t Num = Packet[PacketSize-1];\r
-\r
-        if ( Acc.GetID() )\r
-        {\r
-          uint32_t CharID = Acc.GetCharIdBySlot( Num );\r
-\r
-          // Also check that char is out of game\r
-          if (( CharID != 0 ) && ( Chars->GetChar( CharID ) == NULL ) )\r
-          {\r
-            char query[100];\r
-            snprintf( query, 100, "DELETE FROM characters WHERE c_id = %d LIMIT 1", CharID );\r
-            if ( MySQL->GameQuery( query ) )\r
-              Console->Print( RED, BLACK, "[Notice] Char %d not deleted!", CharID );\r
-            else\r
-            {\r
-              Console->Print( GREEN, BLACK, "[Info] Char %d deleted!", CharID );\r
-\r
-              snprintf( query, 100, "DELETE FROM buddy_list WHERE bud_charid = %d", CharID );\r
-              if ( MySQL->GameQuery( query ) )\r
-                Console->Print( YELLOW, BLACK, "[Notice] Char %d's buddy list not removed!", CharID );\r
-\r
-              snprintf( query, 100, "DELETE FROM genrep WHERE g_charid = %d", CharID );\r
-              if ( MySQL->GameQuery( query ) )\r
-                Console->Print( YELLOW, BLACK, "[Notice] Char %d's genrep list not removed!", CharID );\r
-\r
-              snprintf( query, 100, "DELETE FROM inventory WHERE inv_charid = %d", CharID );\r
-              if ( MySQL->GameQuery( query ) )\r
-                Console->Print( YELLOW, BLACK, "[Notice] Char %d's inventory not removed!", CharID );\r
-\r
-              Appartements->DeleteCharAppartements( CharID );\r
-            }\r
-          }\r
-          else\r
-            return false;\r
-        }\r
-        return ( true );\r
-      }\r
-\r
-      case 7: // create char\r
-      {\r
-        if ( PacketSize < 64 )\r
-          return ( false );\r
-\r
-        uint32_t Slot = * ( uint32_t* ) & Packet[30];\r
-        //uint32_t nClass =* (uint32_t*)&Packet[34]; // Not used - indirectly redundant with Profession\r
-        uint32_t Profession = * ( uint32_t* ) & Packet[38];\r
-        uint32_t Gender = * ( uint32_t* ) & Packet[42];\r
-        uint32_t Head = * ( uint32_t* ) & Packet[46];\r
-        uint32_t Torso = * ( uint32_t* ) & Packet[50];\r
-        uint32_t Legs = * ( uint32_t* ) & Packet[54];\r
-        uint32_t Faction = * ( uint32_t* ) & Packet[58];\r
-        uint8_t NameLen = Packet[62];\r
-        uint8_t NZSNb = Packet[63];\r
-\r
-        char TempName[256];\r
-        std::strncpy( TempName, ( const char* )&Packet[64], NameLen );\r
-        TempName[NameLen] = 0;\r
-\r
-        Answer[5] = 2; // return error if char creation fails\r
-\r
-        if ( PChar::IsCharnameWellFormed( TempName ) )\r
-        {\r
-          // check for already used char name - should not happen though\r
-          if ( ! Chars->CharExist( std::string( TempName ) ) )\r
-          {\r
-            PAccount Acc( Client->GetAccountID() );\r
-            PChar* nChar = new PChar();\r
-\r
-            if ( nChar->CreateNewChar( Acc.GetID(), TempName, Gender, Profession, Faction,\r
-                                       Head, Torso, Legs, NZSNb, ( const char* )&Packet[64+NameLen], Slot ) )\r
-            {\r
-              Answer[5] = 1; // return success\r
-            }\r
-            delete nChar;\r
-          }\r
-        }\r
-\r
-        Socket->write( Answer, 10 );\r
-        return ( true );\r
-      }\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_CHARLIST): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-\r
-    return ( false );\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-bool PGameServer::HandleGetStatus( PClient *Client, PGameState *State, const uint8_t *Packet )\r
-{\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-  if ( *( uint16_t* )&Packet[3] == 0x3787 )\r
-  {\r
-    static const uint8_t STATUS[9] = {0xfe, 0x06, 0x00, 0x87, 0x3a, 0x11, 0x00, 0x00, 0x00};\r
-\r
-    Socket->write( STATUS, 9 );\r
-    State->TCP.mState = PGameState::TCP::GS_GAMEINFO;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_GETSTATUS): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-\r
-    return ( false );\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-bool PGameServer::HandleGameInfo( PClient *Client, PGameState *State, const uint8_t *Packet )\r
-{\r
-// Console->Print("Inside HandleGameInfo");//NEW added\r
-\r
-  static uint8_t GameInfo[31] = {0xfe, 0x1c, 0x00, 0x83, 0x05, // header\r
-                            0x00, 0x00, 0x00, 0x00, // account id\r
-                            0x00, 0x00, 0x00, 0x00, // char id\r
-                            0x00, 0x00, 0x00, 0x00, // udp ip\r
-                            0x00, 0x00,   // udp port\r
-                            0x00, 0x00, 0x00, 0x00, // unknown\r
-                            0x00, 0x00, 0x00, 0x00,\r
-                            0x00, 0x00, 0x00, 0x00, // session key\r
-                           };\r
-\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-  if ( *( uint16_t* )&Packet[3] == 0x3c87 )\r
-  {\r
-    //int PortFix = Config->GetOptionInt("debug_mode");\r
-\r
-    ConnectionUDP* udpConn = ServerSock->getUDPConnection( IPStringToDWord( Client->GetAddress() ), Client->GetRemoteUDPPort() );\r
-    Client->setUDPConnection( udpConn );\r
-    if ( !udpConn )\r
-    {\r
-      Console->Print( RED, BLACK, "Client %d: UDP port setup failed", Client->GetID() );\r
-      ClientDisconnected( Client );\r
-    }\r
-\r
-    uint16_t Port = Client->getUDPConn()->getPort();\r
-\r
-    if ( Port == 0 )\r
-      Console->Print( RED, BLACK, "Client->OpenUDP() failed" );\r
-\r
-\r
-    /* if(PortFix == 1) // removed, no more use\r
-    {\r
-     Port = Config->GetOptionInt("useudpport");\r
-     Console->Print(YELLOW, BLACK, "UDP Port set to non-standard for debugging!");\r
-    }; */\r
-\r
-    uint32_t IP;\r
-    std::string IPServerString;\r
-// use [server_nat_ip] for server if client is NOT on [no_nat_net] (and [no_nat_net]!=0)\r
-    if ( strcmp( Config->GetOption( "no_nat_net" ).c_str(), "0" ) && strncmp( Client->GetAddress(), Config->GetOption( "no_nat_net" ).c_str(), strlen( Config->GetOption( "no_nat_net" ).c_str() ) ) )\r
-    {\r
-      IPServerString = Config->GetOption( "server_nat_ip" );\r
-    }\r
-    else // else client is "local" so use [server_ip]\r
-    {\r
-      IPServerString = Config->GetOption( "server_ip" );\r
-    }\r
-    IP = IPStringToDWord( IPServerString.c_str() );\r
-//Console->Print("IP-1 %d", IP);\r
-    if ( IP == 0 )\r
-      IP = 0x0100007f;\r
-//Console->Print("IP-2 %d", IP);\r
-    *( uint32_t* )&GameInfo[13] = IP;\r
-    *( uint16_t* )&GameInfo[17] = Port;\r
-    Console->Print( GREEN, BLACK, "[Info] Using UDP %s:%d on server", IPServerString.c_str(), Port );\r
-\r
-    *( uint32_t* )&GameInfo[5] = Client->GetAccountID();\r
-    *( uint32_t* )&GameInfo[9] = Client->GetCharID();\r
-    Console->Print( GREEN, BLACK, "[Info] Serving char id :%d", Client->GetCharID() );\r
-\r
-    Socket->write( GameInfo, 31 );\r
-    Socket->flushSendBuffer();\r
-\r
-    static const uint8_t READY[7] = {0xfe, 0x04, 0x00, 0x83, 0x0d, 0x00, 0x00};\r
-    Socket->write( READY, 7 );\r
-\r
-    State->TCP.mState = PGameState::TCP::GS_INGAME;\r
-    State->UDP.mState = PGameState::UDP::GUS_SYNC0;\r
-//Console->Print("Sync Reset");\r
-    Client->ResetTransactionID();\r
-\r
-    // Mark char as Online\r
-    PChar *Char = Client->GetChar();\r
-    Char->SetOnlineStatus( true ); //Also using this info to check if Char may have to be saved at client disconnect\r
-    Client->ChangeCharLocation( Char->GetLocation(), true );\r
-\r
-    // hello-message from server..\r
-    /*\r
-    std::string serverName = Config->GetOption("server_name");\r
-    std::string helloMessage = "Welcome to " + serverName + " - A TinNS Neocron Server.";\r
-    char* message = (char*) helloMessage.c_str();\r
-    Chat->send(Client, CHAT_DIRECT, "System", message, false);\r
-    */\r
-\r
-    bool SendBC = false;\r
-    if ( Config->GetOptionInt( "broadcast_new" ) == 1 )\r
-    {\r
-      if ( Config->GetOptionInt( "broadcast_new_hidestaff" ) == 1 )\r
-      {\r
-        if ( Client->GetAccountLevel() > PAL_REGPLAYER )\r
-          SendBC = false;\r
-        else\r
-          SendBC = true;\r
-      }\r
-      else\r
-      {\r
-        SendBC = true;\r
-      }\r
-    }\r
-    if ( SendBC == true )\r
-    {\r
-      std::string playerName = Chars->GetChar( Client->GetCharID() )->GetName();\r
-      std::string serverName = Config->GetOption( "server_name" );\r
-      std::string helloMessage = "Hello " + playerName + "! Welcome to " + serverName + " - A TinNS Neocron Server.";\r
-      char* message = ( char* ) helloMessage.c_str();\r
-\r
-      Chat->sendOOCBroadcast( message );\r
-    }\r
-    //Console->Print("UDP Setup: %s", nlGetErrorStr(nlGetError()));\r
-  }\r
-  else\r
-  {\r
-    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_GAMEINFO): invalid packet [%04x]", *( uint16_t* )&Packet[3] );\r
-    return ( false );\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-bool PGameServer::HandleGame( PClient *Client, PGameState *State )\r
-{\r
-  //PGameSocket *Socket = Client->GetGameSocket();\r
-  ConnectionUDP *UDPSocket = Client->getUDPConn();\r
-  //Console->Print("Clientadress %s", Client->GetAddress());\r
-\r
-  //int Size = 0;\r
-  PMessage* NewMsg = UDPSocket->GetMessage();\r
-  if ( NewMsg && NewMsg->GetSize() )\r
-  {\r
-\r
-    MsgDecoder->Init( NewMsg, Client, State ); // State used temporarily\r
-    do\r
-    {\r
-      if ( MsgDecoder->Analyse() )\r
-      {\r
-        if ( gDevDebug && MsgDecoder->IsTraceKnownMsg() )\r
-          Console->Print( "%s Client[%d] msg: %s", Console->ColorText( GREEN, BLACK, "[Debug]" ), Client->GetID(), MsgDecoder->GetName().c_str() );\r
-\r
-        if ( MsgDecoder->IsActionReady() )\r
-        {\r
-          MsgDecoder->DoAction();\r
-        }\r
-      }\r
-      else if ( MsgDecoder->IsError() )\r
-      {\r
-        Console->Print( YELLOW, BLACK, "[Info] Client[%d] Decoding error: %s", Client->GetID(), MsgDecoder->GetError().c_str() );\r
-      }\r
-//      else if (MsgDecoder->GetState() == DECODE_UNKNOWN)\r
-      else if ( gDevDebug && ( MsgDecoder->GetState() == DECODE_UNKNOWN ) && MsgDecoder->IsTraceUnknownMsg() )\r
-      {\r
-        Console->Print( "%s Client[%d] Unknown msg: %s", Console->ColorText( YELLOW, BLACK, "[Info]" ), Client->GetID(), MsgDecoder->GetName().c_str() );\r
-      }\r
-\r
-//      if (MsgDecoder->IsTraceDump())\r
-      if ( gDevDebug && MsgDecoder->IsTraceDump() )\r
-      {\r
-        MsgDecoder->DumpMsg();\r
-      }\r
-\r
-    }\r
-    while ( MsgDecoder->MoreSubMsg() );\r
-  }\r
-\r
-  if ( NewMsg )\r
-  {\r
-    delete NewMsg;\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-bool PGameServer::ProcessClient( PClient *Client, PGameState *State )\r
-{\r
-  static const uint8_t HANDSHAKE0A[6] = {0xfe, 0x03, 0x00, 0x80, 0x01, 0x66};\r
-\r
-  if ( !State )\r
-  {\r
-    GameStateMap::iterator node = ClientStates.find( Client );\r
-    if ( node == ClientStates.end() )\r
-      return ( false );\r
-\r
-    State = node->second;\r
-  }\r
-\r
-  ConnectionTCP *Socket = Client->getTCPConn();\r
-  if ( !Socket ) Console->Print( RED, BLACK, "PANIC: Client %d : TCP Socket is NULL !!!", Client->GetID() );\r
-  if ( State->TCP.mWaitSend && Socket->getSendBufferSize() == 0 )\r
-    return ( false );\r
-\r
-  if ( State->TCP.mState == PGameState::TCP::GS_CONNECTED )\r
-  {\r
-    Socket->write( HANDSHAKE0A, 6 );\r
-    State->TCP.mState = PGameState::TCP::GS_HANDSHAKE0;\r
-  }\r
-\r
-  if ( State->TCP.mState == PGameState::TCP::GS_INGAME )\r
-  {\r
-    return ( HandleGame( Client, State ) );\r
-  }\r
-  else\r
-  {\r
-    int PacketSize = 0;\r
-    const uint8_t *Packet = Socket->read( &PacketSize );\r
-\r
-    if ( PacketSize > 0 )\r
-    {\r
-      switch ( State->TCP.mState )\r
-      {\r
-        case PGameState::TCP::GS_HANDSHAKE0:\r
-          return ( HandleHandshake( State, Packet, PacketSize ) );\r
-\r
-        case PGameState::TCP::GS_AUTHENTICATE:\r
-          return ( HandleAuthenticate( Client, State, Packet, PacketSize ) );\r
-\r
-        case PGameState::TCP::GS_GAMEDATA:\r
-          return ( HandleGameData( Client, State, Packet ) );\r
-\r
-        case PGameState::TCP::GS_REQUESTCHARS:\r
-          return ( HandleRequestChars( Client, State, Packet ) );\r
-\r
-        case PGameState::TCP::GS_CHARLIST:\r
-          return ( HandleCharList( Client, State, Packet, PacketSize ) );\r
-\r
-        case PGameState::TCP::GS_GETSTATUS:\r
-          return ( HandleGetStatus( Client, State, Packet ) );\r
-\r
-        case PGameState::TCP::GS_GAMEINFO:\r
-          return ( HandleGameInfo( Client, State, Packet ) );\r
-        default:\r
-          break;\r
-      }\r
-    }\r
-  }\r
-\r
-  return ( true );\r
-}\r
-\r
-void PGameServer::ClientDisconnected( PClient *Client )\r
-{\r
-  GameStateMap::iterator node = ClientStates.find( Client );\r
-\r
-  if ( node == ClientStates.end() )\r
-    return;\r
-\r
-  PGameState *State = node->second;\r
-  FinalizeClient( Client, State );\r
-}\r
-\r
-void PGameServer::UDPStreamClosed( PClient *Client )\r
-{\r
-  GameStateMap::iterator node = ClientStates.find( Client );\r
-\r
-  if ( node == ClientStates.end() )\r
-    return;\r
-\r
-  PGameState *State = node->second;\r
-  FinalizeClient( Client, State );\r
-}\r
-\r
-void PGameServer::FinalizeClient( PClient *Client, PGameState *State )\r
-{\r
-  Console->Print( GREEN, BLACK, "[Info] Gameserver: client %s disconnected", Client->GetAddress() );\r
-\r
-  // Isnt working somehow. I assume that mID and mAccount is deleted already.\r
-  // Mark char as Offline\r
-  //PChar *Char = Chars->GetChar(Client->GetCharID());\r
-  //Char->SetOnlineStatus(false);\r
-\r
-  // delete client from clientmanager list => Do it before we remove network access\r
-  ClientManager->deleteClientFromList( Client->GetLocalID() );\r
-\r
-  Client->GameDisconnect();\r
-  ClientStates.erase( Client );\r
-  delete State;\r
-  --mNumClients;\r
-\r
-}\r
-\r
-void PGameServer::FinalizeClientDelayed( PClient *Client, PGameState *State )\r
-{\r
-  Console->Print( GREEN, BLACK, "[Info] Gameserver: client %s is about to be disconnected", Client->GetAddress() );\r
-  State->TCP.mWaitSend = true;\r
-}\r
-\r
-PGameState* PGameServer::GetClientState( PClient* nClient )\r
-{\r
-  GameStateMap::iterator node = ClientStates.find( nClient );\r
-\r
-  if ( node == ClientStates.end() )\r
-    return NULL;\r
-  else\r
-    return node->second;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "GameServer/Decoder/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// TODO:
+// - Deny login if char is already online (More information about the login procedure is necessary to do that)
+// - Take main loop timeout setting from config file
+// - Add Regex control to new char name validation
+// - Add Check of Char offline (and unloaded) before deleting (from the char choosing i/f) if multiple login
+//   allowed for the same account
+//  - Check if adding to Client to Client manager shouldn't be done only one UDP connection done ?
+//    => Risk of sending UDP chat on non-socket ????
+
+PGameServer::PGameServer()
+{
+  mServerStartupTime = std::time( NULL );
+  mNumClients = 0;
+  MsgDecoder = new PUdpMsgDecoder();
+}
+
+PGameServer::~PGameServer()
+{
+  ServerSock->closeServer();
+  delete MsgDecoder;
+}
+
+void PGameServer::Start()
+{
+  uint16_t Port = Config->GetOptionInt( "gameserver_port" );
+  Console->LPrint( "Starting gameserver on port %i...", Port );
+
+  if ( ServerSock->open( Port ) )
+  {
+    Console->LPrint( GREEN, BLACK, "Success" );
+  }
+  else
+  {
+    Console->LPrint( RED, BLACK, "Failed" );
+  }
+  Console->LClose();
+  ServerSock->settimeout( 0, 10000 );
+
+  SetGameTime(( 1000 / 10 )*3600*12 ); //Set initial time to 12:00 on 7 Jul 2789
+
+  // Init random generator
+  struct timespec tmpTime;
+  if ( !clock_gettime( CLOCK_REALTIME, &tmpTime ) )
+  {
+    srandom(( uint32_t )tmpTime.tv_sec );
+    InitRandom( tmpTime.tv_sec );
+//Console->Print("Initializing random generator. First value is %d", random());
+  }
+
+  if ( Config->GetOptionInt( "gameserver_udpport_max" ) - Config->GetOptionInt( "gameserver_udpport_min" ) + 1 < Config->GetOptionInt( "maxclients" ) )
+  {
+    Console->Print( "%s UDP port range setting doesn't allow for the simultaneous max clients set in config", Console->ColorText( YELLOW, BLACK, "[Warning]" ) );
+  }
+
+}
+
+void PGameServer::SetGameTime( uint32_t newtime )
+{
+  if ( clock_gettime( CLOCK_REALTIME, &mStartTime ) )
+  {
+    Console->Print( RED, BLACK, "[ERROR] Clock unavailable !!!" );
+    perror( "clock_gettime CLOCK_REALTIME" );
+    mStartTime.tv_sec = 0;
+    mStartTime.tv_nsec = 0;
+  }
+  mBaseGameTime = newtime;
+}
+
+uint32_t PGameServer::GetGameTime()
+{
+  //const uint32_t TimeFactor = 375;
+  const uint32_t TimeFactor = 1000;
+  const uint32_t nsTimeFactor = 1000000000 / TimeFactor;
+
+  struct timespec tmpTime;
+
+  if ( mStartTime.tv_sec )
+  {
+    clock_gettime( CLOCK_REALTIME, &tmpTime );
+    return ( mBaseGameTime + (( tmpTime.tv_sec - mStartTime.tv_sec ) * TimeFactor ) + ( tmpTime.tv_nsec / nsTimeFactor ) - ( mStartTime.tv_nsec / nsTimeFactor ) );
+  }
+  else
+    return 0;
+}
+
+void PGameServer::Update()
+{
+  if ( ServerSock->newConnection() )
+  {
+    int clid = Server->NewClient();
+    if ( clid != -1 )
+    {
+      Console->Print( GREEN, BLACK, "[Info] Gameserver: client [%i] connected", clid );
+      PClient *Client = Server->GetClient( clid );
+      if ( Client->getTCPConn() ) Console->Print( RED, BLACK, "WARNING: Client %d : TCP Socket NOT NULL before allocation.", Client->GetID() );
+      ConnectionTCP* tcpConn = ServerSock->getTCPConnection();
+      Client->setTCPConnection( tcpConn );
+
+      //ConnectionUDP* udpConn = ServerSock->getUDPConnection();
+      //Client->setUDPConnection(udpConn);
+
+      Console->Print( "Client address: %s", Client->GetAddress() );
+      ++mNumClients;
+
+      PGameState *state = new PGameState();
+      ClientStates.insert( std::make_pair( Client, state ) );
+      state->TCP.mState = PGameState::TCP::GS_CONNECTED;
+
+      // add the new connected client to the global clientmanager for further use in chat, etc...
+      ClientManager->addClientToList( Client );
+    }
+    else
+    {
+      Console->Print( YELLOW, BLACK, "[Notice] Gameserver: Client connection refused (server full?)" );
+    }
+  }
+
+  /*** temp check ***/
+  for ( PClientMap::iterator it = ClientManager->getClientListBegin(); it != ClientManager->getClientListEnd(); it++ )
+  {
+    if ( !it->second )
+    {
+      Console->Print( RED, BLACK, "PANIC: NULL Client found in ClientManager Clients Map." );
+    }
+  }
+  /*** end temp check ***/
+
+  for ( GameStateMap::iterator i = ClientStates.begin(); i != ClientStates.end(); )
+  {
+    PClient *Client = i->first;
+    PGameState *State = i->second;
+    // node gets erased in FinalizeClient, increment iterator now
+    ++i;
+    if ( !ProcessClient( Client, State ) )
+      FinalizeClient( Client, State );
+  }
+}
+
+bool PGameServer::HandleHandshake( PGameState *State, const uint8_t *Packet, int PacketSize )
+{
+  //static const uint8_t HANDSHAKE1A[6]={0xfe, 0x03, 0x00, 0x80, 0x03, 0x68};
+  //PGameSocket *Socket = Client->GetGameSocket();
+
+  switch ( State->TCP.mState )
+  {
+    case PGameState::TCP::GS_HANDSHAKE0 :
+    {
+      if ( PacketSize == 6 && *( uint16_t* )&Packet[3] == 0x0080 && Packet[5] == 0x78 )
+      {
+        //FIXME: this packet seems to be unnecessary,
+        // although it appears in traffic dumps
+        // (causes clientside "Wrong protocol" errors)
+
+        //Socket->Write(HANDSHAKE1A, 6);
+        State->TCP.mState = PGameState::TCP::GS_AUTHENTICATE;
+      }
+      else
+      {
+        Console->Print( YELLOW, BLACK, "[Notice] Gameserver protocol error (GS_HANDSHAKE0): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+        return ( false );
+      }
+
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  return true;
+}
+
+bool PGameServer::HandleAuthenticate( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize )
+{
+  ConnectionTCP *Socket = Client->getTCPConn();
+
+  if ( PacketSize > 20 && *( uint16_t* )&Packet[3] == 0x8084 )
+  {
+    // authentication method #1
+    const uint8_t *Key = &Packet[5];  // password key
+    uint16_t ULen = *( uint16_t* ) & Packet[16];  // username length
+    uint16_t PLen = *( uint16_t* ) & Packet[18];  // password length
+    char *UserName = ( char* ) & Packet[20]; // account name
+    const uint8_t *PW = &Packet[20+ULen]; // encoded password
+
+    // Safety controls
+    if ( 15 + ULen + PLen > PacketSize )
+    {
+      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): Exessive internal size fields" );
+      return false;
+    }
+    if ( strnlen( UserName, ULen ) == ULen )
+    {
+      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): non-terminated username field" );
+      return false;
+    }
+
+    bool Failed = false;
+
+    PAccount Account( UserName );
+    if ( Account.GetID() == 0 )
+    {
+      Console->Print( YELLOW, BLACK, "[Info] Gameserver: Unknown user %s", UserName );
+      Failed = true;
+    }
+    else if ( !Account.Authenticate( PW, PLen, Key ) )
+    {
+      Console->Print( YELLOW, BLACK, "[Info] Gameserver: User '%s': authentication failed", UserName );
+      Failed = true;
+    }
+
+    if ( !Failed )
+    {
+      Console->Print( GREEN, BLACK, "[Info] Gameserver: User '%s' authentication successful", UserName );
+      if ( Account.GetLevel() == PAL_BANNED )
+      {
+        Console->Print( YELLOW, BLACK, "[Info] User %s is banned, connection refused", UserName );
+        // TODO: ban ip for an adjustable time span?
+        Failed = true; // player is banned
+      }
+
+      if ( Account.GetLevel() == PAL_UNREGPLAYER || Account.GetLevel() == PAL_REGPLAYER )
+      {
+        if ( Server->GetNumClients() > Server->GetMaxClients() )
+        {
+          Console->Print( YELLOW, BLACK, "[Info] Server full, refusing connection from user '%s'", UserName );
+          Failed = true; // server full
+        }
+      }
+    }
+
+    if ( Failed )
+    {
+      // TODO: is this packet correct here?
+      uint8_t AUTHFAILED[15] = {0xfe, 0x0c, 0x00, 0x83, 0x86, 0x05, 0x00, 0x06, 0x00, 'E', 'R',
+                           'R', 'O', 'R', 0
+                          };
+      // TODO: send actual reason instead of ERROR
+      Socket->write( AUTHFAILED, 15 );
+      FinalizeClientDelayed( Client, State );
+      State->TCP.mState = PGameState::TCP::GS_UNKNOWN;
+      Console->Print( YELLOW, BLACK, "[Info] Gameserver: User '%s' login refused", UserName );
+    }
+    else
+    {
+      Client->LoggedIn( &Account );
+      uint8_t AUTHOK[28] = {0xfe, 0x19, 0x00, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+                      };
+      *( uint32_t* )&AUTHOK[5] = Account.GetID();
+      Socket->write( AUTHOK, 28 );
+      State->TCP.mState = PGameState::TCP::GS_GAMEDATA;
+      Console->Print( GREEN, BLACK, "[Info] Gameserver: User '%s' logged in", UserName );
+    }
+  }
+  else if ( PacketSize > 29 && *( uint16_t* )&Packet[3] == 0x0183 )
+  {
+    // authentication method #2, sent when game starts
+    const uint8_t *Key = &Packet[13];  // password key
+    uint16_t PLen = *( uint16_t* ) & Packet[25];  // password length
+    uint16_t ULen = *( uint16_t* ) & Packet[27];  // username length
+    char *UserName = ( char* ) & Packet[29]; // account name
+    const uint8_t *PW = &Packet[29+ULen]; // encoded password
+
+    // Safety controls
+    if ( 24 + ULen + PLen > PacketSize )
+    {
+      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): Exessive internal size fields" );
+      return false;
+    }
+    if ( strnlen( UserName, ULen ) == ULen )
+    {
+      Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): non-terminated username field" );
+      return false;
+    }
+
+    bool Failed = false;
+
+    PAccount Account( UserName );
+    if ( Account.GetID() == 0 )
+    {
+      Console->Print( YELLOW, BLACK, "[Info] Gameserver: Unknown user %s", UserName );
+      Failed = true;
+    }
+    else if ( !Account.Authenticate( PW, PLen, Key ) )
+    {
+      Console->Print( YELLOW, BLACK, "[Info] Gameserver: User '%s': authentication failed", UserName );
+      Failed = true;
+    }
+
+    if ( !Failed )
+    {
+      if ( Account.GetLevel() == PAL_BANNED )
+      {
+        Console->Print( YELLOW, BLACK, "[Info] User %s is banned, connection refused", UserName );
+        // TODO: ban ip for an adjustable time span?
+        Failed = true; // player is banned
+      }
+
+      if ( Account.GetLevel() == PAL_UNREGPLAYER || Account.GetLevel() == PAL_REGPLAYER )
+      {
+        if ( Server->GetNumClients() > ( Server->GetMaxClients() - Server->GetGMSlots() ) )
+        {
+          Console->Print( YELLOW, BLACK, "[Info] Server full, refusing connection from regular user '%s'", UserName );
+          Failed = true; // server full for non-GM users
+        }
+      }
+      else if ( Config->GetOptionInt( "require_validation" ) == 1 && Account.GetLevel() == PAL_UNREGPLAYER )
+      {
+        Console->Print( YELLOW, BLACK, "[Info] Rejecting connection from regular user '%s', account not activated yet", UserName );
+        Failed = true;
+      }
+      else if ( Config->GetOptionInt( "minlevel" ) > Account.GetLevel() )
+      {
+        Console->Print( YELLOW, BLACK, "[Info] Rejecting connection from regular user '%s', insufficient level %d vs %d required", UserName, Account.GetLevel(), Config->GetOptionInt( "minlevel" ) );
+        Failed = true;
+      }
+      else if ( Server->GetNumClients() > Server->GetMaxClients() )
+      {
+        Console->Print( YELLOW, BLACK, "[Info] Server full, refusing connection from privileged user '%s'", UserName );
+        Failed = true; // server full even for GM users
+      }
+    }
+
+
+    if ( !Failed )
+    {
+      int value = *( uint32_t* ) & Packet[21];//i think here we must read uint32_t instead of uint8_t
+      uint32_t CharID = Account.GetCharIdBySlot( value );
+
+      if ( Chars->LoadChar( CharID ) )
+      {
+        Client->SetCharID( CharID );
+      }
+      else
+      {
+        Failed = true;
+      }
+    }
+
+    if ( Failed ) // something strange happened
+      FinalizeClientDelayed( Client, State );
+    else
+    {
+      Client->LoggedIn( &Account );
+      /*uint8_t AUTHOK[28]={0xfe, 0x19, 0x00, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+      *(uint32_t*)&AUTHOK[5]=Account->GetID();
+      Socket->Write(AUTHOK, 28);*/
+      //Client->SetRemoteUDPAddr(*(uint32_t*)&Packet[5], *(uint16_t*)&Packet[9]);
+      State->TCP.mState = PGameState::TCP::GS_GETSTATUS;
+      Console->Print( "Gameserver: User '%s' entered game (%08x:%04x)", UserName, *( uint32_t* )&Packet[5], *( uint16_t* )&Packet[9] );
+      Client->SetRemoteUDPPort( *( int* )&Packet[9] );
+    }
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_AUTHENTICATE): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+    return ( false );
+  }
+
+  return ( true );
+}
+
+bool PGameServer::HandleGameData( PClient *Client, PGameState *State, const uint8_t *Packet )
+{
+  static const uint8_t GAMEDATA[5] = {0xfe, 0x02, 0x00, 0x87, 0x3a};
+  ConnectionTCP *Socket = Client->getTCPConn();
+
+  if ( *( uint16_t* )&Packet[3] == 0x3787 )
+  {
+    Socket->write( GAMEDATA, 5 );
+    State->TCP.mState = PGameState::TCP::GS_REQUESTCHARS;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_GAMEDATA): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+    return ( false );
+  }
+
+  return ( true );
+}
+
+bool PGameServer::HandleRequestChars( PClient *Client, PGameState *State, const uint8_t *Packet )
+{
+  PAccount Account( Client->GetAccountID() );
+
+  if ( !Account.GetID() )
+    return false;
+
+  ConnectionTCP *Socket = Client->getTCPConn();
+
+  struct PCharList
+  {
+    uint16_t Unknown1;
+    uint16_t NumSlots;
+    uint16_t Unknown2;
+  } CharList;
+
+  PCharProfile CharEntry[MAX_CHARS_PER_ACCOUNT];
+
+  const int CHARBASESIZE = 28;
+
+  if ( *( uint16_t* )&Packet[3] == 0x8284 )
+  {
+    CharList.NumSlots = MAX_CHARS_PER_ACCOUNT;
+    int NameLengths = 0;
+
+    for ( int i = 0; i < MAX_CHARS_PER_ACCOUNT; i++ )
+    {
+      CharEntry[i].CharID = 0;
+      CharEntry[i].Type = 0;
+      CharEntry[i].Color0 = 0;
+      CharEntry[i].Location = 1;
+      CharEntry[i].Unknown1 = 0;
+      CharEntry[i].Head = 0;
+      CharEntry[i].Torso = 0;
+      CharEntry[i].Legs = 0;
+      CharEntry[i].Unknown3 = 1;
+      CharEntry[i].Unknown4 = 1;
+      CharEntry[i].Unknown5 = 1;
+      CharEntry[i].Unknown6 = 1;
+      CharEntry[i].Unknown7 = 1;
+      CharEntry[i].Unknown8 = 0;
+      CharEntry[i].Unknown9 = 0;
+      CharEntry[i].Unknown10 = 0;
+      CharEntry[i].Unknown11 = 0;
+      CharEntry[i].Unknown12 = 0;
+
+      CharEntry[i].in_use = false;
+    }
+
+    Chars->GetCharProfiles( Account.GetID(), CharEntry, MAX_CHARS_PER_ACCOUNT );
+
+    for ( int i = 0; i < MAX_CHARS_PER_ACCOUNT; i++ )
+    {
+      if ( CharEntry[i].in_use )
+      {
+        NameLengths += CharEntry[i].NameLen;
+      }
+      else
+      {
+        CharEntry[i].CharID = 0xffffffff;
+        CharEntry[i].NameLen = 0;
+      }
+    }
+
+    uint8_t PacketHeader[5] = {0xfe, 0x00, 0x00, 0x83, 0x85};
+    *( uint16_t* )&PacketHeader[1] = sizeof( uint16_t ) * 3 + ( MAX_CHARS_PER_ACCOUNT * CHARBASESIZE ) + NameLengths + 2;
+    Socket->write( PacketHeader, 5 );
+
+    CharList.Unknown1 = 0x0000;
+    CharList.Unknown2 = CHARBASESIZE;
+    Socket->write( CharList.Unknown1 );
+    Socket->write( CharList.NumSlots );
+    Socket->write( CharList.Unknown2 );
+
+    for ( int i = 0; i < MAX_CHARS_PER_ACCOUNT; i++ )
+    {
+      Socket->write( CharEntry[i].CharID );
+      Socket->write( CharEntry[i].Type );
+      Socket->write( CharEntry[i].Color0 );
+      Socket->write( CharEntry[i].Unknown1 );
+      Socket->write( CharEntry[i].Head );
+      Socket->write( CharEntry[i].Torso );
+      Socket->write( CharEntry[i].Legs );
+      Socket->write( CharEntry[i].Location );
+      Socket->write( CharEntry[i].NameLen );
+      Socket->write( CharEntry[i].Unknown3 );
+      Socket->write( CharEntry[i].Unknown4 );
+      Socket->write( CharEntry[i].Unknown5 );
+      Socket->write( CharEntry[i].Unknown6 );
+      Socket->write( CharEntry[i].Unknown7 );
+      Socket->write( CharEntry[i].Unknown8 );
+      Socket->write( CharEntry[i].Unknown9 );
+      Socket->write( CharEntry[i].Unknown10 );
+      Socket->write( CharEntry[i].Unknown11 );
+      Socket->write( CharEntry[i].Unknown12 );
+
+      if ( CharEntry[i].Name.length() > 0 )
+      {
+        Socket->write( CharEntry[i].Name.c_str() );
+        Socket->write(( uint8_t )0 );
+      }
+    }
+
+    State->TCP.mState = PGameState::TCP::GS_CHARLIST;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "Gameserver protocol error (GS_REQUESTCHARS): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+    return ( false );
+  }
+
+  return ( true );
+}
+
+bool PGameServer::HandleCharList( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize )
+{
+  static uint8_t Answer[10] = {0xfe, 0x07, 0x00, 0x83, 0x86, 0, 0, 0, 0, 0};
+  ConnectionTCP *Socket = Client->getTCPConn();
+
+  if ( PacketSize > 9 && *( uint16_t* )&Packet[3] == 0x8284 )
+  {
+    uint8_t Mode = Packet[9];
+
+    switch ( Mode )
+    {
+      case 6: // request list
+        return ( HandleRequestChars( Client, State, Packet ) );
+
+      case 5: // validate name
+      {
+        if ( PacketSize < 31 )
+          return ( false );
+
+        // check for valid name string
+        bool ValidString = false;
+
+        for ( int i = 30; i < PacketSize; i++ )
+          if ( Packet[i] == 0 )
+          {
+            ValidString = true;
+            break;
+          }
+
+        const char *Name = ( char* ) & Packet[30];
+        if ( ValidString )
+        {
+          ValidString = PChar::IsCharnameWellFormed( Name );
+        }
+
+        if ( ValidString )
+        {
+          if ( Chars->CharExist( std::string( Name ) ) )
+          {
+            ValidString = false;
+          }
+        }
+
+        if ( ValidString )
+          Answer[5] = 1; // ok
+        else
+          Answer[5] = 2; // 2..6 => 'char name already in use!'
+
+        // Answer[5] = 0; // => 'unknown error'
+        Socket->write( Answer, 10 );
+        return ( true );
+      }
+
+      case 3: // delete char
+      {
+        PAccount Acc( Client->GetAccountID() );
+        uint8_t Num = Packet[PacketSize-1];
+
+        if ( Acc.GetID() )
+        {
+          uint32_t CharID = Acc.GetCharIdBySlot( Num );
+
+          // Also check that char is out of game
+          if (( CharID != 0 ) && ( Chars->GetChar( CharID ) == NULL ) )
+          {
+            char query[100];
+            snprintf( query, 100, "DELETE FROM characters WHERE c_id = %d LIMIT 1", CharID );
+            if ( MySQL->GameQuery( query ) )
+              Console->Print( RED, BLACK, "[Notice] Char %d not deleted!", CharID );
+            else
+            {
+              Console->Print( GREEN, BLACK, "[Info] Char %d deleted!", CharID );
+
+              snprintf( query, 100, "DELETE FROM buddy_list WHERE bud_charid = %d", CharID );
+              if ( MySQL->GameQuery( query ) )
+                Console->Print( YELLOW, BLACK, "[Notice] Char %d's buddy list not removed!", CharID );
+
+              snprintf( query, 100, "DELETE FROM genrep WHERE g_charid = %d", CharID );
+              if ( MySQL->GameQuery( query ) )
+                Console->Print( YELLOW, BLACK, "[Notice] Char %d's genrep list not removed!", CharID );
+
+              snprintf( query, 100, "DELETE FROM inventory WHERE inv_charid = %d", CharID );
+              if ( MySQL->GameQuery( query ) )
+                Console->Print( YELLOW, BLACK, "[Notice] Char %d's inventory not removed!", CharID );
+
+              Appartements->DeleteCharAppartements( CharID );
+            }
+          }
+          else
+            return false;
+        }
+        return ( true );
+      }
+
+      case 7: // create char
+      {
+        if ( PacketSize < 64 )
+          return ( false );
+
+        uint32_t Slot = * ( uint32_t* ) & Packet[30];
+        //uint32_t nClass =* (uint32_t*)&Packet[34]; // Not used - indirectly redundant with Profession
+        uint32_t Profession = * ( uint32_t* ) & Packet[38];
+        uint32_t Gender = * ( uint32_t* ) & Packet[42];
+        uint32_t Head = * ( uint32_t* ) & Packet[46];
+        uint32_t Torso = * ( uint32_t* ) & Packet[50];
+        uint32_t Legs = * ( uint32_t* ) & Packet[54];
+        uint32_t Faction = * ( uint32_t* ) & Packet[58];
+        uint8_t NameLen = Packet[62];
+        uint8_t NZSNb = Packet[63];
+
+        char TempName[256];
+        std::strncpy( TempName, ( const char* )&Packet[64], NameLen );
+        TempName[NameLen] = 0;
+
+        Answer[5] = 2; // return error if char creation fails
+
+        if ( PChar::IsCharnameWellFormed( TempName ) )
+        {
+          // check for already used char name - should not happen though
+          if ( ! Chars->CharExist( std::string( TempName ) ) )
+          {
+            PAccount Acc( Client->GetAccountID() );
+            PChar* nChar = new PChar();
+
+            if ( nChar->CreateNewChar( Acc.GetID(), TempName, Gender, Profession, Faction,
+                                       Head, Torso, Legs, NZSNb, ( const char* )&Packet[64+NameLen], Slot ) )
+            {
+              Answer[5] = 1; // return success
+            }
+            delete nChar;
+          }
+        }
+
+        Socket->write( Answer, 10 );
+        return ( true );
+      }
+    }
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_CHARLIST): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+
+    return ( false );
+  }
+
+  return true;
+}
+
+bool PGameServer::HandleGetStatus( PClient *Client, PGameState *State, const uint8_t *Packet )
+{
+  ConnectionTCP *Socket = Client->getTCPConn();
+
+  if ( *( uint16_t* )&Packet[3] == 0x3787 )
+  {
+    static const uint8_t STATUS[9] = {0xfe, 0x06, 0x00, 0x87, 0x3a, 0x11, 0x00, 0x00, 0x00};
+
+    Socket->write( STATUS, 9 );
+    State->TCP.mState = PGameState::TCP::GS_GAMEINFO;
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_GETSTATUS): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+
+    return ( false );
+  }
+
+  return ( true );
+}
+
+bool PGameServer::HandleGameInfo( PClient *Client, PGameState *State, const uint8_t *Packet )
+{
+// Console->Print("Inside HandleGameInfo");//NEW added
+
+  static uint8_t GameInfo[31] = {0xfe, 0x1c, 0x00, 0x83, 0x05, // header
+                            0x00, 0x00, 0x00, 0x00, // account id
+                            0x00, 0x00, 0x00, 0x00, // char id
+                            0x00, 0x00, 0x00, 0x00, // udp ip
+                            0x00, 0x00,   // udp port
+                            0x00, 0x00, 0x00, 0x00, // unknown
+                            0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00, // session key
+                           };
+
+  ConnectionTCP *Socket = Client->getTCPConn();
+
+  if ( *( uint16_t* )&Packet[3] == 0x3c87 )
+  {
+    //int PortFix = Config->GetOptionInt("debug_mode");
+
+    ConnectionUDP* udpConn = ServerSock->getUDPConnection( IPStringToDWord( Client->GetAddress() ), Client->GetRemoteUDPPort() );
+    Client->setUDPConnection( udpConn );
+    if ( !udpConn )
+    {
+      Console->Print( RED, BLACK, "Client %d: UDP port setup failed", Client->GetID() );
+      ClientDisconnected( Client );
+    }
+
+    uint16_t Port = Client->getUDPConn()->getPort();
+
+    if ( Port == 0 )
+      Console->Print( RED, BLACK, "Client->OpenUDP() failed" );
+
+
+    /* if(PortFix == 1) // removed, no more use
+    {
+     Port = Config->GetOptionInt("useudpport");
+     Console->Print(YELLOW, BLACK, "UDP Port set to non-standard for debugging!");
+    }; */
+
+    uint32_t IP;
+    std::string IPServerString;
+// use [server_nat_ip] for server if client is NOT on [no_nat_net] (and [no_nat_net]!=0)
+    if ( strcmp( Config->GetOption( "no_nat_net" ).c_str(), "0" ) && strncmp( Client->GetAddress(), Config->GetOption( "no_nat_net" ).c_str(), strlen( Config->GetOption( "no_nat_net" ).c_str() ) ) )
+    {
+      IPServerString = Config->GetOption( "server_nat_ip" );
+    }
+    else // else client is "local" so use [server_ip]
+    {
+      IPServerString = Config->GetOption( "server_ip" );
+    }
+    IP = IPStringToDWord( IPServerString.c_str() );
+//Console->Print("IP-1 %d", IP);
+    if ( IP == 0 )
+      IP = 0x0100007f;
+//Console->Print("IP-2 %d", IP);
+    *( uint32_t* )&GameInfo[13] = IP;
+    *( uint16_t* )&GameInfo[17] = Port;
+    Console->Print( GREEN, BLACK, "[Info] Using UDP %s:%d on server", IPServerString.c_str(), Port );
+
+    *( uint32_t* )&GameInfo[5] = Client->GetAccountID();
+    *( uint32_t* )&GameInfo[9] = Client->GetCharID();
+    Console->Print( GREEN, BLACK, "[Info] Serving char id :%d", Client->GetCharID() );
+
+    Socket->write( GameInfo, 31 );
+    Socket->flushSendBuffer();
+
+    static const uint8_t READY[7] = {0xfe, 0x04, 0x00, 0x83, 0x0d, 0x00, 0x00};
+    Socket->write( READY, 7 );
+
+    State->TCP.mState = PGameState::TCP::GS_INGAME;
+    State->UDP.mState = PGameState::UDP::GUS_SYNC0;
+//Console->Print("Sync Reset");
+    Client->ResetTransactionID();
+
+    // Mark char as Online
+    PChar *Char = Client->GetChar();
+    Char->SetOnlineStatus( true ); //Also using this info to check if Char may have to be saved at client disconnect
+    Client->ChangeCharLocation( Char->GetLocation(), true );
+
+    // hello-message from server..
+    /*
+    std::string serverName = Config->GetOption("server_name");
+    std::string helloMessage = "Welcome to " + serverName + " - A TinNS Neocron Server.";
+    char* message = (char*) helloMessage.c_str();
+    Chat->send(Client, CHAT_DIRECT, "System", message, false);
+    */
+
+    bool SendBC = false;
+    if ( Config->GetOptionInt( "broadcast_new" ) == 1 )
+    {
+      if ( Config->GetOptionInt( "broadcast_new_hidestaff" ) == 1 )
+      {
+        if ( Client->GetAccountLevel() > PAL_REGPLAYER )
+          SendBC = false;
+        else
+          SendBC = true;
+      }
+      else
+      {
+        SendBC = true;
+      }
+    }
+    if ( SendBC == true )
+    {
+      std::string playerName = Chars->GetChar( Client->GetCharID() )->GetName();
+      std::string serverName = Config->GetOption( "server_name" );
+      std::string helloMessage = "Hello " + playerName + "! Welcome to " + serverName + " - A TinNS Neocron Server.";
+      char* message = ( char* ) helloMessage.c_str();
+
+      Chat->sendOOCBroadcast( message );
+    }
+    //Console->Print("UDP Setup: %s", nlGetErrorStr(nlGetError()));
+  }
+  else
+  {
+    Console->Print( RED, BLACK, "[Notice] Gameserver protocol error (GS_GAMEINFO): invalid packet [%04x]", *( uint16_t* )&Packet[3] );
+    return ( false );
+  }
+
+  return ( true );
+}
+
+bool PGameServer::HandleGame( PClient *Client, PGameState *State )
+{
+  //PGameSocket *Socket = Client->GetGameSocket();
+  ConnectionUDP *UDPSocket = Client->getUDPConn();
+  //Console->Print("Clientadress %s", Client->GetAddress());
+
+  //int Size = 0;
+  PMessage* NewMsg = UDPSocket->GetMessage();
+  if ( NewMsg && NewMsg->GetSize() )
+  {
+
+    MsgDecoder->Init( NewMsg, Client, State ); // State used temporarily
+    do
+    {
+      if ( MsgDecoder->Analyse() )
+      {
+        if ( gDevDebug && MsgDecoder->IsTraceKnownMsg() )
+          Console->Print( "%s Client[%d] msg: %s", Console->ColorText( GREEN, BLACK, "[Debug]" ), Client->GetID(), MsgDecoder->GetName().c_str() );
+
+        if ( MsgDecoder->IsActionReady() )
+        {
+          MsgDecoder->DoAction();
+        }
+      }
+      else if ( MsgDecoder->IsError() )
+      {
+        Console->Print( YELLOW, BLACK, "[Info] Client[%d] Decoding error: %s", Client->GetID(), MsgDecoder->GetError().c_str() );
+      }
+//      else if (MsgDecoder->GetState() == DECODE_UNKNOWN)
+      else if ( gDevDebug && ( MsgDecoder->GetState() == DECODE_UNKNOWN ) && MsgDecoder->IsTraceUnknownMsg() )
+      {
+        Console->Print( "%s Client[%d] Unknown msg: %s", Console->ColorText( YELLOW, BLACK, "[Info]" ), Client->GetID(), MsgDecoder->GetName().c_str() );
+      }
+
+//      if (MsgDecoder->IsTraceDump())
+      if ( gDevDebug && MsgDecoder->IsTraceDump() )
+      {
+        MsgDecoder->DumpMsg();
+      }
+
+    }
+    while ( MsgDecoder->MoreSubMsg() );
+  }
+
+  if ( NewMsg )
+  {
+    delete NewMsg;
+  }
+
+  return ( true );
+}
+
+bool PGameServer::ProcessClient( PClient *Client, PGameState *State )
+{
+  static const uint8_t HANDSHAKE0A[6] = {0xfe, 0x03, 0x00, 0x80, 0x01, 0x66};
+
+  if ( !State )
+  {
+    GameStateMap::iterator node = ClientStates.find( Client );
+    if ( node == ClientStates.end() )
+      return ( false );
+
+    State = node->second;
+  }
+
+  ConnectionTCP *Socket = Client->getTCPConn();
+  if ( !Socket ) Console->Print( RED, BLACK, "PANIC: Client %d : TCP Socket is NULL !!!", Client->GetID() );
+  if ( State->TCP.mWaitSend && Socket->getSendBufferSize() == 0 )
+    return ( false );
+
+  if ( State->TCP.mState == PGameState::TCP::GS_CONNECTED )
+  {
+    Socket->write( HANDSHAKE0A, 6 );
+    State->TCP.mState = PGameState::TCP::GS_HANDSHAKE0;
+  }
+
+  if ( State->TCP.mState == PGameState::TCP::GS_INGAME )
+  {
+    return ( HandleGame( Client, State ) );
+  }
+  else
+  {
+    int PacketSize = 0;
+    const uint8_t *Packet = Socket->read( &PacketSize );
+
+    if ( PacketSize > 0 )
+    {
+      switch ( State->TCP.mState )
+      {
+        case PGameState::TCP::GS_HANDSHAKE0:
+          return ( HandleHandshake( State, Packet, PacketSize ) );
+
+        case PGameState::TCP::GS_AUTHENTICATE:
+          return ( HandleAuthenticate( Client, State, Packet, PacketSize ) );
+
+        case PGameState::TCP::GS_GAMEDATA:
+          return ( HandleGameData( Client, State, Packet ) );
+
+        case PGameState::TCP::GS_REQUESTCHARS:
+          return ( HandleRequestChars( Client, State, Packet ) );
+
+        case PGameState::TCP::GS_CHARLIST:
+          return ( HandleCharList( Client, State, Packet, PacketSize ) );
+
+        case PGameState::TCP::GS_GETSTATUS:
+          return ( HandleGetStatus( Client, State, Packet ) );
+
+        case PGameState::TCP::GS_GAMEINFO:
+          return ( HandleGameInfo( Client, State, Packet ) );
+        default:
+          break;
+      }
+    }
+  }
+
+  return ( true );
+}
+
+void PGameServer::ClientDisconnected( PClient *Client )
+{
+  GameStateMap::iterator node = ClientStates.find( Client );
+
+  if ( node == ClientStates.end() )
+    return;
+
+  PGameState *State = node->second;
+  FinalizeClient( Client, State );
+}
+
+void PGameServer::UDPStreamClosed( PClient *Client )
+{
+  GameStateMap::iterator node = ClientStates.find( Client );
+
+  if ( node == ClientStates.end() )
+    return;
+
+  PGameState *State = node->second;
+  FinalizeClient( Client, State );
+}
+
+void PGameServer::FinalizeClient( PClient *Client, PGameState *State )
+{
+  Console->Print( GREEN, BLACK, "[Info] Gameserver: client %s disconnected", Client->GetAddress() );
+
+  // Isnt working somehow. I assume that mID and mAccount is deleted already.
+  // Mark char as Offline
+  //PChar *Char = Chars->GetChar(Client->GetCharID());
+  //Char->SetOnlineStatus(false);
+
+  // delete client from clientmanager list => Do it before we remove network access
+  ClientManager->deleteClientFromList( Client->GetLocalID() );
+
+  Client->GameDisconnect();
+  ClientStates.erase( Client );
+  delete State;
+  --mNumClients;
+
+}
+
+void PGameServer::FinalizeClientDelayed( PClient *Client, PGameState *State )
+{
+  Console->Print( GREEN, BLACK, "[Info] Gameserver: client %s is about to be disconnected", Client->GetAddress() );
+  State->TCP.mWaitSend = true;
+}
+
+PGameState* PGameServer::GetClientState( PClient* nClient )
+{
+  GameStateMap::iterator node = ClientStates.find( nClient );
+
+  if ( node == ClientStates.end() )
+    return NULL;
+  else
+    return node->second;
+}
index 177c1da..47c93a5 100644 (file)
-#pragma once\r
-\r
-#include <chrono>\r
-#include <cstdint>\r
-#include <map>\r
-\r
-struct PGameState\r
-{\r
-  struct TCP\r
-  {\r
-    enum State\r
-    {\r
-      GS_UNKNOWN,\r
-      GS_CONNECTED,\r
-      GS_HANDSHAKE0,\r
-      GS_AUTHENTICATE,\r
-      GS_GAMEDATA,\r
-      GS_REQUESTCHARS,\r
-      GS_CHARLIST,\r
-      GS_GETSTATUS,\r
-      GS_GAMEINFO,\r
-      GS_INGAME\r
-    } mState;\r
-\r
-    bool mWaitSend; // wait-for-completition flag\r
-  } TCP;\r
-\r
-  struct UDP\r
-  {\r
-    enum State\r
-    {\r
-      GUS_UNKNOWN,\r
-      GUS_SYNC0,\r
-      GUS_SYNC1,\r
-      GUS_SYNC2,\r
-      GUS_SYNC3\r
-    } mState;\r
-\r
-    bool mSynced;\r
-    uint16_t mServerPacketNum;\r
-    uint16_t mSequence;\r
-    //uint16_t mClientPacketNum;\r
-  } UDP;\r
-\r
-  PGameState()\r
-  {\r
-    TCP.mState = TCP::GS_UNKNOWN;\r
-    TCP.mWaitSend = false;\r
-\r
-    UDP.mState = UDP::GUS_UNKNOWN;\r
-    UDP.mSynced = false;\r
-    UDP.mServerPacketNum = 0x9c9f;\r
-    UDP.mSequence = 2;\r
-    //UDP.mClientPacketNum = 0;\r
-  };\r
-};\r
-\r
-class PUdpMsgDecoder;\r
-\r
-class PGameServer\r
-{\r
-  private :\r
-    time_t mServerStartupTime;\r
-    int mNumClients;\r
-    uint32_t mBaseGameTime;\r
-    struct timespec mStartTime;\r
-\r
-    typedef std::map<PClient*, struct PGameState*> GameStateMap;\r
-    GameStateMap ClientStates;\r
-    PUdpMsgDecoder* MsgDecoder;\r
-\r
-  protected :\r
-    bool ProcessClient( PClient *Client, PGameState *State = 0 );\r
-    void FinalizeClient( PClient *Client, PGameState *State );\r
-    void FinalizeClientDelayed( PClient *Client, PGameState *State );\r
-\r
-//  bool HandleHandshake(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);\r
-    bool HandleHandshake( PGameState *State, const uint8_t *Packet, int PacketSize );\r
-\r
-    bool HandleAuthenticate( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize );\r
-//  bool HandleGameData(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);\r
-    bool HandleGameData( PClient *Client, PGameState *State, const uint8_t *Packet );\r
-\r
-//  bool HandleRequestChars(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);\r
-    bool HandleRequestChars( PClient *Client, PGameState *State, const uint8_t *Packet );\r
-\r
-    bool HandleCharList( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize );\r
-//  bool HandleGetStatus(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);\r
-    bool HandleGetStatus( PClient *Client, PGameState *State, const uint8_t *Packet );\r
-\r
-//  bool HandleGameInfo(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);\r
-    bool HandleGameInfo( PClient *Client, PGameState *State, const uint8_t *Packet );\r
-\r
-    bool HandleGame( PClient *Client, PGameState *State );\r
-\r
-  public :\r
-    PGameServer();\r
-    ~PGameServer();\r
-\r
-    void Start();\r
-    void Update();\r
-    void ClientDisconnected( PClient *Client );\r
-    void UDPStreamClosed( PClient *Client );\r
-    void SetGameTime( uint32_t newtime );\r
-    uint32_t GetGameTime();\r
-\r
-    inline time_t GetStartTime() const { return mServerStartupTime; };\r
-\r
-    PGameState* GetClientState( PClient* nClient );\r
-};\r
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#include <map>
+
+struct PGameState
+{
+  struct TCP
+  {
+    enum State
+    {
+      GS_UNKNOWN,
+      GS_CONNECTED,
+      GS_HANDSHAKE0,
+      GS_AUTHENTICATE,
+      GS_GAMEDATA,
+      GS_REQUESTCHARS,
+      GS_CHARLIST,
+      GS_GETSTATUS,
+      GS_GAMEINFO,
+      GS_INGAME
+    } mState;
+
+    bool mWaitSend; // wait-for-completition flag
+  } TCP;
+
+  struct UDP
+  {
+    enum State
+    {
+      GUS_UNKNOWN,
+      GUS_SYNC0,
+      GUS_SYNC1,
+      GUS_SYNC2,
+      GUS_SYNC3
+    } mState;
+
+    bool mSynced;
+    uint16_t mServerPacketNum;
+    uint16_t mSequence;
+    //uint16_t mClientPacketNum;
+  } UDP;
+
+  PGameState()
+  {
+    TCP.mState = TCP::GS_UNKNOWN;
+    TCP.mWaitSend = false;
+
+    UDP.mState = UDP::GUS_UNKNOWN;
+    UDP.mSynced = false;
+    UDP.mServerPacketNum = 0x9c9f;
+    UDP.mSequence = 2;
+    //UDP.mClientPacketNum = 0;
+  };
+};
+
+class PUdpMsgDecoder;
+
+class PGameServer
+{
+  private :
+    time_t mServerStartupTime;
+    int mNumClients;
+    uint32_t mBaseGameTime;
+    struct timespec mStartTime;
+
+    typedef std::map<PClient*, struct PGameState*> GameStateMap;
+    GameStateMap ClientStates;
+    PUdpMsgDecoder* MsgDecoder;
+
+  protected :
+    bool ProcessClient( PClient *Client, PGameState *State = 0 );
+    void FinalizeClient( PClient *Client, PGameState *State );
+    void FinalizeClientDelayed( PClient *Client, PGameState *State );
+
+//  bool HandleHandshake(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);
+    bool HandleHandshake( PGameState *State, const uint8_t *Packet, int PacketSize );
+
+    bool HandleAuthenticate( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize );
+//  bool HandleGameData(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);
+    bool HandleGameData( PClient *Client, PGameState *State, const uint8_t *Packet );
+
+//  bool HandleRequestChars(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);
+    bool HandleRequestChars( PClient *Client, PGameState *State, const uint8_t *Packet );
+
+    bool HandleCharList( PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize );
+//  bool HandleGetStatus(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);
+    bool HandleGetStatus( PClient *Client, PGameState *State, const uint8_t *Packet );
+
+//  bool HandleGameInfo(PClient *Client, PGameState *State, const uint8_t *Packet, int PacketSize);
+    bool HandleGameInfo( PClient *Client, PGameState *State, const uint8_t *Packet );
+
+    bool HandleGame( PClient *Client, PGameState *State );
+
+  public :
+    PGameServer();
+    ~PGameServer();
+
+    void Start();
+    void Update();
+    void ClientDisconnected( PClient *Client );
+    void UDPStreamClosed( PClient *Client );
+    void SetGameTime( uint32_t newtime );
+    uint32_t GetGameTime();
+
+    inline time_t GetStartTime() const { return mServerStartupTime; };
+
+    PGameState* GetClientState( PClient* nClient );
+};
index 743d979..85cb220 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PGenrepList::PGenrepList(uint32_t nOwnerCharID)\r
-{\r
-    mOwnerCharID = nOwnerCharID;\r
-    mListMaxSize = mListSize = 0;\r
-    mGenrepList = NULL;\r
-}\r
-\r
-PGenrepList::~PGenrepList()\r
-{\r
-    if (mGenrepList)\r
-        delete[] mGenrepList;\r
-}\r
-\r
-bool PGenrepList::AddGenrep(uint16_t nWorldID, uint16_t nStationID)\r
-{\r
-    char query[256];\r
-\r
-    if ((FindEntry(nWorldID, nStationID) >= mListSize) && (mListSize < 255))\r
-    {\r
-        if (mListSize == mListMaxSize)\r
-        {\r
-            IncreaseMaxSize();\r
-        }\r
-        mGenrepList[mListSize].mWorldID = nWorldID;\r
-        mGenrepList[mListSize++].mStationID = nStationID;\r
-\r
-        snprintf(query, 256, "INSERT INTO genrep (g_id,g_worldid,g_stationid,g_charid) VALUES (NULL,'%u','%u','%u');", nWorldID, nStationID, mOwnerCharID);\r
-        if ( MySQL->GameQuery(query) )\r
-        {\r
-            Console->Print(RED, BLACK, "PGenrepList::AddGenrep could not add some genrep entry in the database");\r
-            Console->Print("Query was:");\r
-            Console->Print("%s", query);\r
-            MySQL->ShowGameSQLError();\r
-            return false;\r
-        }\r
-\r
-        return true;\r
-    }\r
-    else\r
-        return false;\r
-}\r
-\r
-/*bool PGenrepList::RemoveChar(uint32_t nBuddyCharID)\r
-{\r
-  char query[256];\r
-  uint8_t rEntry, i;\r
-\r
-  if ((rEntry = FindEntry(nBuddyCharID)) < mListSize)\r
-  {\r
-    --mListSize;\r
-    for (i = rEntry; i < mListSize; i++)\r
-    {\r
-      mGenrepList[i] = mGenrepList[i+1];\r
-    }\r
-    // Remove from DB here\r
-    snprintf(query, 256, "DELETE FROM buddy_list WHERE ((bud_charid='%u') AND (bud_buddyid='%u')) LIMIT 1;", mOwnerCharID, nBuddyCharID);\r
-    if ( MySQL->GameQuery(query) )\r
-    {\r
-        Console->Print(RED, BLACK, "PBuddyList::AddChar could not add some buddylist entry in the database");\r
-        Console->Print("Query was:");\r
-        Console->Print("%s", query);\r
-        MySQL->ShowGameSQLError();\r
-        return false;\r
-    }\r
-\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}*/\r
-\r
-bool PGenrepList::SQLLoad()\r
-{\r
-    char query[256];\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    uint8_t EntriesNum;\r
-\r
-    snprintf(query, 256, "SELECT * FROM genrep WHERE (g_charid='%u')", mOwnerCharID);\r
-    result = MySQL->GameResQuery(query);\r
-    if(result == NULL)\r
-    {\r
-        Console->Print(RED, BLACK, "PGenrepList::SQLLoad could not load genreplist from the database");\r
-        Console->Print("Query was:");\r
-        Console->Print("%s", query);\r
-        MySQL->ShowGameSQLError();\r
-        return false;\r
-    }\r
-    //Console->Print(GREEN, BLACK, "PGenrepList::SQLLoad Loading Genrep list for char %d", mOwnerCharID);\r
-    mListSize = 0;\r
-    if((EntriesNum = mysql_num_rows(result)))\r
-    {\r
-        IncreaseMaxSize(EntriesNum);\r
-\r
-        while((row = mysql_fetch_row(result)))\r
-        {\r
-            mGenrepList[mListSize].mWorldID = atoi(row[g_worldid]);\r
-            mGenrepList[mListSize++].mStationID = atoi(row[g_stationid]);\r
-            //Console->Print(GREEN, BLACK, "PGenrepList::SQLLoad Genrep list entry %d : world %d station %d", mListSize, mGenrepList[mListSize-1].mWorldID,mGenrepList[mListSize-1].mStationID);\r
-        }\r
-    }\r
-    MySQL->FreeGameSQLResult(result);\r
-    return true;\r
-}\r
-\r
-void PGenrepList::IncreaseMaxSize(uint8_t nNewMax)\r
-{\r
-    uint16_t tmpSize;\r
-\r
-    if (!nNewMax)\r
-    {\r
-        tmpSize = mListMaxSize + GENREPLIST_ALLOC_SIZE;\r
-    }\r
-    else if (nNewMax > mListMaxSize)\r
-    {\r
-        tmpSize = nNewMax / GENREPLIST_ALLOC_SIZE;\r
-        if (nNewMax % GENREPLIST_ALLOC_SIZE)\r
-            ++tmpSize;\r
-        tmpSize *= GENREPLIST_ALLOC_SIZE;\r
-    }\r
-    else\r
-        return;\r
-\r
-    mListMaxSize = (tmpSize < 256) ? tmpSize : 255;\r
-\r
-    PGenrepEntry* tmpList = new PGenrepEntry[mListMaxSize];\r
-    if (mGenrepList)\r
-    {\r
-        if (mListSize)\r
-        {\r
-            memcpy(tmpList, mGenrepList, sizeof(PGenrepEntry) * mListSize);\r
-        }\r
-        delete[] mGenrepList;\r
-    }\r
-    mGenrepList = tmpList;\r
-}\r
-\r
-uint8_t PGenrepList::FindEntry(uint16_t nWorldID, uint16_t nStationID)\r
-{\r
-    uint8_t i = 255;\r
-\r
-    if (mGenrepList)\r
-    {\r
-        for (i = 0; i < mListSize; i++)\r
-        {\r
-            if ((mGenrepList[i].mWorldID == nWorldID) && (mGenrepList[i].mStationID == nStationID))\r
-                break;\r
-        }\r
-    }\r
-\r
-    return i;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PGenrepList::PGenrepList(uint32_t nOwnerCharID)
+{
+    mOwnerCharID = nOwnerCharID;
+    mListMaxSize = mListSize = 0;
+    mGenrepList = NULL;
+}
+
+PGenrepList::~PGenrepList()
+{
+    if (mGenrepList)
+        delete[] mGenrepList;
+}
+
+bool PGenrepList::AddGenrep(uint16_t nWorldID, uint16_t nStationID)
+{
+    char query[256];
+
+    if ((FindEntry(nWorldID, nStationID) >= mListSize) && (mListSize < 255))
+    {
+        if (mListSize == mListMaxSize)
+        {
+            IncreaseMaxSize();
+        }
+        mGenrepList[mListSize].mWorldID = nWorldID;
+        mGenrepList[mListSize++].mStationID = nStationID;
+
+        snprintf(query, 256, "INSERT INTO genrep (g_id,g_worldid,g_stationid,g_charid) VALUES (NULL,'%u','%u','%u');", nWorldID, nStationID, mOwnerCharID);
+        if ( MySQL->GameQuery(query) )
+        {
+            Console->Print(RED, BLACK, "PGenrepList::AddGenrep could not add some genrep entry in the database");
+            Console->Print("Query was:");
+            Console->Print("%s", query);
+            MySQL->ShowGameSQLError();
+            return false;
+        }
+
+        return true;
+    }
+    else
+        return false;
+}
+
+/*bool PGenrepList::RemoveChar(uint32_t nBuddyCharID)
+{
+  char query[256];
+  uint8_t rEntry, i;
+
+  if ((rEntry = FindEntry(nBuddyCharID)) < mListSize)
+  {
+    --mListSize;
+    for (i = rEntry; i < mListSize; i++)
+    {
+      mGenrepList[i] = mGenrepList[i+1];
+    }
+    // Remove from DB here
+    snprintf(query, 256, "DELETE FROM buddy_list WHERE ((bud_charid='%u') AND (bud_buddyid='%u')) LIMIT 1;", mOwnerCharID, nBuddyCharID);
+    if ( MySQL->GameQuery(query) )
+    {
+        Console->Print(RED, BLACK, "PBuddyList::AddChar could not add some buddylist entry in the database");
+        Console->Print("Query was:");
+        Console->Print("%s", query);
+        MySQL->ShowGameSQLError();
+        return false;
+    }
+
+    return true;
+  }
+  else
+    return false;
+}*/
+
+bool PGenrepList::SQLLoad()
+{
+    char query[256];
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    uint8_t EntriesNum;
+
+    snprintf(query, 256, "SELECT * FROM genrep WHERE (g_charid='%u')", mOwnerCharID);
+    result = MySQL->GameResQuery(query);
+    if(result == NULL)
+    {
+        Console->Print(RED, BLACK, "PGenrepList::SQLLoad could not load genreplist from the database");
+        Console->Print("Query was:");
+        Console->Print("%s", query);
+        MySQL->ShowGameSQLError();
+        return false;
+    }
+    //Console->Print(GREEN, BLACK, "PGenrepList::SQLLoad Loading Genrep list for char %d", mOwnerCharID);
+    mListSize = 0;
+    if((EntriesNum = mysql_num_rows(result)))
+    {
+        IncreaseMaxSize(EntriesNum);
+
+        while((row = mysql_fetch_row(result)))
+        {
+            mGenrepList[mListSize].mWorldID = atoi(row[g_worldid]);
+            mGenrepList[mListSize++].mStationID = atoi(row[g_stationid]);
+            //Console->Print(GREEN, BLACK, "PGenrepList::SQLLoad Genrep list entry %d : world %d station %d", mListSize, mGenrepList[mListSize-1].mWorldID,mGenrepList[mListSize-1].mStationID);
+        }
+    }
+    MySQL->FreeGameSQLResult(result);
+    return true;
+}
+
+void PGenrepList::IncreaseMaxSize(uint8_t nNewMax)
+{
+    uint16_t tmpSize;
+
+    if (!nNewMax)
+    {
+        tmpSize = mListMaxSize + GENREPLIST_ALLOC_SIZE;
+    }
+    else if (nNewMax > mListMaxSize)
+    {
+        tmpSize = nNewMax / GENREPLIST_ALLOC_SIZE;
+        if (nNewMax % GENREPLIST_ALLOC_SIZE)
+            ++tmpSize;
+        tmpSize *= GENREPLIST_ALLOC_SIZE;
+    }
+    else
+        return;
+
+    mListMaxSize = (tmpSize < 256) ? tmpSize : 255;
+
+    PGenrepEntry* tmpList = new PGenrepEntry[mListMaxSize];
+    if (mGenrepList)
+    {
+        if (mListSize)
+        {
+            memcpy(tmpList, mGenrepList, sizeof(PGenrepEntry) * mListSize);
+        }
+        delete[] mGenrepList;
+    }
+    mGenrepList = tmpList;
+}
+
+uint8_t PGenrepList::FindEntry(uint16_t nWorldID, uint16_t nStationID)
+{
+    uint8_t i = 255;
+
+    if (mGenrepList)
+    {
+        for (i = 0; i < mListSize; i++)
+        {
+            if ((mGenrepList[i].mWorldID == nWorldID) && (mGenrepList[i].mStationID == nStationID))
+                break;
+        }
+    }
+
+    return i;
+}
index ea47372..e19b9cd 100644 (file)
@@ -1,39 +1,39 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-#define GENREPLIST_ALLOC_SIZE 4 // atomicity of list entries allocation\r
-\r
-class PGenrepList {\r
-private:\r
-    enum { // genrep DB Table fields\r
-        g_id = 0,\r
-        g_worldid,\r
-        g_stationid,\r
-        g_charid\r
-    };\r
-    struct PGenrepEntry\r
-    {\r
-      uint16_t mWorldID;\r
-      uint16_t mStationID;\r
-    };\r
-\r
-    uint32_t mOwnerCharID;\r
-    uint8_t mListMaxSize;\r
-    uint8_t mListSize;\r
-    PGenrepEntry* mGenrepList;\r
-\r
-    void IncreaseMaxSize(uint8_t nNewMax = 0);\r
-    uint8_t FindEntry(uint16_t nWorldID, uint16_t nStationID);\r
-\r
-  public:\r
-    PGenrepList(uint32_t nOwnerCharID);\r
-    ~PGenrepList();\r
-    bool AddGenrep(uint16_t nWorldID, uint16_t nStationID);\r
-    //bool RemoveChar(uint32_t nBuddyCharID);\r
-    inline uint8_t Count() { return mListSize; }\r
-    uint16_t GetListDataSize() { return (sizeof(PGenrepEntry) * mListSize); }\r
-    const void* GetListData() { return (const void*)mGenrepList; }\r
-    bool SQLLoad();\r
-//    bool SQLSave();\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+#define GENREPLIST_ALLOC_SIZE 4 // atomicity of list entries allocation
+
+class PGenrepList {
+private:
+    enum { // genrep DB Table fields
+        g_id = 0,
+        g_worldid,
+        g_stationid,
+        g_charid
+    };
+    struct PGenrepEntry
+    {
+      uint16_t mWorldID;
+      uint16_t mStationID;
+    };
+
+    uint32_t mOwnerCharID;
+    uint8_t mListMaxSize;
+    uint8_t mListSize;
+    PGenrepEntry* mGenrepList;
+
+    void IncreaseMaxSize(uint8_t nNewMax = 0);
+    uint8_t FindEntry(uint16_t nWorldID, uint16_t nStationID);
+
+  public:
+    PGenrepList(uint32_t nOwnerCharID);
+    ~PGenrepList();
+    bool AddGenrep(uint16_t nWorldID, uint16_t nStationID);
+    //bool RemoveChar(uint32_t nBuddyCharID);
+    inline uint8_t Count() { return mListSize; }
+    uint16_t GetListDataSize() { return (sizeof(PGenrepEntry) * mListSize); }
+    const void* GetListData() { return (const void*)mGenrepList; }
+    bool SQLLoad();
+//    bool SQLSave();
+};
index 28f3f3d..801f2ac 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// TODO:   - Get logfile name from config file\r
-\r
-const char ServerVersion[] = TINNS_GAME_VERSION;\r
-const char SVNRevision[] = TINNS_SVN_REVISION;\r
-\r
-PVehicles *Vehicles = 0;\r
-PMySQL *MySQL = 0;\r
-PConsole *Console = 0;\r
-PServer *Server = 0;\r
-PConfig *Config = 0;\r
-PConfig *CmdAccess = 0;\r
-PGameDefs *GameDefs = 0;\r
-PChars *Chars = 0;\r
-PFileSystem *Filesystem = 0;\r
-PGameServer *GameServer = 0;\r
-ServerSocket *ServerSock = 0;\r
-PMsgBuilder *MsgBuilder = 0;\r
-PWorlds *Worlds = 0;\r
-PAppartements* Appartements = 0;\r
-PWorldActors* WorldActors = 0;\r
-PNPCManager* NPCManager = 0;\r
-PSubway* Subway = 0;\r
-PTerminal* Terminal = 0;\r
-PLuaEngine* LuaEngine = 0;\r
-POutpost* Outposts = 0;\r
-PMultiPart* MultiPartHandler = 0;\r
-\r
-//multi-user chat implementation\r
-PClientManager *ClientManager = 0;\r
-PChat *Chat = 0;\r
-PCommands *GameCommands = 0;\r
-\r
-PISC *ISC = 0;\r
-\r
-const std::string EmptyString;\r
-\r
-// Development debug output control (set by config option dev_debug)\r
-bool gDevDebug = false;\r
-\r
-bool InitTinNS()\r
-{\r
-    Console = new PConsole("log/gameserver.log"); // Make that from config file !!!\r
-    Console->Print("Starting TinNS Gameserver");\r
-    Console->Print(WHITE, BLUE, "/-------------------------------------------------------------------\\");\r
-    Console->Print(WHITE, BLUE, "|               TinNS (TinNS is not a Neocron Server)               |");\r
-    Console->Print(WHITE, BLUE, "|            Copyright (C) 2005 Linux Addicted Community            |");\r
-    Console->Print(WHITE, BLUE, "|                  maintainer Akiko <akiko@gmx.org>                 |");\r
-    Console->Print(WHITE, BLUE, "|             ==========================================            |");\r
-    Console->Print(WHITE, BLUE, "|      Head coders:                   The packet analyzing team:    |");\r
-    Console->Print(WHITE, BLUE, "|      - Akiko                         - MaxxJag                    |");\r
-    Console->Print(WHITE, BLUE, "|      - bakkdoor                      - Sting                      |");\r
-    Console->Print(WHITE, BLUE, "|      - Namikon                       - Balm                       |");\r
-    Console->Print(WHITE, BLUE, "|      - Hammag                                                     |");\r
-    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");\r
-    Console->Print(WHITE, BLUE, "|  This project would'nt be at its current stage without the help   |");\r
-    Console->Print(WHITE, BLUE, "|        from the NeoPolis team, special thanks to you guys!        |");\r
-    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");\r
-    Console->Print(WHITE, BLUE, "|  This project is under GPL, see any source file for more details  |");\r
-    Console->Print(WHITE, BLUE, "\\-------------------------------------------------------------------/");\r
-\r
-    //char svnrev[10];\r
-    //GetSVNRev(svnrev);\r
-    Console->LPrint("You are running TinNS Gameserver version");\r
-    Console->LPrint(GREEN, BLACK, " %s", ServerVersion);\r
-    Console->LPrint(WHITE, BLACK, " - SVN Rev");\r
-    Console->LPrint(GREEN, BLACK, " %s", SVNRevision);\r
-    Console->LClose();\r
-\r
-    Config = new PConfig();\r
-    if(!Config->LoadOptions(GameConfigTemplate, "./conf/gameserver.conf"))\r
-        return false; //Shutdown();\r
-\r
-    CmdAccess = new PConfig();\r
-    if(!CmdAccess->LoadOptions(CommandsTemplate, "./conf/commands.conf"))\r
-        return false; //Shutdown();\r
-\r
-    gDevDebug = Config->GetOptionInt("dev_debug");\r
-    std::string MyName = Config->GetOption("server_name");\r
-    std::string IP = Config->GetOption("server_ip");\r
-    char myCname[100], myCip[100];\r
-    strncpy (myCname, Console->ColorText(CYAN, BLACK, MyName.c_str()), 100);\r
-    strncpy (myCip, Console->ColorText(CYAN, BLACK, IP.c_str()), 100);\r
-    Console->Print("My name is '%s', and my address is %s", myCname, myCip);\r
-\r
-    MySQL = new PMySQL();\r
-    if(MySQL->Connect() == false)\r
-        return false; //Shutdown();\r
-\r
-    Filesystem = new PFileSystem();\r
-\r
-    GameDefs = new PGameDefs();\r
-    GameDefs->Init();\r
-\r
-    Worlds = new PWorlds();\r
-    Worlds->LoadWorlds();\r
-\r
-    WorldActors = new PWorldActors();\r
-    LuaEngine = new PLuaEngine();\r
-\r
-    NPCManager = new PNPCManager();\r
-    Appartements = new PAppartements;\r
-    Subway = new PSubway;\r
-\r
-    if (!PAccount::SetUsernameRegexFilter(Config->GetOption("username_filter").c_str()))\r
-    {\r
-      Console->Print("%s Could not creat username_filter PCRE '%s'", Console->ColorText(RED, BLACK, "[Error]"), Config->GetOption("username_filter").c_str());\r
-      return false;\r
-    }\r
-    if(!PAccount::SetPasswordRegexFilter(Config->GetOption("password_filter").c_str()))\r
-    {\r
-      Console->Print("%s Could not creat password_filter PCRE '%s'", Console->ColorText(RED, BLACK, "[Error]"), Config->GetOption("password_filter").c_str());\r
-      return false;\r
-    }\r
-\r
-    if (!PChar::SetCharnameRegexFilter(Config->GetOption("charname_filter").c_str()))\r
-    {\r
-      Console->Print("%s Could not creat charname_filter PCRE '%s'", Console->ColorText(RED, BLACK, "[Error]"), Config->GetOption("charname_filter").c_str());\r
-      return false;\r
-    }\r
-    Chars = new PChars();\r
-\r
-    ServerSock = new ServerSocket();\r
-    Server = new PServer();\r
-    GameServer = new PGameServer();\r
-    MsgBuilder = new PMsgBuilder();\r
-\r
-    Vehicles = new PVehicles();\r
-\r
-    ClientManager = new PClientManager();\r
-    Chat = new PChat();\r
-    GameCommands = new PCommands();\r
-\r
-    ISC = new PISC();\r
-    Terminal = new PTerminal();\r
-\r
-    Outposts = new POutpost();\r
-\r
-    MultiPartHandler = new PMultiPart();\r
-\r
-    return true;\r
-}\r
-\r
-void Shutdown()\r
-{\r
-    if(MultiPartHandler)\r
-        delete MultiPartHandler;\r
-    if(Outposts)\r
-        delete Outposts;\r
-    if(LuaEngine)\r
-        delete LuaEngine;\r
-    if(Terminal)\r
-        delete Terminal;\r
-    if(WorldActors)\r
-        delete WorldActors;\r
-    if(NPCManager)\r
-        delete NPCManager;\r
-    if(ISC)\r
-    {\r
-        ISC->Shutdown();\r
-        delete ISC;\r
-    }\r
-    if(Server)\r
-        Server->Shutdown();\r
-    if(GameServer)\r
-        delete GameServer;\r
-    if(Chat)\r
-        delete Chat;\r
-    if(Server)\r
-        delete Server;\r
-    if(Filesystem)\r
-        delete Filesystem;\r
-    if(GameDefs)\r
-        delete GameDefs;\r
-    if(Worlds)\r
-    {\r
-        Worlds->Shutdown();\r
-        delete Worlds;\r
-    }\r
-    if(Subway)\r
-        delete Subway;\r
-    if(Chars)\r
-        delete Chars;\r
-    if(MySQL)\r
-        delete MySQL;\r
-    if(Config)\r
-        delete Config;\r
-    if(Console)\r
-        delete Console;\r
-    if(ServerSock)\r
-        delete ServerSock;\r
-\r
-    exit(0);\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// TODO:   - Get logfile name from config file
+
+const char ServerVersion[] = TINNS_GAME_VERSION;
+const char SVNRevision[] = TINNS_SVN_REVISION;
+
+PVehicles *Vehicles = 0;
+PMySQL *MySQL = 0;
+PConsole *Console = 0;
+PServer *Server = 0;
+PConfig *Config = 0;
+PConfig *CmdAccess = 0;
+PGameDefs *GameDefs = 0;
+PChars *Chars = 0;
+PFileSystem *Filesystem = 0;
+PGameServer *GameServer = 0;
+ServerSocket *ServerSock = 0;
+PMsgBuilder *MsgBuilder = 0;
+PWorlds *Worlds = 0;
+PAppartements* Appartements = 0;
+PWorldActors* WorldActors = 0;
+PNPCManager* NPCManager = 0;
+PSubway* Subway = 0;
+PTerminal* Terminal = 0;
+PLuaEngine* LuaEngine = 0;
+POutpost* Outposts = 0;
+PMultiPart* MultiPartHandler = 0;
+
+//multi-user chat implementation
+PClientManager *ClientManager = 0;
+PChat *Chat = 0;
+PCommands *GameCommands = 0;
+
+PISC *ISC = 0;
+
+const std::string EmptyString;
+
+// Development debug output control (set by config option dev_debug)
+bool gDevDebug = false;
+
+bool InitTinNS()
+{
+    Console = new PConsole("log/gameserver.log"); // Make that from config file !!!
+    Console->Print("Starting TinNS Gameserver");
+    Console->Print(WHITE, BLUE, "/-------------------------------------------------------------------\\");
+    Console->Print(WHITE, BLUE, "|               TinNS (TinNS is not a Neocron Server)               |");
+    Console->Print(WHITE, BLUE, "|            Copyright (C) 2005 Linux Addicted Community            |");
+    Console->Print(WHITE, BLUE, "|                  maintainer Akiko <akiko@gmx.org>                 |");
+    Console->Print(WHITE, BLUE, "|             ==========================================            |");
+    Console->Print(WHITE, BLUE, "|      Head coders:                   The packet analyzing team:    |");
+    Console->Print(WHITE, BLUE, "|      - Akiko                         - MaxxJag                    |");
+    Console->Print(WHITE, BLUE, "|      - bakkdoor                      - Sting                      |");
+    Console->Print(WHITE, BLUE, "|      - Namikon                       - Balm                       |");
+    Console->Print(WHITE, BLUE, "|      - Hammag                                                     |");
+    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");
+    Console->Print(WHITE, BLUE, "|  This project would'nt be at its current stage without the help   |");
+    Console->Print(WHITE, BLUE, "|        from the NeoPolis team, special thanks to you guys!        |");
+    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");
+    Console->Print(WHITE, BLUE, "|  This project is under GPL, see any source file for more details  |");
+    Console->Print(WHITE, BLUE, "\\-------------------------------------------------------------------/");
+
+    //char svnrev[10];
+    //GetSVNRev(svnrev);
+    Console->LPrint("You are running TinNS Gameserver version");
+    Console->LPrint(GREEN, BLACK, " %s", ServerVersion);
+    Console->LPrint(WHITE, BLACK, " - SVN Rev");
+    Console->LPrint(GREEN, BLACK, " %s", SVNRevision);
+    Console->LClose();
+
+    Config = new PConfig();
+    if(!Config->LoadOptions(GameConfigTemplate, "./conf/gameserver.conf"))
+        return false; //Shutdown();
+
+    CmdAccess = new PConfig();
+    if(!CmdAccess->LoadOptions(CommandsTemplate, "./conf/commands.conf"))
+        return false; //Shutdown();
+
+    gDevDebug = Config->GetOptionInt("dev_debug");
+    std::string MyName = Config->GetOption("server_name");
+    std::string IP = Config->GetOption("server_ip");
+    char myCname[100], myCip[100];
+    strncpy (myCname, Console->ColorText(CYAN, BLACK, MyName.c_str()), 100);
+    strncpy (myCip, Console->ColorText(CYAN, BLACK, IP.c_str()), 100);
+    Console->Print("My name is '%s', and my address is %s", myCname, myCip);
+
+    MySQL = new PMySQL();
+    if(MySQL->Connect() == false)
+        return false; //Shutdown();
+
+    Filesystem = new PFileSystem();
+
+    GameDefs = new PGameDefs();
+    GameDefs->Init();
+
+    Worlds = new PWorlds();
+    Worlds->LoadWorlds();
+
+    WorldActors = new PWorldActors();
+    LuaEngine = new PLuaEngine();
+
+    NPCManager = new PNPCManager();
+    Appartements = new PAppartements;
+    Subway = new PSubway;
+
+    if (!PAccount::SetUsernameRegexFilter(Config->GetOption("username_filter").c_str()))
+    {
+      Console->Print("%s Could not creat username_filter PCRE '%s'", Console->ColorText(RED, BLACK, "[Error]"), Config->GetOption("username_filter").c_str());
+      return false;
+    }
+    if(!PAccount::SetPasswordRegexFilter(Config->GetOption("password_filter").c_str()))
+    {
+      Console->Print("%s Could not creat password_filter PCRE '%s'", Console->ColorText(RED, BLACK, "[Error]"), Config->GetOption("password_filter").c_str());
+      return false;
+    }
+
+    if (!PChar::SetCharnameRegexFilter(Config->GetOption("charname_filter").c_str()))
+    {
+      Console->Print("%s Could not creat charname_filter PCRE '%s'", Console->ColorText(RED, BLACK, "[Error]"), Config->GetOption("charname_filter").c_str());
+      return false;
+    }
+    Chars = new PChars();
+
+    ServerSock = new ServerSocket();
+    Server = new PServer();
+    GameServer = new PGameServer();
+    MsgBuilder = new PMsgBuilder();
+
+    Vehicles = new PVehicles();
+
+    ClientManager = new PClientManager();
+    Chat = new PChat();
+    GameCommands = new PCommands();
+
+    ISC = new PISC();
+    Terminal = new PTerminal();
+
+    Outposts = new POutpost();
+
+    MultiPartHandler = new PMultiPart();
+
+    return true;
+}
+
+void Shutdown()
+{
+    if(MultiPartHandler)
+        delete MultiPartHandler;
+    if(Outposts)
+        delete Outposts;
+    if(LuaEngine)
+        delete LuaEngine;
+    if(Terminal)
+        delete Terminal;
+    if(WorldActors)
+        delete WorldActors;
+    if(NPCManager)
+        delete NPCManager;
+    if(ISC)
+    {
+        ISC->Shutdown();
+        delete ISC;
+    }
+    if(Server)
+        Server->Shutdown();
+    if(GameServer)
+        delete GameServer;
+    if(Chat)
+        delete Chat;
+    if(Server)
+        delete Server;
+    if(Filesystem)
+        delete Filesystem;
+    if(GameDefs)
+        delete GameDefs;
+    if(Worlds)
+    {
+        Worlds->Shutdown();
+        delete Worlds;
+    }
+    if(Subway)
+        delete Subway;
+    if(Chars)
+        delete Chars;
+    if(MySQL)
+        delete MySQL;
+    if(Config)
+        delete Config;
+    if(Console)
+        delete Console;
+    if(ServerSock)
+        delete ServerSock;
+
+    exit(0);
+}
index e35b5f2..d399724 100644 (file)
@@ -1,89 +1,89 @@
-#pragma once\r
-\r
-#include "GameServer/Accounts.hxx"\r
-#include "GameServer/Appartements.hxx"\r
-#include "GameServer/BuddyList.hxx"\r
-#include "GameServer/Chars.hxx"\r
-#include "GameServer/Chat.hxx"\r
-#include "GameServer/Client.hxx"\r
-#include "GameServer/ClientManager.hxx"\r
-#include "GameServer/Commands.hxx"\r
-#include "GameServer/ConfigTemplate.hxx"\r
-#include "GameServer/Container.hxx"\r
-#include "GameServer/DoorTemplate.hxx"\r
-#include "GameServer/FurnitureTemplate.hxx"\r
-#include "GameServer/GameScript.hxx"\r
-#include "GameServer/GameServer.hxx"\r
-#include "GameServer/GenrepList.hxx"\r
-#include "GameServer/Inventory.hxx"\r
-#include "GameServer/Isc.hxx"\r
-#include "GameServer/Item.hxx"\r
-#include "GameServer/LuaEngine.hxx"\r
-#include "GameServer/Main.hxx"\r
-#include "GameServer/MessageBuilder.hxx"\r
-#include "GameServer/MultiPart.hxx"\r
-#include "GameServer/Npc.hxx"\r
-#include "GameServer/NpcTemplate.hxx"\r
-#include "GameServer/Outpost.hxx"\r
-#include "GameServer/RemoteConsole.hxx"\r
-#include "GameServer/Server.hxx"\r
-#include "GameServer/Skill.hxx"\r
-#include "GameServer/Sql.hxx"\r
-#include "GameServer/Subway.hxx"\r
-#include "GameServer/Terminal.hxx"\r
-#include "GameServer/Vehicle.hxx"\r
-#include "GameServer/VehicleAccessRequest.hxx"\r
-#include "GameServer/WorldActors.hxx"\r
-#include "GameServer/WorldDataTemplate.hxx"\r
-#include "GameServer/Worlds.hxx"\r
-#include "GameServer/Zoning.hxx"\r
-\r
-extern class PLuaEngine *LuaEngine;\r
-\r
-extern class ServerSocket *ServerSock;\r
-extern class PConsole *Console;\r
-//extern class PRConsole *RemoteConsole;\r
-extern class PConfig *Config;\r
-extern class PConfig *CmdAccess;\r
-\r
-extern class PGameDefs *GameDefs;\r
-extern class PFileSystem *Filesystem;\r
-extern class PServer *Server;\r
-\r
-extern class PGameServer *GameServer;\r
-extern class PChars *Chars;\r
-\r
-extern class PMsgBuilder *MsgBuilder;\r
-extern class PWorlds *Worlds;\r
-extern class PAppartements* Appartements;\r
-extern class PWorldActors* WorldActors;\r
-extern class PTerminal* Terminal;\r
-//extern class gmMachine machine;   // Virtual Machine instance\r
-\r
-//multiuser chat\r
-extern class PClientManager *ClientManager;\r
-extern class PNPCManager* NPCManager;\r
-extern class PChat *Chat;\r
-extern class PCommands *GameCommands;\r
-\r
-extern class POutpost *Outposts;\r
-extern class PMultiPart *MultiPartHandler;\r
-\r
-// Development debug output control\r
-extern bool gDevDebug;\r
-\r
-//MySQL-Support\r
-extern class PMySQL* MySQL;\r
-\r
-//Vehicles\r
-extern class PVehicles *Vehicles;\r
-extern class PSubway* Subway;\r
-\r
-//Infoserver update\r
-extern class PISC *ISC;\r
-\r
-extern const char ServerVersion[];\r
-extern const char SVNRevision[];\r
-\r
-bool InitTinNS();\r
-void Shutdown();\r
+#pragma once
+
+#include "GameServer/Accounts.hxx"
+#include "GameServer/Appartements.hxx"
+#include "GameServer/BuddyList.hxx"
+#include "GameServer/Chars.hxx"
+#include "GameServer/Chat.hxx"
+#include "GameServer/Client.hxx"
+#include "GameServer/ClientManager.hxx"
+#include "GameServer/Commands.hxx"
+#include "GameServer/ConfigTemplate.hxx"
+#include "GameServer/Container.hxx"
+#include "GameServer/DoorTemplate.hxx"
+#include "GameServer/FurnitureTemplate.hxx"
+#include "GameServer/GameScript.hxx"
+#include "GameServer/GameServer.hxx"
+#include "GameServer/GenrepList.hxx"
+#include "GameServer/Inventory.hxx"
+#include "GameServer/Isc.hxx"
+#include "GameServer/Item.hxx"
+#include "GameServer/LuaEngine.hxx"
+#include "GameServer/Main.hxx"
+#include "GameServer/MessageBuilder.hxx"
+#include "GameServer/MultiPart.hxx"
+#include "GameServer/Npc.hxx"
+#include "GameServer/NpcTemplate.hxx"
+#include "GameServer/Outpost.hxx"
+#include "GameServer/RemoteConsole.hxx"
+#include "GameServer/Server.hxx"
+#include "GameServer/Skill.hxx"
+#include "GameServer/Sql.hxx"
+#include "GameServer/Subway.hxx"
+#include "GameServer/Terminal.hxx"
+#include "GameServer/Vehicle.hxx"
+#include "GameServer/VehicleAccessRequest.hxx"
+#include "GameServer/WorldActors.hxx"
+#include "GameServer/WorldDataTemplate.hxx"
+#include "GameServer/Worlds.hxx"
+#include "GameServer/Zoning.hxx"
+
+extern class PLuaEngine *LuaEngine;
+
+extern class ServerSocket *ServerSock;
+extern class PConsole *Console;
+//extern class PRConsole *RemoteConsole;
+extern class PConfig *Config;
+extern class PConfig *CmdAccess;
+
+extern class PGameDefs *GameDefs;
+extern class PFileSystem *Filesystem;
+extern class PServer *Server;
+
+extern class PGameServer *GameServer;
+extern class PChars *Chars;
+
+extern class PMsgBuilder *MsgBuilder;
+extern class PWorlds *Worlds;
+extern class PAppartements* Appartements;
+extern class PWorldActors* WorldActors;
+extern class PTerminal* Terminal;
+//extern class gmMachine machine;   // Virtual Machine instance
+
+//multiuser chat
+extern class PClientManager *ClientManager;
+extern class PNPCManager* NPCManager;
+extern class PChat *Chat;
+extern class PCommands *GameCommands;
+
+extern class POutpost *Outposts;
+extern class PMultiPart *MultiPartHandler;
+
+// Development debug output control
+extern bool gDevDebug;
+
+//MySQL-Support
+extern class PMySQL* MySQL;
+
+//Vehicles
+extern class PVehicles *Vehicles;
+extern class PSubway* Subway;
+
+//Infoserver update
+extern class PISC *ISC;
+
+extern const char ServerVersion[];
+extern const char SVNRevision[];
+
+bool InitTinNS();
+void Shutdown();
index 9d82354..5d82f13 100644 (file)
-#include "GameServer/Includes.hxx"\r
-\r
-/* --- PInventory class --- */\r
-\r
-PInventory::PInventory ()\r
-{\r
-  mWorn = new PContainerWithHoles(INV_WORN_MAXSLOTS);\r
-  //mBackpack = new PContainer2D();\r
-  mBackpack = new PContainer2DWorkaround(); // until Inside-Backpack item moving issues are solved\r
-  mBackpack->Set2DPosMax(INV_BACKPACK_COLS);\r
-  mGogo = new PContainerAutoFindFree(INV_GOGO_MAXSLOTS);\r
-}\r
-\r
-PInventory::~PInventory ()\r
-{\r
-  delete mWorn;\r
-  delete mBackpack;\r
-  delete mGogo;\r
-}\r
-\r
-void PInventory::SetCharId(uint32_t CharID)\r
-{\r
-  mWorn->SetInfo(CharID, INV_DB_LOC_WORN);\r
-  mBackpack->SetInfo(CharID, INV_DB_LOC_BACKPACK);\r
-  mGogo->SetInfo(CharID, INV_DB_LOC_GOGO);\r
-}\r
-\r
-bool PInventory::SQLLoad()\r
-{\r
-  return ( mWorn->SQLLoad() && mBackpack->SQLLoad() && mGogo->SQLLoad() );\r
-\r
-/*bool ret = mWorn->SQLLoad() && mBackpack->SQLLoad() && mGogo->SQLLoad();\r
-Console->Print(YELLOW, BLACK, "--- Worn Inventory ---");\r
-mWorn->Dump();\r
-Console->Print(YELLOW, BLACK, "--- Backpack Inventory ---");\r
-mBackpack->Dump();\r
-Console->Print(YELLOW, BLACK, "--- Gogo Inventory ---");\r
-mGogo->Dump();\r
-Console->Print(YELLOW, BLACK, "--- End Inventory ---");\r
-return ret;*/\r
-}\r
-\r
-bool PInventory::SQLSave()\r
-{\r
-  return mWorn->SQLSave() && mBackpack->SQLSave() && mGogo->SQLSave();\r
-}\r
-\r
-bool PInventory::IsDirty() const\r
-{\r
-  return (mWorn && mWorn->IsDirty()) || (mBackpack && mBackpack->IsDirty()) || (mGogo && mGogo->IsDirty());\r
-}\r
-\r
-PContainer* PInventory::GetContainer(uint8_t nInvLoc)\r
-{\r
-  PContainer* tContainer;\r
-  switch(nInvLoc)\r
-  {\r
-    case INV_LOC_WORN:\r
-      tContainer = mWorn;\r
-      break;\r
-    case INV_LOC_BACKPACK:\r
-      tContainer = mBackpack;\r
-      break;\r
-    case INV_LOC_GOGO:\r
-      tContainer = mGogo;\r
-      break;\r
-    default:\r
-      tContainer = NULL;\r
-  }\r
-  return tContainer;\r
-}\r
-\r
-bool PInventory::AddItem(PItem *NewItem, uint8_t nInvLoc, uint32_t nInvID, uint8_t nPosX, uint8_t nPosY, bool SetDirty)\r
-{\r
-  PContainer* destContainer = GetContainer(nInvLoc);\r
-  return(destContainer ? destContainer->AddItem(NewItem, nInvID, nPosX, nPosY, SetDirty) : false);\r
-}\r
-\r
-/*\r
-bool PInventory::QB_IsFree(uint8_t nSlot)\r
-{\r
-    if(nSlot > 9)\r
-        return false;\r
-\r
-    //    if (gDevDebug) Console->Print("Checking QBSlot %d. Content: %d", nSlot, mQuickAccessBelt[nSlot]);\r
-    if(mQuickAccessBelt[nSlot] == 0)\r
-        return true;\r
-    else\r
-        return false;\r
-}\r
-\r
-void PInventory::QB_SetSlot(uint8_t nSlot, uint16_t nItemID)\r
-{\r
-    if(nSlot > 9)\r
-        return;\r
-    //    if (gDevDebug) Console->Print("Setting QBSlot %d. Newcontent: %d Oldcontent: %d", nSlot, nItemID, mQuickAccessBelt[nSlot]);\r
-    mQuickAccessBelt[nSlot] = nItemID;\r
-}\r
-\r
-uint16_t PInventory::QB_GetSlot(uint8_t nSlot)\r
-{\r
-    if(nSlot > 9)\r
-        return 0;\r
-    //    if (gDevDebug) Console->Print("Getting QBSlot %d. Content: %d", nSlot, mQuickAccessBelt[nSlot]);\r
-    return mQuickAccessBelt[nSlot];\r
-}\r
-\r
-void PInventory::QB_Move(uint8_t nSlotSRC, uint8_t nSlotDST)\r
-{\r
-    if(nSlotSRC > 9 || nSlotDST > 9)\r
-        return;\r
-\r
-    //    if (gDevDebug) Console->Print("Moving QBSlot %d [%d] to %d [%d]", nSlotSRC, mQuickAccessBelt[nSlotSRC], nSlotDST, mQuickAccessBelt[nSlotDST]);\r
-    mQuickAccessBelt[nSlotDST] = mQuickAccessBelt[nSlotSRC];\r
-    mQuickAccessBelt[nSlotSRC] = 0;\r
-    //    if (gDevDebug) Console->Print("Moving done. %d [%d] %d [%d]", nSlotSRC, mQuickAccessBelt[nSlotSRC], nSlotDST, mQuickAccessBelt[nSlotDST]);\r
-}\r
-*/\r
+#include "GameServer/Includes.hxx"
+
+/* --- PInventory class --- */
+
+PInventory::PInventory ()
+{
+  mWorn = new PContainerWithHoles(INV_WORN_MAXSLOTS);
+  //mBackpack = new PContainer2D();
+  mBackpack = new PContainer2DWorkaround(); // until Inside-Backpack item moving issues are solved
+  mBackpack->Set2DPosMax(INV_BACKPACK_COLS);
+  mGogo = new PContainerAutoFindFree(INV_GOGO_MAXSLOTS);
+}
+
+PInventory::~PInventory ()
+{
+  delete mWorn;
+  delete mBackpack;
+  delete mGogo;
+}
+
+void PInventory::SetCharId(uint32_t CharID)
+{
+  mWorn->SetInfo(CharID, INV_DB_LOC_WORN);
+  mBackpack->SetInfo(CharID, INV_DB_LOC_BACKPACK);
+  mGogo->SetInfo(CharID, INV_DB_LOC_GOGO);
+}
+
+bool PInventory::SQLLoad()
+{
+  return ( mWorn->SQLLoad() && mBackpack->SQLLoad() && mGogo->SQLLoad() );
+
+/*bool ret = mWorn->SQLLoad() && mBackpack->SQLLoad() && mGogo->SQLLoad();
+Console->Print(YELLOW, BLACK, "--- Worn Inventory ---");
+mWorn->Dump();
+Console->Print(YELLOW, BLACK, "--- Backpack Inventory ---");
+mBackpack->Dump();
+Console->Print(YELLOW, BLACK, "--- Gogo Inventory ---");
+mGogo->Dump();
+Console->Print(YELLOW, BLACK, "--- End Inventory ---");
+return ret;*/
+}
+
+bool PInventory::SQLSave()
+{
+  return mWorn->SQLSave() && mBackpack->SQLSave() && mGogo->SQLSave();
+}
+
+bool PInventory::IsDirty() const
+{
+  return (mWorn && mWorn->IsDirty()) || (mBackpack && mBackpack->IsDirty()) || (mGogo && mGogo->IsDirty());
+}
+
+PContainer* PInventory::GetContainer(uint8_t nInvLoc)
+{
+  PContainer* tContainer;
+  switch(nInvLoc)
+  {
+    case INV_LOC_WORN:
+      tContainer = mWorn;
+      break;
+    case INV_LOC_BACKPACK:
+      tContainer = mBackpack;
+      break;
+    case INV_LOC_GOGO:
+      tContainer = mGogo;
+      break;
+    default:
+      tContainer = NULL;
+  }
+  return tContainer;
+}
+
+bool PInventory::AddItem(PItem *NewItem, uint8_t nInvLoc, uint32_t nInvID, uint8_t nPosX, uint8_t nPosY, bool SetDirty)
+{
+  PContainer* destContainer = GetContainer(nInvLoc);
+  return(destContainer ? destContainer->AddItem(NewItem, nInvID, nPosX, nPosY, SetDirty) : false);
+}
+
+/*
+bool PInventory::QB_IsFree(uint8_t nSlot)
+{
+    if(nSlot > 9)
+        return false;
+
+    //    if (gDevDebug) Console->Print("Checking QBSlot %d. Content: %d", nSlot, mQuickAccessBelt[nSlot]);
+    if(mQuickAccessBelt[nSlot] == 0)
+        return true;
+    else
+        return false;
+}
+
+void PInventory::QB_SetSlot(uint8_t nSlot, uint16_t nItemID)
+{
+    if(nSlot > 9)
+        return;
+    //    if (gDevDebug) Console->Print("Setting QBSlot %d. Newcontent: %d Oldcontent: %d", nSlot, nItemID, mQuickAccessBelt[nSlot]);
+    mQuickAccessBelt[nSlot] = nItemID;
+}
+
+uint16_t PInventory::QB_GetSlot(uint8_t nSlot)
+{
+    if(nSlot > 9)
+        return 0;
+    //    if (gDevDebug) Console->Print("Getting QBSlot %d. Content: %d", nSlot, mQuickAccessBelt[nSlot]);
+    return mQuickAccessBelt[nSlot];
+}
+
+void PInventory::QB_Move(uint8_t nSlotSRC, uint8_t nSlotDST)
+{
+    if(nSlotSRC > 9 || nSlotDST > 9)
+        return;
+
+    //    if (gDevDebug) Console->Print("Moving QBSlot %d [%d] to %d [%d]", nSlotSRC, mQuickAccessBelt[nSlotSRC], nSlotDST, mQuickAccessBelt[nSlotDST]);
+    mQuickAccessBelt[nSlotDST] = mQuickAccessBelt[nSlotSRC];
+    mQuickAccessBelt[nSlotSRC] = 0;
+    //    if (gDevDebug) Console->Print("Moving done. %d [%d] %d [%d]", nSlotSRC, mQuickAccessBelt[nSlotSRC], nSlotDST, mQuickAccessBelt[nSlotDST]);
+}
+*/
index 2218a5c..34b81ff 100644 (file)
@@ -1,83 +1,83 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-//NC containers message locations\r
-#define INV_LOC_GROUND 1\r
-#define INV_LOC_WORN 2\r
-#define INV_LOC_BACKPACK 3\r
-#define INV_LOC_BOX 4\r
-#define INV_LOC_NPCTRADE 5\r
-#define INV_LOC_GOGO 18\r
-#define INV_LOC_BOX2 255\r
-//PC-Trade window = ?\r
-\r
-//Inventory containers info\r
-#define INV_WORN_QB_START 0\r
-#define INV_WORN_QB_END 9\r
-#define INV_WORN_QB_NONE 99\r
-#define INV_WORN_QB_HAND 11\r
-\r
-#define INV_WORN_PROC_START 12\r
-#define INV_WORN_PROC_END 24\r
-\r
-#define INV_WORN_IMP_START 26\r
-#define INV_WORN_IMP_END 38\r
-\r
-#define INV_WORN_ARMOR_START 39\r
-#define INV_WORN_ARMOR_END 43\r
-\r
-#define INV_WORN_COLS 44\r
-#define INV_WORN_MAXSLOTS 44\r
-\r
-\r
-#define INV_BACKPACK_COLS 10\r
-\r
-#define INV_GOGO_COLS 5\r
-#define INV_GOGO_MAXSLOTS 50\r
-\r
-#define INV_CABINET_COLS 5\r
-#define INV_CABINET_MAXSLOTS 33\r
-\r
-// inv_loc values in database\r
-#define INV_DB_LOC_GOGO 1\r
-#define INV_DB_LOC_WORN 2\r
-#define INV_DB_LOC_BACKPACK 3\r
-\r
-class PItem;\r
-class PContainer;\r
-class PContainerWithHoles;\r
-class PContainer2DWorkaround;\r
-class PContainerAutoFindFree;\r
-\r
-class PInventory\r
-{\r
-  private:\r
-    PContainerWithHoles* mWorn; // PContainerLinearSlots\r
-    PContainer2DWorkaround* mBackpack; // PContainer2DAreas\r
-    PContainerAutoFindFree* mGogo; // PContainerLinearSlots\r
-\r
-  public:\r
-\r
-    PInventory();\r
-    ~PInventory();\r
-\r
-    void SetCharId(uint32_t CharID);\r
-    bool SQLLoad();\r
-    bool SQLSave();\r
-    PContainer* GetContainer(uint8_t nInvLoc);\r
-    inline PContainer2DWorkaround* GetBackpackContainer() { return mBackpack; }\r
-\r
-    bool IsDirty() const;\r
-\r
-    bool AddItem(PItem* NewItem, uint8_t nInvLoc = INV_LOC_BACKPACK, uint32_t nInvID = 0, uint8_t nPosX = 0, uint8_t nPosY = 0, bool SetDirty = true);\r
-    //bool CheckItem(uint32_t ItemID, uint8_t StackSize = 1);\r
-    //PItem *GetItem(uint32_t ItemID, uint8_t StackSize = 1);\r
-    //PItem *GetItemByPos(uint8_t nPosX, uint8_t nPosY, uint8_t StackSize = 1);\r
-    //bool MoveItem(uint8_t oPosX, uint8_t oPosY, uint8_t dPosX, uint8_t dPosY);\r
-\r
-    //bool QB_IsFree(uint8_t nSlot);\r
-    //void QB_SetSlot(uint8_t nSlot, uint16_t nItemID);\r
-    //uint16_t QB_GetSlot(uint8_t nSlot);\r
-    //void QB_Move(uint8_t nSlotSRC, uint8_t nSlotDST);\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+//NC containers message locations
+#define INV_LOC_GROUND 1
+#define INV_LOC_WORN 2
+#define INV_LOC_BACKPACK 3
+#define INV_LOC_BOX 4
+#define INV_LOC_NPCTRADE 5
+#define INV_LOC_GOGO 18
+#define INV_LOC_BOX2 255
+//PC-Trade window = ?
+
+//Inventory containers info
+#define INV_WORN_QB_START 0
+#define INV_WORN_QB_END 9
+#define INV_WORN_QB_NONE 99
+#define INV_WORN_QB_HAND 11
+
+#define INV_WORN_PROC_START 12
+#define INV_WORN_PROC_END 24
+
+#define INV_WORN_IMP_START 26
+#define INV_WORN_IMP_END 38
+
+#define INV_WORN_ARMOR_START 39
+#define INV_WORN_ARMOR_END 43
+
+#define INV_WORN_COLS 44
+#define INV_WORN_MAXSLOTS 44
+
+
+#define INV_BACKPACK_COLS 10
+
+#define INV_GOGO_COLS 5
+#define INV_GOGO_MAXSLOTS 50
+
+#define INV_CABINET_COLS 5
+#define INV_CABINET_MAXSLOTS 33
+
+// inv_loc values in database
+#define INV_DB_LOC_GOGO 1
+#define INV_DB_LOC_WORN 2
+#define INV_DB_LOC_BACKPACK 3
+
+class PItem;
+class PContainer;
+class PContainerWithHoles;
+class PContainer2DWorkaround;
+class PContainerAutoFindFree;
+
+class PInventory
+{
+  private:
+    PContainerWithHoles* mWorn; // PContainerLinearSlots
+    PContainer2DWorkaround* mBackpack; // PContainer2DAreas
+    PContainerAutoFindFree* mGogo; // PContainerLinearSlots
+
+  public:
+
+    PInventory();
+    ~PInventory();
+
+    void SetCharId(uint32_t CharID);
+    bool SQLLoad();
+    bool SQLSave();
+    PContainer* GetContainer(uint8_t nInvLoc);
+    inline PContainer2DWorkaround* GetBackpackContainer() { return mBackpack; }
+
+    bool IsDirty() const;
+
+    bool AddItem(PItem* NewItem, uint8_t nInvLoc = INV_LOC_BACKPACK, uint32_t nInvID = 0, uint8_t nPosX = 0, uint8_t nPosY = 0, bool SetDirty = true);
+    //bool CheckItem(uint32_t ItemID, uint8_t StackSize = 1);
+    //PItem *GetItem(uint32_t ItemID, uint8_t StackSize = 1);
+    //PItem *GetItemByPos(uint8_t nPosX, uint8_t nPosY, uint8_t StackSize = 1);
+    //bool MoveItem(uint8_t oPosX, uint8_t oPosY, uint8_t dPosX, uint8_t dPosY);
+
+    //bool QB_IsFree(uint8_t nSlot);
+    //void QB_SetSlot(uint8_t nSlot, uint16_t nItemID);
+    //uint16_t QB_GetSlot(uint8_t nSlot);
+    //void QB_Move(uint8_t nSlotSRC, uint8_t nSlotDST);
+};
index 0fece43..5115e79 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// TODO: - implement ISC protocol\r
-\r
-PISC::PISC()\r
-{\r
-  use_isc = false;\r
-  use_mysql = false;\r
-}\r
-\r
-PISC::~PISC()\r
-{\r
-}\r
-\r
-void PISC::Start()\r
-{\r
-  isc_method = Config->GetOptionInt("isc_method");\r
-\r
-  if(isc_method & 1)\r
-  {\r
-      Console->Print("%s Infoserver updating over MySQL is enabled", Console->ColorText(GREEN, BLACK, "[Info]"));\r
-      use_mysql = true;\r
-  }\r
-  if(isc_method & 2)\r
-  {\r
-      Console->Print("%s Infoserver updating over ISC is enabled, update intervall: infoserver: %s", Console->ColorText(GREEN, BLACK, "[Info]"), "?");\r
-      use_isc = true;\r
-      Console->Print("%s Infoserver updating over ISC not implemented yet. DISABLED", Console->ColorText(YELLOW, BLACK, "[Notice]"));\r
-      use_isc = false;\r
-  }\r
-  if(!(use_isc || use_mysql))\r
-  {\r
-      Console->Print("%s ISC and MySQL are both disabled, infoserver will NOT be updated", Console->ColorText(YELLOW, BLACK, "[Notice]"));\r
-  }\r
-\r
-  if (use_isc)\r
-    Start_isc();\r
-\r
-  if (use_mysql)\r
-    Start_mysql();\r
-\r
-}\r
-\r
-void PISC::Update()\r
-{\r
-  if (use_isc)\r
-    Update_isc();\r
-\r
-  if (use_mysql)\r
-    Update_mysql();\r
-}\r
-\r
-void PISC::Shutdown()\r
-{\r
-  if (use_isc)\r
-  {\r
-    use_isc = false;\r
-    Shutdown_isc();\r
-  }\r
-\r
-  if (use_mysql)\r
-  {\r
-    use_mysql = false;\r
-    Shutdown_mysql();\r
-  }\r
-}\r
-\r
-/*** ISC protocol mode specific ***/\r
-\r
-void PISC::Start_isc()\r
-{\r
-  uint16_t Port = Config->GetOptionInt("isc_infoserverport");\r
-    if (Port == 0)\r
-    {\r
-        Console->Print("%s Unable to start ISC, isc_infoserverport setting is invalid");\r
-        use_isc = false;\r
-        return;\r
-    }\r
-    Console->Print("Trying to connect to infoserver...", Port);\r
-    // Add function for initial connect here and store the connectioninfo somewhere\r
-}\r
-\r
-void PISC::Update_isc()\r
-{\r
-}\r
-\r
-void PISC::Shutdown_isc()\r
-{\r
-}\r
-\r
-/*** IMySQL mode specific ***/\r
-\r
-void PISC::Start_mysql()\r
-{\r
-  m_server_id = Config->GetOptionInt("isc_server_id");\r
-  mysql_update_intervall = Config->GetOptionInt("isc_update_intervall");\r
-  if (mysql_update_intervall < 10)\r
-  {\r
-    Console->Print("%s value for 'isc_update_intervall' too low (%d). Set to 10 sec.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mysql_update_intervall);\r
-    mysql_update_intervall = 10;\r
-  }\r
-\r
-  mysql_delayed_update_intervall = Config->GetOptionInt("isc_delayed_update_intervall");\r
-  if (mysql_delayed_update_intervall < 0)\r
-  {\r
-    Console->Print("%s value for 'isc_delayed_update_intervall' is invalid (%d). Set to 0 sec (immediate update)", Console->ColorText(YELLOW, BLACK, "[Notice]"), mysql_delayed_update_intervall);\r
-    mysql_delayed_update_intervall = 0;\r
-  }\r
-\r
-  mysql_last_update_time = 0;\r
-  mysql_last_client_count = 0;\r
-  mysql_last_count_decrease_time = 0;\r
-\r
-  Update_mysql();\r
-}\r
-\r
-void PISC::Update_mysql()\r
-{\r
-  bool do_update = false;\r
-  std::time_t t = std::time(NULL);\r
-  int client_count = Server->GetNumClients();\r
-\r
-  if (((t - mysql_last_update_time) >= mysql_update_intervall) || (client_count > mysql_last_client_count))\r
-  {\r
-    do_update = true;\r
-//if(gDevDebug) Console->Print("%s ISC : time or more clients", Console->ColorText(GREEN, BLACK, "[Debug]"));\r
-  }\r
-  else if (client_count < mysql_last_client_count)\r
-  {\r
-    if(mysql_last_count_decrease_time && ((t - mysql_last_count_decrease_time) >= mysql_delayed_update_intervall))\r
-    {\r
-      do_update = true;\r
-//if(gDevDebug) Console->Print("%s ISC : less clients timed out", Console->ColorText(GREEN, BLACK, "[Debug]"));\r
-    }\r
-    else if (!mysql_last_count_decrease_time)\r
-    {\r
-      mysql_last_count_decrease_time = t;\r
-//if(gDevDebug) Console->Print("%s ISC : Starting less clients time count", Console->ColorText(GREEN, BLACK, "[Debug]"));\r
-    }\r
-  }\r
-  else if (mysql_last_count_decrease_time && (client_count == mysql_last_client_count))\r
-  {\r
-    mysql_last_count_decrease_time = 0;\r
-//if(gDevDebug) Console->Print("%s ISC : Canceling less clients time count", Console->ColorText(GREEN, BLACK, "[Debug]"));    \r
-  }\r
-\r
-  if (do_update)\r
-  {\r
-    do_mysql_db_update(client_count);\r
-    mysql_last_client_count = client_count;\r
-    mysql_last_count_decrease_time = 0;\r
-    mysql_last_update_time = std::time(NULL);\r
-  }\r
-}\r
-\r
-void PISC::Shutdown_mysql()\r
-{\r
-  use_mysql = false;\r
-  do_mysql_db_update(0,true);\r
-}\r
-\r
-bool PISC::do_mysql_db_update(int players, bool shutdown)\r
-{\r
-  char query[256];\r
-  snprintf (query, 256, "UPDATE `server_list` SET `s_players` = '%d', `s_lastupdate` = %s WHERE `s_id` = %d LIMIT 1;", players, (shutdown ? "'0'" : "NOW()"), m_server_id);\r
-\r
-//if(gDevDebug) Console->Print("%s Updating Infoserver over MySQL.", Console->ColorText(GREEN, BLACK, "[Debug]"));\r
-  if(MySQL->InfoQuery(query))\r
-  {\r
-    use_mysql = false;\r
-    Console->Print("%s Could not update Infoserver over MySQL. Updating DISABLED. Error was:", Console->ColorText(RED, BLACK, "[ERROR]"));\r
-    MySQL->ShowInfoSQLError();\r
-    return false;\r
-  }\r
-  else\r
-    return true;\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// TODO: - implement ISC protocol
+
+PISC::PISC()
+{
+  use_isc = false;
+  use_mysql = false;
+}
+
+PISC::~PISC()
+{
+}
+
+void PISC::Start()
+{
+  isc_method = Config->GetOptionInt("isc_method");
+
+  if(isc_method & 1)
+  {
+      Console->Print("%s Infoserver updating over MySQL is enabled", Console->ColorText(GREEN, BLACK, "[Info]"));
+      use_mysql = true;
+  }
+  if(isc_method & 2)
+  {
+      Console->Print("%s Infoserver updating over ISC is enabled, update intervall: infoserver: %s", Console->ColorText(GREEN, BLACK, "[Info]"), "?");
+      use_isc = true;
+      Console->Print("%s Infoserver updating over ISC not implemented yet. DISABLED", Console->ColorText(YELLOW, BLACK, "[Notice]"));
+      use_isc = false;
+  }
+  if(!(use_isc || use_mysql))
+  {
+      Console->Print("%s ISC and MySQL are both disabled, infoserver will NOT be updated", Console->ColorText(YELLOW, BLACK, "[Notice]"));
+  }
+
+  if (use_isc)
+    Start_isc();
+
+  if (use_mysql)
+    Start_mysql();
+
+}
+
+void PISC::Update()
+{
+  if (use_isc)
+    Update_isc();
+
+  if (use_mysql)
+    Update_mysql();
+}
+
+void PISC::Shutdown()
+{
+  if (use_isc)
+  {
+    use_isc = false;
+    Shutdown_isc();
+  }
+
+  if (use_mysql)
+  {
+    use_mysql = false;
+    Shutdown_mysql();
+  }
+}
+
+/*** ISC protocol mode specific ***/
+
+void PISC::Start_isc()
+{
+  uint16_t Port = Config->GetOptionInt("isc_infoserverport");
+    if (Port == 0)
+    {
+        Console->Print("%s Unable to start ISC, isc_infoserverport setting is invalid");
+        use_isc = false;
+        return;
+    }
+    Console->Print("Trying to connect to infoserver...", Port);
+    // Add function for initial connect here and store the connectioninfo somewhere
+}
+
+void PISC::Update_isc()
+{
+}
+
+void PISC::Shutdown_isc()
+{
+}
+
+/*** IMySQL mode specific ***/
+
+void PISC::Start_mysql()
+{
+  m_server_id = Config->GetOptionInt("isc_server_id");
+  mysql_update_intervall = Config->GetOptionInt("isc_update_intervall");
+  if (mysql_update_intervall < 10)
+  {
+    Console->Print("%s value for 'isc_update_intervall' too low (%d). Set to 10 sec.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mysql_update_intervall);
+    mysql_update_intervall = 10;
+  }
+
+  mysql_delayed_update_intervall = Config->GetOptionInt("isc_delayed_update_intervall");
+  if (mysql_delayed_update_intervall < 0)
+  {
+    Console->Print("%s value for 'isc_delayed_update_intervall' is invalid (%d). Set to 0 sec (immediate update)", Console->ColorText(YELLOW, BLACK, "[Notice]"), mysql_delayed_update_intervall);
+    mysql_delayed_update_intervall = 0;
+  }
+
+  mysql_last_update_time = 0;
+  mysql_last_client_count = 0;
+  mysql_last_count_decrease_time = 0;
+
+  Update_mysql();
+}
+
+void PISC::Update_mysql()
+{
+  bool do_update = false;
+  std::time_t t = std::time(NULL);
+  int client_count = Server->GetNumClients();
+
+  if (((t - mysql_last_update_time) >= mysql_update_intervall) || (client_count > mysql_last_client_count))
+  {
+    do_update = true;
+//if(gDevDebug) Console->Print("%s ISC : time or more clients", Console->ColorText(GREEN, BLACK, "[Debug]"));
+  }
+  else if (client_count < mysql_last_client_count)
+  {
+    if(mysql_last_count_decrease_time && ((t - mysql_last_count_decrease_time) >= mysql_delayed_update_intervall))
+    {
+      do_update = true;
+//if(gDevDebug) Console->Print("%s ISC : less clients timed out", Console->ColorText(GREEN, BLACK, "[Debug]"));
+    }
+    else if (!mysql_last_count_decrease_time)
+    {
+      mysql_last_count_decrease_time = t;
+//if(gDevDebug) Console->Print("%s ISC : Starting less clients time count", Console->ColorText(GREEN, BLACK, "[Debug]"));
+    }
+  }
+  else if (mysql_last_count_decrease_time && (client_count == mysql_last_client_count))
+  {
+    mysql_last_count_decrease_time = 0;
+//if(gDevDebug) Console->Print("%s ISC : Canceling less clients time count", Console->ColorText(GREEN, BLACK, "[Debug]"));    
+  }
+
+  if (do_update)
+  {
+    do_mysql_db_update(client_count);
+    mysql_last_client_count = client_count;
+    mysql_last_count_decrease_time = 0;
+    mysql_last_update_time = std::time(NULL);
+  }
+}
+
+void PISC::Shutdown_mysql()
+{
+  use_mysql = false;
+  do_mysql_db_update(0,true);
+}
+
+bool PISC::do_mysql_db_update(int players, bool shutdown)
+{
+  char query[256];
+  snprintf (query, 256, "UPDATE `server_list` SET `s_players` = '%d', `s_lastupdate` = %s WHERE `s_id` = %d LIMIT 1;", players, (shutdown ? "'0'" : "NOW()"), m_server_id);
+
+//if(gDevDebug) Console->Print("%s Updating Infoserver over MySQL.", Console->ColorText(GREEN, BLACK, "[Debug]"));
+  if(MySQL->InfoQuery(query))
+  {
+    use_mysql = false;
+    Console->Print("%s Could not update Infoserver over MySQL. Updating DISABLED. Error was:", Console->ColorText(RED, BLACK, "[ERROR]"));
+    MySQL->ShowInfoSQLError();
+    return false;
+  }
+  else
+    return true;
+}
index dc04f9e..b0843de 100644 (file)
@@ -1,64 +1,64 @@
-#pragma once\r
-\r
-#include <chrono>\r
-#include <cstdint>\r
-\r
-#define ISC_VER 2\r
-\r
-// Part of mConStatus bitmask\r
-#define ISC_CONNECTED 1\r
-#define ISC_ADMIN 2\r
-\r
-class PISC {\r
-    private:\r
-        enum PISC_Status\r
-        {\r
-            ISC_NOTCONNECTED,\r
-            ISC_HANDSHAKE01,  // "Hello" msg sent, awaiting answer\r
-            ISC_HANDSHAKE02,  // PW sent, awaiting answer\r
-            ISC_GSDATA01,     // Servername sent, awaiting answer\r
-            ISC_GSDATA02,     // IP, Port & Patchlevel sent, awaiting blabla..\r
-            ISC_GSDATA03,     // Players / Staff onlinecounter sent, ...\r
-            ISC_GSDATA04,     // Minlevel to connect, minlevel to see Playercount, minlevel to see server sent,....\r
-            ISC_CLIENTIDENT,  // Awaiting client identification answer\r
-            ISC_ADMINLOGIN,   // Awaiting answer to Infoserver control login request\r
-            ISC_ICTRL_AUTOACC,// Infoserver control: Awaiting response to AutoAccount command\r
-            ISC_ICTRL_LOGLV,  // Infoserver control: Awaiting response to LoginLevel command\r
-            ISC_ICTRL_RELOAD, // Infoserver control: Awaiting response to Reload command\r
-            ISC_ICTRL_SHUTD,  // Infoserver control: Awaiting response to Shutdown command\r
-            ISC_ICTRL_HIDE,   // Infoserver control: Awaiting response to HidePeople command\r
-            ISC_IDLE          // Updateloop running\r
-        } mLinkStatus;\r
-\r
-        uint16_t mConStatus;     // Bitmask of Connection status\r
-\r
-        int isc_method;\r
-\r
-        bool use_isc;\r
-        char isc_pwd;\r
-\r
-        bool use_mysql;\r
-        int m_server_id;\r
-        time_t mysql_update_intervall;\r
-        time_t mysql_delayed_update_intervall;\r
-        time_t mysql_last_update_time;\r
-        int mysql_last_client_count;\r
-        time_t mysql_last_count_decrease_time;\r
-\r
-        void Start_isc();\r
-        void Update_isc();\r
-        void Shutdown_isc();\r
-\r
-        void Start_mysql();\r
-        void Update_mysql();\r
-        bool do_mysql_db_update(int players, bool shutdown = false);\r
-        void Shutdown_mysql();\r
-\r
-    public:\r
-        PISC();\r
-        ~PISC();\r
-\r
-        void Start();\r
-        void Update();\r
-        void Shutdown();\r
-};\r
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+
+#define ISC_VER 2
+
+// Part of mConStatus bitmask
+#define ISC_CONNECTED 1
+#define ISC_ADMIN 2
+
+class PISC {
+    private:
+        enum PISC_Status
+        {
+            ISC_NOTCONNECTED,
+            ISC_HANDSHAKE01,  // "Hello" msg sent, awaiting answer
+            ISC_HANDSHAKE02,  // PW sent, awaiting answer
+            ISC_GSDATA01,     // Servername sent, awaiting answer
+            ISC_GSDATA02,     // IP, Port & Patchlevel sent, awaiting blabla..
+            ISC_GSDATA03,     // Players / Staff onlinecounter sent, ...
+            ISC_GSDATA04,     // Minlevel to connect, minlevel to see Playercount, minlevel to see server sent,....
+            ISC_CLIENTIDENT,  // Awaiting client identification answer
+            ISC_ADMINLOGIN,   // Awaiting answer to Infoserver control login request
+            ISC_ICTRL_AUTOACC,// Infoserver control: Awaiting response to AutoAccount command
+            ISC_ICTRL_LOGLV,  // Infoserver control: Awaiting response to LoginLevel command
+            ISC_ICTRL_RELOAD, // Infoserver control: Awaiting response to Reload command
+            ISC_ICTRL_SHUTD,  // Infoserver control: Awaiting response to Shutdown command
+            ISC_ICTRL_HIDE,   // Infoserver control: Awaiting response to HidePeople command
+            ISC_IDLE          // Updateloop running
+        } mLinkStatus;
+
+        uint16_t mConStatus;     // Bitmask of Connection status
+
+        int isc_method;
+
+        bool use_isc;
+        char isc_pwd;
+
+        bool use_mysql;
+        int m_server_id;
+        time_t mysql_update_intervall;
+        time_t mysql_delayed_update_intervall;
+        time_t mysql_last_update_time;
+        int mysql_last_client_count;
+        time_t mysql_last_count_decrease_time;
+
+        void Start_isc();
+        void Update_isc();
+        void Shutdown_isc();
+
+        void Start_mysql();
+        void Update_mysql();
+        bool do_mysql_db_update(int players, bool shutdown = false);
+        void Shutdown_mysql();
+
+    public:
+        PISC();
+        ~PISC();
+
+        void Start();
+        void Update();
+        void Shutdown();
+};
index ce2b4b1..5a3a8e5 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-\r
-PItem::PItem(uint32_t ItemID, uint8_t nStackSize, uint8_t CurDur, uint8_t MaxDur, uint8_t Dmg, uint8_t Freq, uint8_t Hand, uint8_t Rng)\r
-{\r
-  mDefItem = GameDefs->Items()->GetDef(ItemID);\r
-  if (mDefItem) {\r
-    mItemID = ItemID;\r
-    mStackable = mDefItem->IsStackable();\r
-    mStackSize = mStackable ? nStackSize : 1;\r
-\r
-    mLoadedAmmoId = 0;\r
-    mLoadedAmmoNb = 0;\r
-\r
-    mPropertiesFlags = 0;\r
-\r
-    mUsedSlots = mMaxSlots = 0;\r
-    mModificators = 0;\r
-\r
-    mConstructorId = 0;\r
-    //mType = mDefItem->GetType();\r
-    //mValue1 = mDefItem->GetValue1();\r
-    //mValue2 = mDefItem->GetValue2();\r
-    //mValue3 = mDefItem->GetValue3();\r
-    //mSizeX = mDefItem->GetSizeX();\r
-    //mSizeY = mDefItem->GetSizeY();\r
-    //mWeight = mDefItem->GetWeight();\r
-    //mFillWeight = mDefItem->GetFillWeight();\r
-    //mQualifier = mDefItem->GetQualifier();\r
-    //mItemGroupID = mDefItem->GetItemGroupID();\r
-    //mBasePrice = mDefItem->GetBasePrice();\r
-    //mTechlevel = mDefItem->GetTechlevel();\r
-    //mItemflags = mDefItem->GetItemflags();\r
-\r
-    //if (!mStackable) // only non-stackable items can have quality stats (?)\r
-    //{\r
-    //  mStackSize = 1;\r
-      mCurDuration = CurDur;\r
-      mMaxDuration = MaxDur;\r
-      mDamages = Dmg;\r
-      mFrequency = Freq;\r
-      mHandling = Hand;\r
-      mRange = Rng;\r
-    //}\r
-  }\r
-  else\r
-  {\r
-    mItemID = 0;\r
-    Console->Print(YELLOW, BLACK, "PItem::PItem: Invalid item ID %d", ItemID);\r
-  }\r
-}\r
-\r
-void PItem::MakeItemStandard(uint8_t GlobalQualityMin, uint8_t GlobalQualityMax)\r
-{\r
-  if(GlobalQualityMin > GlobalQualityMax) GlobalQualityMin = GlobalQualityMax;\r
-\r
-  mCurDuration = 255;\r
-  mMaxDuration = 255;\r
-  if(GlobalQualityMin == GlobalQualityMax)\r
-  {\r
-    mDamages = GlobalQualityMin;\r
-    mFrequency = GlobalQualityMin;\r
-    mHandling = GlobalQualityMin;\r
-    mRange = GlobalQualityMin;\r
-  }\r
-  else\r
-  {\r
-    mDamages = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);\r
-    mFrequency = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);\r
-    mHandling = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);\r
-    mRange = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);\r
-  }\r
-}\r
-\r
-uint32_t PItem::GetItemID()\r
-{\r
-    return mItemID;\r
-}\r
-\r
-int PItem::GetType()\r
-{\r
-    return mDefItem->GetType();\r
-}\r
-\r
-uint8_t PItem::GetItemflags()\r
-{\r
-    return mDefItem->GetItemflags();\r
-}\r
-\r
-const std::string &PItem::GetName() const\r
-{\r
-    return mDefItem->GetName();\r
-}\r
-\r
-uint8_t PItem::GetSizeX()\r
-{\r
-    return mDefItem->GetSizeX();\r
-}\r
-\r
-uint8_t PItem::GetSizeY()\r
-{\r
-    return mDefItem->GetSizeY();\r
-}\r
-\r
-float PItem::GetWeight()\r
-{\r
-    return mStackSize * mDefItem->GetWeight();\r
-}\r
-\r
-float PItem::GetSingleUnitWeight()\r
-{\r
-    return mDefItem->GetWeight();\r
-}\r
-\r
-float PItem::GetFillWeight()\r
-{\r
-    return mDefItem->GetFillWeight();\r
-}\r
-\r
-uint32_t PItem::GetBasePrice()\r
-{\r
-    return mDefItem->GetBasePrice();\r
-}\r
-\r
-uint16_t PItem::GetTechlevel()\r
-{\r
-    return mDefItem->GetTechlevel();\r
-}\r
-\r
-int PItem::GetValue1()\r
-{\r
-    return mDefItem->GetValue1();\r
-}\r
-\r
-int PItem::GetValue2()\r
-{\r
-    return mDefItem->GetValue2();\r
-}\r
-\r
-int PItem::GetValue3()\r
-{\r
-    return mDefItem->GetValue3();\r
-}\r
-\r
-int PItem::GetQualifier()\r
-{\r
-    return mDefItem->GetQualifier();\r
-}\r
-\r
-bool PItem::IsStackable()\r
-{\r
-    return mDefItem->IsStackable();\r
-}\r
-\r
-uint8_t PItem::GetStackSize()\r
-{\r
-    return mStackSize;\r
-}\r
-\r
-uint8_t PItem::AddToStack(uint8_t ItemNb) // returns nb of items not added\r
-{\r
-  uint8_t addedItems = 0;\r
-  if (mStackable)\r
-  {\r
-    addedItems = (ItemNb <= (MAX_ITEMSTACK_SIZE - mStackSize)) ? ItemNb : (MAX_ITEMSTACK_SIZE - mStackSize);\r
-    mStackSize += addedItems;\r
-  }\r
-  return (ItemNb - addedItems);\r
-}\r
-\r
-uint8_t PItem::TakeFromStack(uint8_t ItemNb)\r
-{\r
-  uint8_t retreivedItems = 0;\r
-  if (mStackable)\r
-  {\r
-    retreivedItems = std::min(mStackSize, ItemNb);\r
-    mStackSize -= retreivedItems;\r
-  }\r
-  return retreivedItems;\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+
+PItem::PItem(uint32_t ItemID, uint8_t nStackSize, uint8_t CurDur, uint8_t MaxDur, uint8_t Dmg, uint8_t Freq, uint8_t Hand, uint8_t Rng)
+{
+  mDefItem = GameDefs->Items()->GetDef(ItemID);
+  if (mDefItem) {
+    mItemID = ItemID;
+    mStackable = mDefItem->IsStackable();
+    mStackSize = mStackable ? nStackSize : 1;
+
+    mLoadedAmmoId = 0;
+    mLoadedAmmoNb = 0;
+
+    mPropertiesFlags = 0;
+
+    mUsedSlots = mMaxSlots = 0;
+    mModificators = 0;
+
+    mConstructorId = 0;
+    //mType = mDefItem->GetType();
+    //mValue1 = mDefItem->GetValue1();
+    //mValue2 = mDefItem->GetValue2();
+    //mValue3 = mDefItem->GetValue3();
+    //mSizeX = mDefItem->GetSizeX();
+    //mSizeY = mDefItem->GetSizeY();
+    //mWeight = mDefItem->GetWeight();
+    //mFillWeight = mDefItem->GetFillWeight();
+    //mQualifier = mDefItem->GetQualifier();
+    //mItemGroupID = mDefItem->GetItemGroupID();
+    //mBasePrice = mDefItem->GetBasePrice();
+    //mTechlevel = mDefItem->GetTechlevel();
+    //mItemflags = mDefItem->GetItemflags();
+
+    //if (!mStackable) // only non-stackable items can have quality stats (?)
+    //{
+    //  mStackSize = 1;
+      mCurDuration = CurDur;
+      mMaxDuration = MaxDur;
+      mDamages = Dmg;
+      mFrequency = Freq;
+      mHandling = Hand;
+      mRange = Rng;
+    //}
+  }
+  else
+  {
+    mItemID = 0;
+    Console->Print(YELLOW, BLACK, "PItem::PItem: Invalid item ID %d", ItemID);
+  }
+}
+
+void PItem::MakeItemStandard(uint8_t GlobalQualityMin, uint8_t GlobalQualityMax)
+{
+  if(GlobalQualityMin > GlobalQualityMax) GlobalQualityMin = GlobalQualityMax;
+
+  mCurDuration = 255;
+  mMaxDuration = 255;
+  if(GlobalQualityMin == GlobalQualityMax)
+  {
+    mDamages = GlobalQualityMin;
+    mFrequency = GlobalQualityMin;
+    mHandling = GlobalQualityMin;
+    mRange = GlobalQualityMin;
+  }
+  else
+  {
+    mDamages = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);
+    mFrequency = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);
+    mHandling = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);
+    mRange = (uint8_t) GetRandom(GlobalQualityMax, GlobalQualityMin);
+  }
+}
+
+uint32_t PItem::GetItemID()
+{
+    return mItemID;
+}
+
+int PItem::GetType()
+{
+    return mDefItem->GetType();
+}
+
+uint8_t PItem::GetItemflags()
+{
+    return mDefItem->GetItemflags();
+}
+
+const std::string &PItem::GetName() const
+{
+    return mDefItem->GetName();
+}
+
+uint8_t PItem::GetSizeX()
+{
+    return mDefItem->GetSizeX();
+}
+
+uint8_t PItem::GetSizeY()
+{
+    return mDefItem->GetSizeY();
+}
+
+float PItem::GetWeight()
+{
+    return mStackSize * mDefItem->GetWeight();
+}
+
+float PItem::GetSingleUnitWeight()
+{
+    return mDefItem->GetWeight();
+}
+
+float PItem::GetFillWeight()
+{
+    return mDefItem->GetFillWeight();
+}
+
+uint32_t PItem::GetBasePrice()
+{
+    return mDefItem->GetBasePrice();
+}
+
+uint16_t PItem::GetTechlevel()
+{
+    return mDefItem->GetTechlevel();
+}
+
+int PItem::GetValue1()
+{
+    return mDefItem->GetValue1();
+}
+
+int PItem::GetValue2()
+{
+    return mDefItem->GetValue2();
+}
+
+int PItem::GetValue3()
+{
+    return mDefItem->GetValue3();
+}
+
+int PItem::GetQualifier()
+{
+    return mDefItem->GetQualifier();
+}
+
+bool PItem::IsStackable()
+{
+    return mDefItem->IsStackable();
+}
+
+uint8_t PItem::GetStackSize()
+{
+    return mStackSize;
+}
+
+uint8_t PItem::AddToStack(uint8_t ItemNb) // returns nb of items not added
+{
+  uint8_t addedItems = 0;
+  if (mStackable)
+  {
+    addedItems = (ItemNb <= (MAX_ITEMSTACK_SIZE - mStackSize)) ? ItemNb : (MAX_ITEMSTACK_SIZE - mStackSize);
+    mStackSize += addedItems;
+  }
+  return (ItemNb - addedItems);
+}
+
+uint8_t PItem::TakeFromStack(uint8_t ItemNb)
+{
+  uint8_t retreivedItems = 0;
+  if (mStackable)
+  {
+    retreivedItems = std::min(mStackSize, ItemNb);
+    mStackSize -= retreivedItems;
+  }
+  return retreivedItems;
+}
index fbe9668..dce8925 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-\r
-class PDefItems;\r
-\r
-// TODO: Add CreatorID (for "named" item), CurrentMunitionID, CurrentMunitionNb (for weapons & charge-items: muns,\r
-//        medkit, etc.) to DB, equipped/free slots, & corresponding code\r
-\r
-#define MAX_ITEMSTACK_SIZE 250\r
-\r
-//Type\r
-#define ITEM_TYPE_VARIOUS 0\r
-#define ITEM_TYPE_WEAPON 1\r
-#define ITEM_TYPE_AMMO 2\r
-#define ITEM_TYPE_HEALTH 3\r
-#define ITEM_TYPE_IMPLANT 4\r
-#define ITEM_TYPE_DRUG 5\r
-#define ITEM_TYPE_MOD 6\r
-#define ITEM_TYPE_GFXMOD 7\r
-#define ITEM_TYPE_BLUEPRINT 8\r
-#define ITEM_TYPE_ARMOR 9\r
-#define ITEM_TYPE_PSIMOD 10\r
-#define ITEM_TYPE_PSIMODREADY 11\r
-#define ITEM_TYPE_REPAIR 12\r
-#define ITEM_TYPE_RECYCLER 13\r
-#define ITEM_TYPE_DATACUBE 14\r
-#define ITEM_TYPE_CONSTRUCTOR 15\r
-#define ITEM_TYPE_RESEARCHER 16\r
-#define ITEM_TYPE_IMPLANTER 17\r
-#define ITEM_TYPE_APARTMENTKEY 18\r
-#define ITEM_TYPE_CLANKEY 19\r
-#define ITEM_TYPE_CASHCUBE 20\r
-#define ITEM_TYPE_AUTOWEAPON 21\r
-#define ITEM_TYPE_VHCKEY 22\r
-#define ITEM_TYPE_UNIDENTPART 24\r
-#define ITEM_TYPE_WRECKEDPART 25\r
-#define ITEM_TYPE_SALVAGE 26\r
-#define ITEM_TYPE_VHCCOMPONENT 27\r
-#define ITEM_TYPE_RECORDABLE 28\r
-\r
-// gfxmodflags\r
-#define ITEM_MOD_FLASHLIGHT 1\r
-#define ITEM_MOD_SCOP 2\r
-#define ITEM_MOD_SILENCER 4\r
-#define ITEM_MOD_LASERPOINTER 8\r
-\r
-// itemflags:\r
-#define ITEM_FLAG_RESEARCHABLE 1\r
-#define ITEM_FLAG_NO_DROP 2\r
-#define ITEM_FLAG_NO_MAX_REPAIRE_DECAY 4\r
-#define ITEM_FLAG_AMMO 8 // for loadable ammo\r
-// not sure for ITEM_FLAG_AMMO\r
-\r
-class PItem {\r
-  friend class PContainerEntry;\r
-  friend class PMsgBuilder;\r
-\r
-  private:\r
-    uint32_t mItemID;\r
-    const PDefItems* mDefItem;\r
-\r
-    bool mStackable;\r
-    uint8_t mStackSize;\r
-\r
-    uint32_t mLoadedAmmoId;\r
-    uint8_t mLoadedAmmoNb;\r
-\r
-    uint8_t mPropertiesFlags;\r
-\r
-    uint8_t mCurDuration;\r
-    uint8_t mMaxDuration;\r
-    uint8_t mDamages;\r
-    uint8_t mFrequency;\r
-    uint8_t mHandling;\r
-    uint8_t mRange;\r
-\r
-    uint8_t mUsedSlots;\r
-    uint8_t mMaxSlots;\r
-    uint8_t mSlot[5];\r
-    uint8_t mModificators;\r
-\r
-    uint32_t mConstructorId;\r
-\r
-  public:\r
-    PItem(uint32_t ItemID, uint8_t nStackSize = 1, uint8_t CurDur = 0, uint8_t MaxDur = 0, uint8_t Dmg = 0, uint8_t Freq = 0, uint8_t Hand = 0, uint8_t Rng = 0);\r
-    //~PItem();\r
-    void MakeItemStandard(uint8_t GlobalQualityMin = 120, uint8_t GlobalQualityMax = 180);\r
-\r
-    uint32_t GetItemID();\r
-    int GetType();\r
-    uint8_t GetItemflags();\r
-    const std::string &GetName() const;\r
-    uint8_t GetSizeX();\r
-    uint8_t GetSizeY();\r
-    float GetWeight();\r
-    float GetSingleUnitWeight();\r
-    float GetFillWeight();\r
-    uint32_t GetBasePrice();\r
-    uint16_t GetTechlevel();\r
-    int GetValue1();\r
-    int GetValue2();\r
-    int GetValue3();\r
-    int GetQualifier();\r
-    bool IsStackable();\r
-    uint8_t GetStackSize();\r
-    uint8_t AddToStack(uint8_t ItemNb); // return the nb of items NOT added\r
-    uint8_t TakeFromStack(uint8_t ItemNb); // return the nb of retreived items\r
-\r
-    //mItemGroupID = def->GetItemGroupID();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+class PDefItems;
+
+// TODO: Add CreatorID (for "named" item), CurrentMunitionID, CurrentMunitionNb (for weapons & charge-items: muns,
+//        medkit, etc.) to DB, equipped/free slots, & corresponding code
+
+#define MAX_ITEMSTACK_SIZE 250
+
+//Type
+#define ITEM_TYPE_VARIOUS 0
+#define ITEM_TYPE_WEAPON 1
+#define ITEM_TYPE_AMMO 2
+#define ITEM_TYPE_HEALTH 3
+#define ITEM_TYPE_IMPLANT 4
+#define ITEM_TYPE_DRUG 5
+#define ITEM_TYPE_MOD 6
+#define ITEM_TYPE_GFXMOD 7
+#define ITEM_TYPE_BLUEPRINT 8
+#define ITEM_TYPE_ARMOR 9
+#define ITEM_TYPE_PSIMOD 10
+#define ITEM_TYPE_PSIMODREADY 11
+#define ITEM_TYPE_REPAIR 12
+#define ITEM_TYPE_RECYCLER 13
+#define ITEM_TYPE_DATACUBE 14
+#define ITEM_TYPE_CONSTRUCTOR 15
+#define ITEM_TYPE_RESEARCHER 16
+#define ITEM_TYPE_IMPLANTER 17
+#define ITEM_TYPE_APARTMENTKEY 18
+#define ITEM_TYPE_CLANKEY 19
+#define ITEM_TYPE_CASHCUBE 20
+#define ITEM_TYPE_AUTOWEAPON 21
+#define ITEM_TYPE_VHCKEY 22
+#define ITEM_TYPE_UNIDENTPART 24
+#define ITEM_TYPE_WRECKEDPART 25
+#define ITEM_TYPE_SALVAGE 26
+#define ITEM_TYPE_VHCCOMPONENT 27
+#define ITEM_TYPE_RECORDABLE 28
+
+// gfxmodflags
+#define ITEM_MOD_FLASHLIGHT 1
+#define ITEM_MOD_SCOP 2
+#define ITEM_MOD_SILENCER 4
+#define ITEM_MOD_LASERPOINTER 8
+
+// itemflags:
+#define ITEM_FLAG_RESEARCHABLE 1
+#define ITEM_FLAG_NO_DROP 2
+#define ITEM_FLAG_NO_MAX_REPAIRE_DECAY 4
+#define ITEM_FLAG_AMMO 8 // for loadable ammo
+// not sure for ITEM_FLAG_AMMO
+
+class PItem {
+  friend class PContainerEntry;
+  friend class PMsgBuilder;
+
+  private:
+    uint32_t mItemID;
+    const PDefItems* mDefItem;
+
+    bool mStackable;
+    uint8_t mStackSize;
+
+    uint32_t mLoadedAmmoId;
+    uint8_t mLoadedAmmoNb;
+
+    uint8_t mPropertiesFlags;
+
+    uint8_t mCurDuration;
+    uint8_t mMaxDuration;
+    uint8_t mDamages;
+    uint8_t mFrequency;
+    uint8_t mHandling;
+    uint8_t mRange;
+
+    uint8_t mUsedSlots;
+    uint8_t mMaxSlots;
+    uint8_t mSlot[5];
+    uint8_t mModificators;
+
+    uint32_t mConstructorId;
+
+  public:
+    PItem(uint32_t ItemID, uint8_t nStackSize = 1, uint8_t CurDur = 0, uint8_t MaxDur = 0, uint8_t Dmg = 0, uint8_t Freq = 0, uint8_t Hand = 0, uint8_t Rng = 0);
+    //~PItem();
+    void MakeItemStandard(uint8_t GlobalQualityMin = 120, uint8_t GlobalQualityMax = 180);
+
+    uint32_t GetItemID();
+    int GetType();
+    uint8_t GetItemflags();
+    const std::string &GetName() const;
+    uint8_t GetSizeX();
+    uint8_t GetSizeY();
+    float GetWeight();
+    float GetSingleUnitWeight();
+    float GetFillWeight();
+    uint32_t GetBasePrice();
+    uint16_t GetTechlevel();
+    int GetValue1();
+    int GetValue2();
+    int GetValue3();
+    int GetQualifier();
+    bool IsStackable();
+    uint8_t GetStackSize();
+    uint8_t AddToStack(uint8_t ItemNb); // return the nb of items NOT added
+    uint8_t TakeFromStack(uint8_t ItemNb); // return the nb of retreived items
+
+    //mItemGroupID = def->GetItemGroupID();
+};
index c5b65d7..d153ace 100644 (file)
@@ -1,52 +1,52 @@
-#pragma once\r
-\r
-//#include "version.h"\r
-\r
-//basic includes\r
-//#include "include/external.h"\r
-\r
-//tinns includes\r
-//#include "include/types.h"\r
-//#include "common/netcode.h"\r
-/*\r
-#include "../gamemonkey/gmMachine.h"\r
-#include "../gamemonkey/gmCall.h"\r
-*/\r
-//#include "common/console.h"\r
-//#include "common/misc.h"\r
-\r
-// MySQL Support\r
-/*\r
-#ifdef MYSQL_INC_DIR\r
-#include <mysql/mysql.h>\r
-#else\r
-#include <mysql.h>\r
-#endif\r
-\r
-#include "include/sql.h"\r
-\r
-#include "common/config.h"\r
-#include "common/filesystem.h"\r
-#include "include/defparser.h"\r
-\r
-#include "include/skill.h"\r
-#include "include/chars.h"\r
-#include "include/accounts.h"\r
-#include "include/client.h"\r
-#include "include/server.h"\r
-#include "include/gameserver.h"\r
-#include "include/globals.h"\r
-#include "include/defs.h"\r
-#include "include/zoning.h"\r
-#include "include/item.h"\r
-#include "include/inventory.h"\r
-#include "include/worldactors.h"\r
-#include "include/npc.h"\r
-#include "include/outpost.h"\r
-#include "include/multipart.h"\r
-#include "include/terminal.h"\r
-\r
-#include "include/lua_engine.h"\r
-#include "include/chat.h"\r
-#include "include/commands.h"\r
-#include "include/clientmanager.h" */\r
+#pragma once
+
+//#include "version.h"
+
+//basic includes
+//#include "include/external.h"
+
+//tinns includes
+//#include "include/types.h"
+//#include "common/netcode.h"
+/*
+#include "../gamemonkey/gmMachine.h"
+#include "../gamemonkey/gmCall.h"
+*/
+//#include "common/console.h"
+//#include "common/misc.h"
+
+// MySQL Support
+/*
+#ifdef MYSQL_INC_DIR
+#include <mysql/mysql.h>
+#else
+#include <mysql.h>
+#endif
+
+#include "include/sql.h"
+
+#include "common/config.h"
+#include "common/filesystem.h"
+#include "include/defparser.h"
+
+#include "include/skill.h"
+#include "include/chars.h"
+#include "include/accounts.h"
+#include "include/client.h"
+#include "include/server.h"
+#include "include/gameserver.h"
+#include "include/globals.h"
+#include "include/defs.h"
+#include "include/zoning.h"
+#include "include/item.h"
+#include "include/inventory.h"
+#include "include/worldactors.h"
+#include "include/npc.h"
+#include "include/outpost.h"
+#include "include/multipart.h"
+#include "include/terminal.h"
+
+#include "include/lua_engine.h"
+#include "include/chat.h"
+#include "include/commands.h"
+#include "include/clientmanager.h" */
index c9cd3f9..3456d3a 100644 (file)
@@ -155,160 +155,160 @@ PMessage* PMsgBuilder::BuildCharHelloMsg( PClient* nClient )
     return tmpMsg;
 }
 
-PMessage* PMsgBuilder::BuildReqNPCScriptAnswerMsg( uint32_t nInfoId, std::string *nNPCScript )\r
- {\r
-    PMessage* tmpMsg;\r
\r
-    tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x19;\r
-    *tmpMsg << ( uint16_t )0x0006; // InfoQuery\r
-    *tmpMsg << ( uint16_t )0x0003; // NPC Script\r
-    *tmpMsg << ( uint32_t )nInfoId;\r
-    *tmpMsg << nNPCScript->c_str();\r
\r
-    return tmpMsg;\r
\r
- }\r
\r
-PMessage* PMsgBuilder::BuildYouGotEmailsMsg( PClient* nClient, uint8_t nMailCount )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x0c;\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x1f;\r
-    *tmpMsg << ( uint16_t )nClient->GetLocalID();\r
-    *tmpMsg << ( uint8_t )0x3d;\r
-    *tmpMsg << ( uint8_t )0x0c;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )nMailCount;\r
\r
-    return tmpMsg;\r
- }\r
\r
-PMessage* PMsgBuilder::BuildReceiveDBAnswerMsg( PClient* nClient, PMessage* nResultBuffer, std::string *nCommandName, uint16_t nNumRows, uint16_t nNumFields)\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
-/*    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x2b;\r
-    *tmpMsg << ( uint8_t )0x1a;\r
-    if(nCommandName->length() > 0)\r
-        *tmpMsg << ( uint8_t )0x01;\r
-    else\r
-        *tmpMsg << ( uint8_t )0x00;\r
\r
-     *tmpMsg << ( uint8_t )0x00;\r
-     *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << *nCommandName;\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
\r
-    // 2nd message\r
-    *tmpMsg << ( uint16_t )(13 + nCommandName->length() + nResultBuffer->GetSize()); // ??\r
- */\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x2b;\r
-    *tmpMsg << ( uint8_t )0x17;\r
-    *tmpMsg << ( uint16_t )(nCommandName->length()+1);\r
-    *tmpMsg << ( uint16_t )nNumRows;\r
-    *tmpMsg << ( uint16_t )nNumFields;\r
-    *tmpMsg << *nCommandName;\r
-    *tmpMsg << *nResultBuffer;\r
\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
\r
\r
-    return tmpMsg;\r
-            //len = (unsigned int)strlen(DB);\r
-            //SendBuffer[0] = 0x13;\r
-            //SendBuffer[5] = 11 + len;\r
-            //SendBuffer[6] = 0x03;\r
-            //Network_IncrementUDP (ClientNum);\r
-            //*(unsigned short*)&SendBuffer[7] = Client_Sockets[ClientNum].UDP_ID;\r
-    //      SendBuffer[9] = 0x2b;\r
-    //      SendBuffer[10] = 0x1a;\r
-    //      *(unsigned short*)&SendBuffer[11] = len;\r
-    //      if (num == 0)\r
-    //          SendBuffer[13] = 0x00;\r
-    //      else\r
-    //          SendBuffer[13] = 0x01;\r
-    //      SendBuffer[14] = 0x00;\r
-    //      SendBuffer[15] = 0x00;\r
-    //      strcpy (SendBuffer+16, DB);\r
-    //      plen = 17+len;\r
\r
-    //      SendBuffer[plen] = 13+len+slen;\r
-    //      SendBuffer[plen+1] = 0x03;\r
-    //      Network_IncrementUDP (ClientNum);\r
-    //      *(unsigned short*)&SendBuffer[plen+2] = Client_Sockets[ClientNum].UDP_ID;\r
-    //      *(unsigned short*)&SendBuffer[1] = Client_Sockets[ClientNum].UDP_ID;\r
-    //      *(unsigned short*)&SendBuffer[3] = Client_Sockets[ClientNum].UDP_ID_HIGH;\r
-    //      SendBuffer[plen+4] = 0x2b;\r
-    //      SendBuffer[plen+5] = 0x17;\r
-    //      *(unsigned short*)&SendBuffer[plen+6] = len+1;\r
-    //      *(unsigned short*)&SendBuffer[plen+8] = num;\r
-    //      *(unsigned short*)&SendBuffer[plen+10] = Fields;\r
-    //      //Fieldnum is defined in each DB below\r
-    //      strcpy (SendBuffer+plen+12, DB);\r
-    //      plen += 13+len;\r
\r
-    //      for (i=0;i<slen;i++)\r
-    //          SendBuffer[plen+i] = TempBuffer[i];\r
\r
\r
- }\r
\r
\r
-PMessage* PMsgBuilder::BuildTryAccessAnswerMsg(PClient* nClient, char *nArea, bool nAllowed)\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
-    //uint8_t i = (uint8_t)strlen(nArea);\r
\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << (uint8_t)0x13;\r
-    *tmpMsg << (uint16_t)nClient->GetUDP_ID();\r
-    *tmpMsg << (uint16_t)nClient->GetSessionID();\r
-    *tmpMsg << (uint8_t)0x00;\r
-    *tmpMsg << (uint8_t)0x03;\r
-    *tmpMsg << (uint16_t)nClient->GetUDP_ID();\r
-    *tmpMsg << (uint8_t)0x2b;\r
-    *tmpMsg << (uint8_t)0x1a;\r
-    *tmpMsg << (uint16_t)(strlen(nArea)+1);\r
\r
-    if(nAllowed)\r
-        *tmpMsg << (uint8_t)0x01;\r
-    else\r
-        *tmpMsg << (uint8_t)0x00;\r
\r
-    *tmpMsg << (uint8_t)0x00;\r
-    *tmpMsg << (uint8_t)0x00;\r
-    *tmpMsg << nArea;\r
\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
-    return tmpMsg;\r
- }\r
+PMessage* PMsgBuilder::BuildReqNPCScriptAnswerMsg( uint32_t nInfoId, std::string *nNPCScript )
+ {
+    PMessage* tmpMsg;
+    tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x19;
+    *tmpMsg << ( uint16_t )0x0006; // InfoQuery
+    *tmpMsg << ( uint16_t )0x0003; // NPC Script
+    *tmpMsg << ( uint32_t )nInfoId;
+    *tmpMsg << nNPCScript->c_str();
+    return tmpMsg;
+ }
+PMessage* PMsgBuilder::BuildYouGotEmailsMsg( PClient* nClient, uint8_t nMailCount )
+ {
+    PMessage* tmpMsg = new PMessage();
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x0c;
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x1f;
+    *tmpMsg << ( uint16_t )nClient->GetLocalID();
+    *tmpMsg << ( uint8_t )0x3d;
+    *tmpMsg << ( uint8_t )0x0c;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )nMailCount;
+    return tmpMsg;
+ }
+PMessage* PMsgBuilder::BuildReceiveDBAnswerMsg( PClient* nClient, PMessage* nResultBuffer, std::string *nCommandName, uint16_t nNumRows, uint16_t nNumFields)
+ {
+    PMessage* tmpMsg = new PMessage();
+/*    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x2b;
+    *tmpMsg << ( uint8_t )0x1a;
+    if(nCommandName->length() > 0)
+        *tmpMsg << ( uint8_t )0x01;
+    else
+        *tmpMsg << ( uint8_t )0x00;
+     *tmpMsg << ( uint8_t )0x00;
+     *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << *nCommandName;
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    // 2nd message
+    *tmpMsg << ( uint16_t )(13 + nCommandName->length() + nResultBuffer->GetSize()); // ??
+ */
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x2b;
+    *tmpMsg << ( uint8_t )0x17;
+    *tmpMsg << ( uint16_t )(nCommandName->length()+1);
+    *tmpMsg << ( uint16_t )nNumRows;
+    *tmpMsg << ( uint16_t )nNumFields;
+    *tmpMsg << *nCommandName;
+    *tmpMsg << *nResultBuffer;
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    return tmpMsg;
+            //len = (unsigned int)strlen(DB);
+            //SendBuffer[0] = 0x13;
+            //SendBuffer[5] = 11 + len;
+            //SendBuffer[6] = 0x03;
+            //Network_IncrementUDP (ClientNum);
+            //*(unsigned short*)&SendBuffer[7] = Client_Sockets[ClientNum].UDP_ID;
+    //      SendBuffer[9] = 0x2b;
+    //      SendBuffer[10] = 0x1a;
+    //      *(unsigned short*)&SendBuffer[11] = len;
+    //      if (num == 0)
+    //          SendBuffer[13] = 0x00;
+    //      else
+    //          SendBuffer[13] = 0x01;
+    //      SendBuffer[14] = 0x00;
+    //      SendBuffer[15] = 0x00;
+    //      strcpy (SendBuffer+16, DB);
+    //      plen = 17+len;
+    //      SendBuffer[plen] = 13+len+slen;
+    //      SendBuffer[plen+1] = 0x03;
+    //      Network_IncrementUDP (ClientNum);
+    //      *(unsigned short*)&SendBuffer[plen+2] = Client_Sockets[ClientNum].UDP_ID;
+    //      *(unsigned short*)&SendBuffer[1] = Client_Sockets[ClientNum].UDP_ID;
+    //      *(unsigned short*)&SendBuffer[3] = Client_Sockets[ClientNum].UDP_ID_HIGH;
+    //      SendBuffer[plen+4] = 0x2b;
+    //      SendBuffer[plen+5] = 0x17;
+    //      *(unsigned short*)&SendBuffer[plen+6] = len+1;
+    //      *(unsigned short*)&SendBuffer[plen+8] = num;
+    //      *(unsigned short*)&SendBuffer[plen+10] = Fields;
+    //      //Fieldnum is defined in each DB below
+    //      strcpy (SendBuffer+plen+12, DB);
+    //      plen += 13+len;
+    //      for (i=0;i<slen;i++)
+    //          SendBuffer[plen+i] = TempBuffer[i];
+ }
+PMessage* PMsgBuilder::BuildTryAccessAnswerMsg(PClient* nClient, char *nArea, bool nAllowed)
+ {
+    PMessage* tmpMsg = new PMessage();
+    //uint8_t i = (uint8_t)strlen(nArea);
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << (uint8_t)0x13;
+    *tmpMsg << (uint16_t)nClient->GetUDP_ID();
+    *tmpMsg << (uint16_t)nClient->GetSessionID();
+    *tmpMsg << (uint8_t)0x00;
+    *tmpMsg << (uint8_t)0x03;
+    *tmpMsg << (uint16_t)nClient->GetUDP_ID();
+    *tmpMsg << (uint8_t)0x2b;
+    *tmpMsg << (uint8_t)0x1a;
+    *tmpMsg << (uint16_t)(strlen(nArea)+1);
+    if(nAllowed)
+        *tmpMsg << (uint8_t)0x01;
+    else
+        *tmpMsg << (uint8_t)0x00;
+    *tmpMsg << (uint8_t)0x00;
+    *tmpMsg << (uint8_t)0x00;
+    *tmpMsg << nArea;
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    return tmpMsg;
+ }
 
 PMessage* PMsgBuilder::BuildReqInfoAnswerMsg( PClient* nClient, uint16_t nReqType, uint32_t nInfoId, void* nResponse, uint16_t nResponseLength )
 {
@@ -1463,334 +1463,334 @@ PMessage* PMsgBuilder::BuildSubskillIncMsg( PClient* nClient, uint8_t nSubskill,
 
   return tmpMsg;
 }
- */\r
-// NPC Dialog. Start dialog with NPC\r
-PMessage* PMsgBuilder::BuildNPCStartDialogMsg( PClient* nClient, uint32_t nNPCWorldID, std::string *nDialogScript  )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
-    nClient->IncreaseUDP_ID();\r
\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t ) 0x0000; // UDP Placeholder\r
-    *tmpMsg << ( uint16_t ) 0x0000; // UDP Placeholder\r
-    *tmpMsg << ( uint8_t )0x00; // Message length\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x1f;\r
-    *tmpMsg << ( uint16_t )nClient->GetLocalID();\r
-    *tmpMsg << ( uint8_t )0x18;\r
-    *tmpMsg << ( uint32_t ) nNPCWorldID;\r
\r
-    // Todo: is this correct? random uint32_t value??\r
-    *tmpMsg << ( uint16_t ) GetRandom( 65535, 4369 );\r
-    *tmpMsg << ( uint16_t ) GetRandom( 65535, 4369 );\r
-    *tmpMsg << ( uint32_t ) 0x0000;\r
-    *tmpMsg << nDialogScript->c_str();\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x0a;\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x1f;\r
-    *tmpMsg << ( uint16_t )nClient->GetLocalID();\r
-    *tmpMsg << ( uint8_t )0x1a;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x00;\r
\r
-    tmpMsg->U16Data( 1 ) = nClient->GetUDP_ID();\r
-    tmpMsg->U16Data( 3 ) = nClient->GetSessionID();\r
\r
-    return tmpMsg;\r
- }\r
-// NPC Dialog. Send next node number in lua script to client\r
-PMessage* PMsgBuilder::BuildNPCDialogReplyMsg( PClient* nClient, uint16_t nNextNode, std::vector<int>*nResultBuffer)\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();;\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();;\r
-    *tmpMsg << ( uint8_t )0x00; // SubMessage length;\r
\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();;\r
-    *tmpMsg << ( uint8_t )0x1f;\r
-    *tmpMsg << ( uint16_t )nClient->GetLocalID();\r
-    *tmpMsg << ( uint8_t )0x1a;\r
-    *tmpMsg << ( uint16_t )nNextNode;\r
-    //*tmpMsg << ( uint8_t )nNumResults;\r
-    *tmpMsg << ( uint8_t )nResultBuffer->size();\r
\r
-    std::vector<int>::const_iterator it;\r
\r
-    for(it = nResultBuffer->begin(); it != nResultBuffer->end(); it++)\r
-     {\r
-        *tmpMsg << ( float )*(it);\r
-     }\r
\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
\r
-    return tmpMsg;\r
- }\r
-
-PMessage* PMsgBuilder::BuildNPCBeginAllBuyerTradeMsg( PClient* nClient, int nWorldID )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x00; // Message length\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x1f;\r
-    *tmpMsg << ( uint16_t )nClient->GetLocalID();\r
-    *tmpMsg << ( uint8_t )0x26;\r
-    *tmpMsg << ( uint32_t ) nWorldID;\r
-    *tmpMsg << ( uint8_t )0x01; // Traders inventory\r
-    *tmpMsg << ( uint16_t )0xFFFF; // Traders inventory\r
\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
\r
-    return tmpMsg;\r
- }\r
\r
-PMessage* PMsgBuilder::BuildNPCShoppingListMsg( PClient* nClient, PMessage* nContentList, int nWorldID, uint8_t nItemQuality)\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x00; // Message length\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint8_t )0x1f;\r
-    *tmpMsg << ( uint16_t )nClient->GetLocalID();\r
-    *tmpMsg << ( uint8_t )0x26;\r
-    *tmpMsg << ( uint32_t ) nWorldID;\r
-    *tmpMsg << ( uint8_t )0x01; // Traders inventory\r
-    *tmpMsg << ( uint16_t )( nContentList->GetSize() / 6 ); // List entries\r
-    *tmpMsg << ( uint8_t )nItemQuality; // Items quality\r
-    *tmpMsg << *nContentList;\r
\r
-    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );\r
\r
-    return tmpMsg;\r
- }\r
\r
-// ==========================\r
-PMessage* PMsgBuilder::BuildNPCSingleInfoMsg( PClient* nClient, uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing,\r
-uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nUnknown,\r
-uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName)\r
-// Initial NPC Packet that defines how the NPC look, etc\r
- {\r
-//    uint8_t tMsgLen = 29 + nNpcName->size() + nAngleStr->size() + nCustomName->size();\r
\r
-    PMessage* tmpMsg = new PMessage();\r
-    nClient->IncreaseUDP_ID();\r
\r
-    *tmpMsg << ( uint8_t )0x13; // Begin UDP message\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x00;\r
-     *tmpMsg << ( uint8_t )0x03;\r
-     *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-     *tmpMsg << ( uint8_t )0x28;\r
-     *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x01;\r
-    *tmpMsg << ( uint32_t )nWorldID;\r
-    *tmpMsg << ( uint16_t )nTypeID;\r
-    *tmpMsg << ( uint16_t )nClothing;\r
-    *tmpMsg << ( uint16_t )nNameID;\r
-    *tmpMsg << ( uint16_t )nPosY;\r
-    *tmpMsg << ( uint16_t )nPosZ;\r
-    *tmpMsg << ( uint16_t )nPosX;\r
-     *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint16_t )nUnknown;\r
-    *tmpMsg << ( uint16_t )nTraderID;\r
-    *tmpMsg << nNpcName->c_str();\r
-    *tmpMsg << nAngleStr->c_str();\r
-    if(nCustomName->length() > 1)\r
-        *tmpMsg << nCustomName->c_str();\r
\r
-    (*tmpMsg)[5] = (uint8_t)(tmpMsg->GetSize() - 6);\r
-    return tmpMsg;\r
- }\r
\r
-PMessage* PMsgBuilder::BuildNPCMassInfoMsg( uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing,\r
-uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nHealth,\r
-uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName)\r
-// Initial NPC Packet that defines how the NPC look, etc\r
- {\r
-//    uint8_t tMsgLen = 29 + nNpcName->size() + nAngleStr->size() + nCustomName->size();\r
\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x13; // Begin UDP message\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x03;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint8_t )0x28;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )0x01;\r
-    *tmpMsg << ( uint32_t )nWorldID;\r
-    *tmpMsg << ( uint16_t )nTypeID;\r
-    *tmpMsg << ( uint16_t )nClothing;\r
-    *tmpMsg << ( uint16_t )nNameID;\r
-    *tmpMsg << ( uint16_t )nPosY;\r
-    *tmpMsg << ( uint16_t )nPosZ;\r
-    *tmpMsg << ( uint16_t )nPosX;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint16_t )nHealth;\r
-    *tmpMsg << ( uint16_t )nTraderID;\r
-    *tmpMsg << nNpcName->c_str();\r
-    *tmpMsg << nAngleStr->c_str();\r
-    if(nCustomName->length() > 1)\r
-        *tmpMsg << nCustomName->c_str();\r
\r
-    (*tmpMsg)[5] = (uint8_t)(tmpMsg->GetSize() - 6);\r
-     return tmpMsg;\r
- }\r
\r
-// **************\r
-PMessage* PMsgBuilder::BuildNPCUpdateMsg(uint32_t nWorldID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint8_t nActionBM, uint16_t nHealth, uint8_t nWeaponState, uint8_t nUnknown, uint32_t nTargetID)\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x13;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint8_t )0x00;      // len\r
-    *tmpMsg << ( uint8_t )0x1b;      // NPC Update\r
-    *tmpMsg << ( uint32_t )nWorldID; // NPCs world ID\r
-    *tmpMsg << ( uint8_t )0x1f;      // Parameters\r
-    *tmpMsg << ( uint16_t )nPosY;    // Position Y\r
-    *tmpMsg << ( uint16_t )nPosZ;    // Position Z\r
-    *tmpMsg << ( uint16_t )nPosX;    // Position X\r
-    *tmpMsg << ( uint8_t )nActionBM; // NPCs current action-bitmask\r
-    *tmpMsg << ( uint16_t )nHealth;   // Health value\r
-    if(nTargetID > 0)\r
-        *tmpMsg << ( uint32_t )nTargetID; // WorldID of NPCs target (if any)\r
-    *tmpMsg << ( uint8_t )nUnknown;\r
-    *tmpMsg << ( uint8_t )nWeaponState;\r
\r
-    (*tmpMsg)[5] = (uint8_t)(tmpMsg->GetSize() - 6);\r
\r
-    return tmpMsg;\r
- }\r
-// **************\r
\r
-PMessage* PMsgBuilder::BuildNPCSingleAliveMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x13; // Begin UDP message\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x11;\r
-    *tmpMsg << ( uint8_t )0x1B;\r
-    *tmpMsg << ( uint32_t )nWorldID;\r
-    *tmpMsg << ( uint8_t )0x1F;\r
-    *tmpMsg << ( uint16_t )nY;\r
-    *tmpMsg << ( uint16_t )nZ;\r
-    *tmpMsg << ( uint16_t )nX;\r
-    *tmpMsg << ( uint8_t )nActionStatus;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )nHealth;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )nAction;\r
\r
-    return tmpMsg;\r
- }\r
\r
-PMessage* PMsgBuilder::BuildNPCMassAliveMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x13; // Begin UDP message\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint8_t )0x11;\r
-    *tmpMsg << ( uint8_t )0x1B;\r
-    *tmpMsg << ( uint32_t )nWorldID;\r
-    *tmpMsg << ( uint8_t )0x1F;\r
-    *tmpMsg << ( uint16_t )nY;\r
-    *tmpMsg << ( uint16_t )nZ;\r
-    *tmpMsg << ( uint16_t )nX;\r
-    *tmpMsg << ( uint8_t )nActionStatus;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )nHealth;\r
-    *tmpMsg << ( uint8_t )0x00;\r
-    *tmpMsg << ( uint8_t )nAction;\r
\r
-    return tmpMsg;\r
- }\r
\r
-PMessage* PMsgBuilder::BuildNPCMassUpdateMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x13; // Begin UDP message\r
-     *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint16_t )0x0000;\r
-    *tmpMsg << ( uint8_t )0x15; // Message length\r
-    *tmpMsg << ( uint8_t )0x1b;\r
-    *tmpMsg << ( uint32_t )nWorldID;\r
-    *tmpMsg << ( uint8_t )0x1F;\r
-    *tmpMsg << ( uint16_t )nY;\r
-    *tmpMsg << ( uint16_t )nZ;\r
-    *tmpMsg << ( uint16_t )nX;\r
-    *tmpMsg << ( uint8_t )nActionStatus;\r
-    *tmpMsg << ( uint8_t )0x77; // ?\r
-    *tmpMsg << ( uint8_t )nHealth;\r
-    *tmpMsg << ( uint16_t )nTarget;\r
-    *tmpMsg << ( uint8_t )0x00; // ?\r
-    *tmpMsg << ( uint8_t )0x00; // ?\r
-    *tmpMsg << ( uint8_t )0x00; // ?\r
-    *tmpMsg << ( uint8_t )nAction;\r
\r
-    return tmpMsg;\r
- }\r
\r
-// ==========================\r
\r
-PMessage* PMsgBuilder::BuildNPCSingleUpdateMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction )\r
- {\r
-    PMessage* tmpMsg = new PMessage();\r
\r
-    *tmpMsg << ( uint8_t )0x13; // Begin UDP message\r
-    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();\r
-    *tmpMsg << ( uint16_t )nClient->GetSessionID();\r
-    *tmpMsg << ( uint8_t )0x15; // Message length\r
-    *tmpMsg << ( uint8_t )0x1b;\r
-    *tmpMsg << ( uint32_t )nWorldID;\r
-    *tmpMsg << ( uint8_t )0x1F;\r
-    *tmpMsg << ( uint16_t )nY;\r
-    *tmpMsg << ( uint16_t )nZ;\r
-    *tmpMsg << ( uint16_t )nX;\r
-    *tmpMsg << ( uint8_t )nActionStatus;\r
-    *tmpMsg << ( uint8_t )0x77; // ?\r
-    *tmpMsg << ( uint8_t )nHealth;\r
-    *tmpMsg << ( uint16_t )nTarget;\r
-    *tmpMsg << ( uint8_t )0x00; // ?\r
-    *tmpMsg << ( uint8_t )0x00; // ?\r
-    *tmpMsg << ( uint8_t )0x00; // ?\r
-    *tmpMsg << ( uint8_t )nAction;\r
\r
-    return tmpMsg;\r
- }\r
-// ==========================\r
+ */
+// NPC Dialog. Start dialog with NPC
+PMessage* PMsgBuilder::BuildNPCStartDialogMsg( PClient* nClient, uint32_t nNPCWorldID, std::string *nDialogScript  )
+ {
+    PMessage* tmpMsg = new PMessage();
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t ) 0x0000; // UDP Placeholder
+    *tmpMsg << ( uint16_t ) 0x0000; // UDP Placeholder
+    *tmpMsg << ( uint8_t )0x00; // Message length
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x1f;
+    *tmpMsg << ( uint16_t )nClient->GetLocalID();
+    *tmpMsg << ( uint8_t )0x18;
+    *tmpMsg << ( uint32_t ) nNPCWorldID;
+    // Todo: is this correct? random uint32_t value??
+    *tmpMsg << ( uint16_t ) GetRandom( 65535, 4369 );
+    *tmpMsg << ( uint16_t ) GetRandom( 65535, 4369 );
+    *tmpMsg << ( uint32_t ) 0x0000;
+    *tmpMsg << nDialogScript->c_str();
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x0a;
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x1f;
+    *tmpMsg << ( uint16_t )nClient->GetLocalID();
+    *tmpMsg << ( uint8_t )0x1a;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x00;
+    tmpMsg->U16Data( 1 ) = nClient->GetUDP_ID();
+    tmpMsg->U16Data( 3 ) = nClient->GetSessionID();
+    return tmpMsg;
+ }
+// NPC Dialog. Send next node number in lua script to client
+PMessage* PMsgBuilder::BuildNPCDialogReplyMsg( PClient* nClient, uint16_t nNextNode, std::vector<int>*nResultBuffer)
+ {
+    PMessage* tmpMsg = new PMessage();
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();;
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();;
+    *tmpMsg << ( uint8_t )0x00; // SubMessage length;
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();;
+    *tmpMsg << ( uint8_t )0x1f;
+    *tmpMsg << ( uint16_t )nClient->GetLocalID();
+    *tmpMsg << ( uint8_t )0x1a;
+    *tmpMsg << ( uint16_t )nNextNode;
+    //*tmpMsg << ( uint8_t )nNumResults;
+    *tmpMsg << ( uint8_t )nResultBuffer->size();
+    std::vector<int>::const_iterator it;
+    for(it = nResultBuffer->begin(); it != nResultBuffer->end(); it++)
+     {
+        *tmpMsg << ( float )*(it);
+     }
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    return tmpMsg;
+ }
+
+PMessage* PMsgBuilder::BuildNPCBeginAllBuyerTradeMsg( PClient* nClient, int nWorldID )
+ {
+    PMessage* tmpMsg = new PMessage();
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x00; // Message length
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x1f;
+    *tmpMsg << ( uint16_t )nClient->GetLocalID();
+    *tmpMsg << ( uint8_t )0x26;
+    *tmpMsg << ( uint32_t ) nWorldID;
+    *tmpMsg << ( uint8_t )0x01; // Traders inventory
+    *tmpMsg << ( uint16_t )0xFFFF; // Traders inventory
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    return tmpMsg;
+ }
+PMessage* PMsgBuilder::BuildNPCShoppingListMsg( PClient* nClient, PMessage* nContentList, int nWorldID, uint8_t nItemQuality)
+ {
+    PMessage* tmpMsg = new PMessage();
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x00; // Message length
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint8_t )0x1f;
+    *tmpMsg << ( uint16_t )nClient->GetLocalID();
+    *tmpMsg << ( uint8_t )0x26;
+    *tmpMsg << ( uint32_t ) nWorldID;
+    *tmpMsg << ( uint8_t )0x01; // Traders inventory
+    *tmpMsg << ( uint16_t )( nContentList->GetSize() / 6 ); // List entries
+    *tmpMsg << ( uint8_t )nItemQuality; // Items quality
+    *tmpMsg << *nContentList;
+    ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
+    return tmpMsg;
+ }
+// ==========================
+PMessage* PMsgBuilder::BuildNPCSingleInfoMsg( PClient* nClient, uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing,
+uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nUnknown,
+uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName)
+// Initial NPC Packet that defines how the NPC look, etc
+ {
+//    uint8_t tMsgLen = 29 + nNpcName->size() + nAngleStr->size() + nCustomName->size();
+    PMessage* tmpMsg = new PMessage();
+    nClient->IncreaseUDP_ID();
+    *tmpMsg << ( uint8_t )0x13; // Begin UDP message
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x00;
+     *tmpMsg << ( uint8_t )0x03;
+     *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+     *tmpMsg << ( uint8_t )0x28;
+     *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x01;
+    *tmpMsg << ( uint32_t )nWorldID;
+    *tmpMsg << ( uint16_t )nTypeID;
+    *tmpMsg << ( uint16_t )nClothing;
+    *tmpMsg << ( uint16_t )nNameID;
+    *tmpMsg << ( uint16_t )nPosY;
+    *tmpMsg << ( uint16_t )nPosZ;
+    *tmpMsg << ( uint16_t )nPosX;
+     *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint16_t )nUnknown;
+    *tmpMsg << ( uint16_t )nTraderID;
+    *tmpMsg << nNpcName->c_str();
+    *tmpMsg << nAngleStr->c_str();
+    if(nCustomName->length() > 1)
+        *tmpMsg << nCustomName->c_str();
+    (*tmpMsg)[5] = (uint8_t)(tmpMsg->GetSize() - 6);
+    return tmpMsg;
+ }
+PMessage* PMsgBuilder::BuildNPCMassInfoMsg( uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing,
+uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nHealth,
+uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName)
+// Initial NPC Packet that defines how the NPC look, etc
+ {
+//    uint8_t tMsgLen = 29 + nNpcName->size() + nAngleStr->size() + nCustomName->size();
+    PMessage* tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x13; // Begin UDP message
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x03;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint8_t )0x28;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )0x01;
+    *tmpMsg << ( uint32_t )nWorldID;
+    *tmpMsg << ( uint16_t )nTypeID;
+    *tmpMsg << ( uint16_t )nClothing;
+    *tmpMsg << ( uint16_t )nNameID;
+    *tmpMsg << ( uint16_t )nPosY;
+    *tmpMsg << ( uint16_t )nPosZ;
+    *tmpMsg << ( uint16_t )nPosX;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint16_t )nHealth;
+    *tmpMsg << ( uint16_t )nTraderID;
+    *tmpMsg << nNpcName->c_str();
+    *tmpMsg << nAngleStr->c_str();
+    if(nCustomName->length() > 1)
+        *tmpMsg << nCustomName->c_str();
+    (*tmpMsg)[5] = (uint8_t)(tmpMsg->GetSize() - 6);
+     return tmpMsg;
+ }
+// **************
+PMessage* PMsgBuilder::BuildNPCUpdateMsg(uint32_t nWorldID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint8_t nActionBM, uint16_t nHealth, uint8_t nWeaponState, uint8_t nUnknown, uint32_t nTargetID)
+ {
+    PMessage* tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x13;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint8_t )0x00;      // len
+    *tmpMsg << ( uint8_t )0x1b;      // NPC Update
+    *tmpMsg << ( uint32_t )nWorldID; // NPCs world ID
+    *tmpMsg << ( uint8_t )0x1f;      // Parameters
+    *tmpMsg << ( uint16_t )nPosY;    // Position Y
+    *tmpMsg << ( uint16_t )nPosZ;    // Position Z
+    *tmpMsg << ( uint16_t )nPosX;    // Position X
+    *tmpMsg << ( uint8_t )nActionBM; // NPCs current action-bitmask
+    *tmpMsg << ( uint16_t )nHealth;   // Health value
+    if(nTargetID > 0)
+        *tmpMsg << ( uint32_t )nTargetID; // WorldID of NPCs target (if any)
+    *tmpMsg << ( uint8_t )nUnknown;
+    *tmpMsg << ( uint8_t )nWeaponState;
+    (*tmpMsg)[5] = (uint8_t)(tmpMsg->GetSize() - 6);
+    return tmpMsg;
+ }
+// **************
+PMessage* PMsgBuilder::BuildNPCSingleAliveMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction )
+ {
+    PMessage* tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x13; // Begin UDP message
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x11;
+    *tmpMsg << ( uint8_t )0x1B;
+    *tmpMsg << ( uint32_t )nWorldID;
+    *tmpMsg << ( uint8_t )0x1F;
+    *tmpMsg << ( uint16_t )nY;
+    *tmpMsg << ( uint16_t )nZ;
+    *tmpMsg << ( uint16_t )nX;
+    *tmpMsg << ( uint8_t )nActionStatus;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )nHealth;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )nAction;
+    return tmpMsg;
+ }
+PMessage* PMsgBuilder::BuildNPCMassAliveMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction )
+ {
+    PMessage* tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x13; // Begin UDP message
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint8_t )0x11;
+    *tmpMsg << ( uint8_t )0x1B;
+    *tmpMsg << ( uint32_t )nWorldID;
+    *tmpMsg << ( uint8_t )0x1F;
+    *tmpMsg << ( uint16_t )nY;
+    *tmpMsg << ( uint16_t )nZ;
+    *tmpMsg << ( uint16_t )nX;
+    *tmpMsg << ( uint8_t )nActionStatus;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )nHealth;
+    *tmpMsg << ( uint8_t )0x00;
+    *tmpMsg << ( uint8_t )nAction;
+    return tmpMsg;
+ }
+PMessage* PMsgBuilder::BuildNPCMassUpdateMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction )
+ {
+    PMessage* tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x13; // Begin UDP message
+     *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint16_t )0x0000;
+    *tmpMsg << ( uint8_t )0x15; // Message length
+    *tmpMsg << ( uint8_t )0x1b;
+    *tmpMsg << ( uint32_t )nWorldID;
+    *tmpMsg << ( uint8_t )0x1F;
+    *tmpMsg << ( uint16_t )nY;
+    *tmpMsg << ( uint16_t )nZ;
+    *tmpMsg << ( uint16_t )nX;
+    *tmpMsg << ( uint8_t )nActionStatus;
+    *tmpMsg << ( uint8_t )0x77; // ?
+    *tmpMsg << ( uint8_t )nHealth;
+    *tmpMsg << ( uint16_t )nTarget;
+    *tmpMsg << ( uint8_t )0x00; // ?
+    *tmpMsg << ( uint8_t )0x00; // ?
+    *tmpMsg << ( uint8_t )0x00; // ?
+    *tmpMsg << ( uint8_t )nAction;
+    return tmpMsg;
+ }
+// ==========================
+PMessage* PMsgBuilder::BuildNPCSingleUpdateMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction )
+ {
+    PMessage* tmpMsg = new PMessage();
+    *tmpMsg << ( uint8_t )0x13; // Begin UDP message
+    *tmpMsg << ( uint16_t )nClient->GetUDP_ID();
+    *tmpMsg << ( uint16_t )nClient->GetSessionID();
+    *tmpMsg << ( uint8_t )0x15; // Message length
+    *tmpMsg << ( uint8_t )0x1b;
+    *tmpMsg << ( uint32_t )nWorldID;
+    *tmpMsg << ( uint8_t )0x1F;
+    *tmpMsg << ( uint16_t )nY;
+    *tmpMsg << ( uint16_t )nZ;
+    *tmpMsg << ( uint16_t )nX;
+    *tmpMsg << ( uint8_t )nActionStatus;
+    *tmpMsg << ( uint8_t )0x77; // ?
+    *tmpMsg << ( uint8_t )nHealth;
+    *tmpMsg << ( uint16_t )nTarget;
+    *tmpMsg << ( uint8_t )0x00; // ?
+    *tmpMsg << ( uint8_t )0x00; // ?
+    *tmpMsg << ( uint8_t )0x00; // ?
+    *tmpMsg << ( uint8_t )nAction;
+    return tmpMsg;
+ }
+// ==========================
 PMessage* PMsgBuilder::BuildSubskillIncMsg( PClient* nClient, uint8_t nSubskill, uint16_t nSkillPoints )
 {
     PMessage* tmpMsg = new PMessage( 33 );
@@ -3612,8 +3612,8 @@ PMessage* PMsgBuilder::BuildNpcCleanupMsg( uint32_t nNpcId, uint8_t nCmd )
     ( *tmpMsg )[5] = ( uint8_t )( tmpMsg->GetSize() - 6 );
 
     return tmpMsg;
- }\r
\r
+ }
 
 /*
 void Cmd_GiveItem (int ItemId, int Amount, int ClientNum)
index df307f5..5e8d2d1 100644 (file)
@@ -48,32 +48,32 @@ public:
     // Temp. NPC update message for testing
     PMessage* BuildNpcDeathMsg( PClient* nClient, uint32_t nNpcId, uint8_t unknown1 = 0x4a, uint8_t npcAction = 0x1e );
 
-    PMessage* BuildNPCMassInfoMsg( uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing, uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nHealth, uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName);\r
-    PMessage* BuildNPCMassAliveMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction );\r
-    PMessage* BuildNPCMassUpdateMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction );\r
-    // Moved here since its a zone broadcast!\r
-    PMessage* BuildNpcCleanupMsg( uint32_t nNpcId, uint8_t nCmd = 6 ); // see implementation about nCmd\r
+    PMessage* BuildNPCMassInfoMsg( uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing, uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nHealth, uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName);
+    PMessage* BuildNPCMassAliveMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction );
+    PMessage* BuildNPCMassUpdateMsg( uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction );
+    // Moved here since its a zone broadcast!
+    PMessage* BuildNpcCleanupMsg( uint32_t nNpcId, uint8_t nCmd = 6 ); // see implementation about nCmd
 
 // Following methods for unicast messages DO include UDP_ID increment and
 // UDP_ID / SessionID setting when needed (at least for now)
-    PMessage* BuildOutpostClanInfoMsg( PClient* nClient, uint32_t nClanID, uint8_t nFaction );\r
-    PMessage* BuildTryAccessAnswerMsg(PClient* nClient, char *nArea, bool nAllowed);\r
-    PMessage* BuildReceiveDBAnswerMsg( PClient* nClient, PMessage* nResultBuffer, std::string* nCommandName, uint16_t nNumRows, uint16_t nNumFields);\r
-    PMessage* BuildYouGotEmailsMsg( PClient* nClient, uint8_t nMailCount );\r
\r
-    PMessage* BuildNPCStartDialogMsg( PClient* nClient, uint32_t nNPCWorldID, std::string *nDialogScript  );\r
-    PMessage* BuildNPCDialogReplyMsg( PClient* nClient, uint16_t nNextNode, std::vector<int>*nResultBuffer);\r
-    PMessage* BuildReqNPCScriptAnswerMsg( uint32_t nInfoId, std::string *nNPCScript );\r
-    PMessage* BuildNPCShoppingListMsg( PClient* nClient, PMessage* nContentList, int nWorldID, uint8_t nItemQuality);\r
-    PMessage* BuildNPCBeginAllBuyerTradeMsg( PClient* nClient, int nWorldID );\r
\r
-    PMessage* BuildNPCSingleInfoMsg( PClient* nClient, uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing, uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nHealth, uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName);\r
-    PMessage* BuildNPCSingleAliveMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction );\r
-    PMessage* BuildNPCSingleUpdateMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction );\r
\r
-    // NEW for testing. Combined update message\r
-    PMessage* BuildNPCUpdateMsg(uint32_t nWorldID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint8_t nActionBM, uint16_t nHealth, uint8_t nWeaponState, uint8_t nUnknown, uint32_t nTargetID = 0);\r
\r
+    PMessage* BuildOutpostClanInfoMsg( PClient* nClient, uint32_t nClanID, uint8_t nFaction );
+    PMessage* BuildTryAccessAnswerMsg(PClient* nClient, char *nArea, bool nAllowed);
+    PMessage* BuildReceiveDBAnswerMsg( PClient* nClient, PMessage* nResultBuffer, std::string* nCommandName, uint16_t nNumRows, uint16_t nNumFields);
+    PMessage* BuildYouGotEmailsMsg( PClient* nClient, uint8_t nMailCount );
+    PMessage* BuildNPCStartDialogMsg( PClient* nClient, uint32_t nNPCWorldID, std::string *nDialogScript  );
+    PMessage* BuildNPCDialogReplyMsg( PClient* nClient, uint16_t nNextNode, std::vector<int>*nResultBuffer);
+    PMessage* BuildReqNPCScriptAnswerMsg( uint32_t nInfoId, std::string *nNPCScript );
+    PMessage* BuildNPCShoppingListMsg( PClient* nClient, PMessage* nContentList, int nWorldID, uint8_t nItemQuality);
+    PMessage* BuildNPCBeginAllBuyerTradeMsg( PClient* nClient, int nWorldID );
+    PMessage* BuildNPCSingleInfoMsg( PClient* nClient, uint32_t nWorldID, uint16_t nTypeID, uint16_t nClothing, uint16_t nNameID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint16_t nHealth, uint16_t nTraderID, std::string *nAngleStr, std::string *nNpcName, std::string *nCustomName);
+    PMessage* BuildNPCSingleAliveMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint8_t nAction );
+    PMessage* BuildNPCSingleUpdateMsg( PClient* nClient, uint32_t nWorldID, uint16_t nX, uint16_t nY, uint16_t nZ, uint8_t nActionStatus, uint8_t nHealth, uint16_t nTarget, uint8_t nAction );
+    // NEW for testing. Combined update message
+    PMessage* BuildNPCUpdateMsg(uint32_t nWorldID, uint16_t nPosY, uint16_t nPosZ, uint16_t nPosX, uint8_t nActionBM, uint16_t nHealth, uint8_t nWeaponState, uint8_t nUnknown, uint32_t nTargetID = 0);
     PMessage* BuildReqInfoAnswerMsg( PClient* nClient, uint16_t nReqType, uint32_t nInfoId, void* nResponse, uint16_t nResponseLength );
 
     PMessage* BuildPacket0Msg( PClient* nClient );
index bf585b9..b08c947 100644 (file)
@@ -10,29 +10,29 @@ void PNPC::PushUpdateTimer()
 };
 
 // Reload LUA script while running, in case we modified it and dont want to restart the entire server
-bool PNPC::ReloadLUAScript()\r
-{\r
-    // Erase current LUA script\r
-    mLUAFile = "";\r
-\r
-    // Reload it\r
-    return LoadLUAScript();\r
-}\r
+bool PNPC::ReloadLUAScript()
+{
+    // Erase current LUA script
+    mLUAFile = "";
+
+    // Reload it
+    return LoadLUAScript();
+}
 
 bool PNPC::DEF_Load(uint32_t nWorldID)
  {
     if ( gDevDebug ) Console->Print( "[DEBUG] Now loading NPC data for NPC id %d from DEF", mWorldID );
     const PNPCTemplate* t_defNPC = Worlds->GetWorld(nWorldID)->GetNPCTemplate(mWorldID);
 
-    mNameID = (uint16_t)t_defNPC->GetNPCTypeID(); // 16 or 32??\r
-    const PDefNpc* t_NpcTypeDef = GameDefs->Npcs()->GetDef(mNameID);\r
-    if(!t_NpcTypeDef)\r
-    {\r
-        Console->Print("%s [PNPC::DEF_Load()] Unknown NPC Type %d in .dat file found", Console->ColorText(RED,BLACK, "[Error]"), mNameID);\r
-        return false;\r
+    mNameID = (uint16_t)t_defNPC->GetNPCTypeID(); // 16 or 32??
+    const PDefNpc* t_NpcTypeDef = GameDefs->Npcs()->GetDef(mNameID);
+    if(!t_NpcTypeDef)
+    {
+        Console->Print("%s [PNPC::DEF_Load()] Unknown NPC Type %d in .dat file found", Console->ColorText(RED,BLACK, "[Error]"), mNameID);
+        return false;
     }
 
-    // TODO: Find out what exactly these TypeID and ClothingID values do and where they are generated/read\r
+    // TODO: Find out what exactly these TypeID and ClothingID values do and where they are generated/read
     // Possible (working) solution: Random seed for name generation that happens clientside
     mTypeID = GetRandom(32767, 1);
     mClothing = GetRandom(32767, 1);
@@ -43,7 +43,7 @@ bool PNPC::DEF_Load(uint32_t nWorldID)
     mPosZ = t_defNPC->GetPosZ()+32768;
     mAngle = atoi( t_defNPC->GetAngle().c_str() );
     mLoot = t_NpcTypeDef->GetLoot();
-    mHealth = t_NpcTypeDef->GetHealth() * NPC_HEALTHFACTOR;\r
+    mHealth = t_NpcTypeDef->GetHealth() * NPC_HEALTHFACTOR;
     mMaxHealth = mHealth;
     mTrader = t_defNPC->GetTradeID();
     mFaction = t_NpcTypeDef->GetFaction();
@@ -51,254 +51,254 @@ bool PNPC::DEF_Load(uint32_t nWorldID)
     mFromDEF = true;
 
     mName = t_defNPC->GetActorName();
-\r
-\r
-    // Load dialogscript for this NPC right uppon startup\r
-    mDialogScript = t_NpcTypeDef->GetDialogScript();\r
-    CleanUpString(&mDialogScript);\r
-\r
-    // Try to load any lua scripts\r
-    // Checks are done in target function\r
-    LoadLUAScript();\r
+
+
+    // Load dialogscript for this NPC right uppon startup
+    mDialogScript = t_NpcTypeDef->GetDialogScript();
+    CleanUpString(&mDialogScript);
+
+    // Try to load any lua scripts
+    // Checks are done in target function
+    LoadLUAScript();
     if ( gDevDebug ) Console->Print( "[DEBUG] NPC: WID:%d NID:%d TID:%d CL:%d PX:%d PY:%d PZ:%d ", mWorldID, mNameID, mTypeID, mClothing, mPosX, mPosY, mPosZ);
-    if ( gDevDebug ) Console->Print( "ANG:%d HITPOINTS:%d TRADE:%d LOOT:%d NAME:%s CNAME:%s CUSTOMSCRIPT:%s", mAngle, mHealth, mTrader, mLoot, mName.c_str(), mCustomName.c_str(), mCustomLua.c_str() );\r
+    if ( gDevDebug ) Console->Print( "ANG:%d HITPOINTS:%d TRADE:%d LOOT:%d NAME:%s CNAME:%s CUSTOMSCRIPT:%s", mAngle, mHealth, mTrader, mLoot, mName.c_str(), mCustomName.c_str(), mCustomLua.c_str() );
     if ( gDevDebug ) Console->Print( "DIALOGSCR:%s", mDialogScript.c_str() );
     return true;
  }
-\r
-bool PNPC::SQL_Load()\r
-{\r
-    if ( gDevDebug ) Console->Print( "[DEBUG] Now loading NPC data for NPC id %d from SQL", mID );\r
-    MYSQL_RES *result = NULL;\r
-    MYSQL_ROW row;\r
-    char query[100];\r
-\r
-    snprintf( query, 100, "SELECT * FROM `npc_spawns` WHERE `npc_id` = %d", mID );\r
-    if ( gDevDebug ) Console->Print( "[DEBUG] Executing query %s", query );\r
-    result = MySQL->GameResQuery( query );\r
-    if ( result == NULL )\r
-    {\r
-        Console->Print( RED, BLACK, "PNPC::SQL_Load could not load NPC definition" );\r
-        Console->Print( "Query was:" );\r
-        Console->Print( "%s", query );\r
-        MySQL->ShowGameSQLError();\r
-        return false;\r
-    }\r
-    if ( mysql_num_rows( result ) == 0 )\r
-    {\r
-        if ( gDevDebug ) Console->Print( "[DEBUG] No NPCs found, returning false" );\r
-        MySQL->FreeGameSQLResult( result );\r
-        return false;\r
-    }\r
-    else if ( mysql_num_rows( result ) > 1 )\r
-    {\r
-        Console->Print( RED, BLACK, "PNPC::SQL_Load Duplicate entry for NPC %d", mID );\r
-        MySQL->FreeGameSQLResult( result );\r
-        return false;\r
-    }\r
-    if ( gDevDebug ) Console->Print( "[DEBUG] One NPC found for my ID. Now grabbing data..." );\r
-    row = mysql_fetch_row( result );\r
-\r
-    mWorldID = atoi( row[npc_worldid] );\r
-    mNameID = atoi( row[npc_nameid] );\r
-    mTypeID = atoi( row[npc_typeid] );\r
-    mClothing = atoi( row[npc_clothing] );\r
-    mPosX = atoi( row[npc_x] );\r
-    mPosY = atoi( row[npc_y] );\r
-    mPosZ = atoi( row[npc_z] );\r
-    mAngle = atoi( row[npc_angle] );\r
-    mLoot = atoi( row[npc_loot] );\r
-    mHealth = atoi( row[npc_unknown] );\r
-    mMaxHealth = mHealth;\r
-    mTrader = atoi( row[npc_trader] );\r
-    mItemQuality = atoi( row[npc_shop_quality] );\r
-    if(atoi(row[npc_scripting]) == 1)\r
-        mScripting = true;\r
-    else\r
-        mScripting = false;\r
-\r
-    if ( row[npc_name] != NULL )\r
-        mName = row[npc_name];\r
-\r
-    if ( row[npc_customname] != NULL )\r
-        mCustomName = row[npc_customname];\r
-\r
-    if ( row[npc_customscript] != NULL )\r
-        mCustomLua = row[npc_customscript];\r
-\r
-    // Now make sure we have an valid NPC here. Besides we need some more information\r
-    const PDefNpc* t_npc = GameDefs->Npcs()->GetDef(mNameID);\r
-    if(!t_npc)\r
-    {\r
-        Console->Print( RED, BLACK, "PNPC::SQL_Load Invalid NPC Type found; SQL ID: %d", mID );\r
-        return false;\r
-    }\r
-    mFaction = t_npc->GetFaction();\r
-\r
-    // Load dialogscript for this NPC right uppon startup\r
-    // !-> Only if no custom lua script is attached <-!\r
-    if(mCustomLua.length() < 1)\r
-    {\r
-        if(t_npc->GetDialogScript().length() > 3)\r
-        {\r
-            size_t tfound;\r
-            std::string t_dialogscript = t_npc->GetDialogScript();\r
-            std::string t_replacechr ("\"");\r
-\r
-            tfound = t_dialogscript.find(t_replacechr);\r
-            while(tfound != std::string::npos)\r
-            {\r
-                t_dialogscript.replace(tfound, 1, " ");\r
-                tfound = t_dialogscript.find( t_replacechr, tfound +1 );\r
-            }\r
-            Trim(&t_dialogscript);\r
-            if(t_dialogscript.length() > 1)\r
-            {\r
-                mDialogScript = t_dialogscript;\r
-            }\r
-        }\r
-    }\r
-    // Try to load any lua scripts\r
-    // Checks are done in target function\r
-    LoadLUAScript();\r
-\r
-    if ( gDevDebug ) Console->Print( "[DEBUG] NPC: WID:%d NID:%d TID:%d CL:%d PX:%d PY:%d PZ:%d ", mWorldID, mNameID, mTypeID, mClothing, mPosX, mPosY, mPosZ);\r
-    if ( gDevDebug ) Console->Print( "ANG:%d HITPTS:%d TRADE:%d LOOT:%d NAME:%s CNAME:%s CUSTOMSCRIPT:%s", mAngle, mHealth, mTrader, mLoot, mName.c_str(), mCustomName.c_str(), mCustomLua.c_str() );\r
-    if ( gDevDebug ) Console->Print( "DIALOGSCR:%s", mDialogScript.c_str() );\r
-    MySQL->FreeGameSQLResult( result );\r
-    return true;\r
-}\r
-\r
-bool PNPC::LoadLUAScript()\r
-{\r
-    uint32_t tFileLen = 0;\r
-    PFile* fLua = NULL;\r
-    std::string tLuaFile = "";\r
-    std::string tHDRFile = "";\r
-\r
-    // Load LUA script and include the correct header file\r
-    // based in mDialogScript\r
-    // if mDialogScript is empty, look at mCustomLua and load this file. Standart include header for custom\r
-    // script files is dialogheader.lua since we dont know (yet) what standart header the NC Client uses\r
-    // for custom loaded scripts.\r
-\r
-    if(mDialogScript.length() > 1)\r
-    {\r
-        // Get LUA filename from defs\r
-        const PDefScripts* tDefScripts = NULL;\r
-        std::map<int, PDefScripts*>::const_iterator itScrStart = GameDefs->Scripts()->ConstIteratorBegin();\r
-        std::map<int, PDefScripts*>::const_iterator itScrEnd = GameDefs->Scripts()->ConstIteratorEnd();\r
-        for ( std::map<int, PDefScripts*>::const_iterator i = itScrStart; i != itScrEnd; i++ )\r
-        {\r
-            tDefScripts = i->second;\r
-    //        Console->Print("[DEBUG PNPC::LoadLUAScript] Identifier: [%s] LUA: [%s]", tDefScripts->GetIdentifier().c_str(), tDefScripts->GetLuaFile().c_str());\r
-\r
-            if(tDefScripts->GetIdentifier().compare(mDialogScript) == 0)\r
-            {\r
-                break;\r
-            }\r
-        }\r
-        // If we left the loop without an positive match.. false!\r
-        if(tDefScripts->GetIdentifier().compare(mDialogScript) != 0)\r
-        {\r
-            return false;\r
-        }\r
-\r
-        // Assign our LUA file to load later\r
-        tLuaFile = tDefScripts->GetLuaFile();\r
-        // MaKe ThE sTrInG aLl lowercase! :)\r
-        std::transform(tLuaFile.begin(), tLuaFile.end(), tLuaFile.begin(), (int(*)(int))std::tolower);\r
-\r
-\r
-        // We only have 2 headerfiles, so this one is hardcoded\r
-        if(tDefScripts->GetScriptHeader() == "DIALOGHEADER")\r
-        {\r
-            tHDRFile = "scripts/lua/dialogheader.lua";\r
-        }\r
-        else if(tDefScripts->GetScriptHeader() == "MISSIONHEADER")\r
-        {\r
-            tHDRFile = "scripts/lua/missionheader.lua";\r
-        }\r
-    }\r
-    // Customlua is set?\r
-    else if(mCustomLua.length() > 1)\r
-    {\r
-        // Assign lua file and header\r
-        tLuaFile = mCustomLua;\r
-        tHDRFile = "scripts/lua/dialogheader.lua";\r
-    }\r
-    else\r
-    {\r
-        // No LUA Scripts to load. Skipping\r
-        return true;\r
-    }\r
-\r
-    // Load HEADER file\r
-    fLua = Filesystem->Open( "", tHDRFile.c_str(), Config->GetOption( "nc_data_path" ) );\r
-    if(fLua)\r
-    {\r
-        tFileLen = fLua->GetSize();\r
-        char* t_content = new char[tFileLen+1];\r
-        memset(t_content, '\0', tFileLen+1);\r
-\r
-        fLua->Read( t_content, tFileLen );\r
-        Filesystem->Close( fLua );\r
-        mLUAFile = t_content;\r
-        delete t_content;\r
-        if (gDevDebug) Console->Print( "%s [PNPC::LoadLUAScript] Loaded LUA Header Script %s", Console->ColorText( GREEN, BLACK, "[SUCCESS]" ), tHDRFile.c_str() );\r
-    }\r
-    else\r
-    {\r
-        Console->Print( "%s [PNPC::LoadLUAScript] Unable to load LUA Header script %s NPC is now DISABLED for scripting", Console->ColorText( RED, BLACK, "[ERROR]" ), tLuaFile.c_str() );\r
-        // We encountered an error while loading. Make sure this NPC will never act as Dialog NPC!\r
-        mLUAFile = "";\r
-        mCustomLua = "";\r
-        mDialogScript = "";\r
-        return false;\r
-    }\r
-\r
-    // Reset vars\r
-    tFileLen = 0;\r
-    fLua = NULL;\r
-\r
-    fLua = Filesystem->Open( "", tLuaFile.c_str(), Config->GetOption( "nc_data_path" ) );\r
-    if(fLua)\r
-    {\r
-        tFileLen = fLua->GetSize();\r
-        char* t_content = new char[tFileLen+1];\r
-        memset(t_content, '\0', tFileLen+1);\r
-\r
-        fLua->Read( t_content, tFileLen );\r
-        Filesystem->Close( fLua );\r
-        mLUAFile += t_content;  // APPEND the script to our existing lua headerfile\r
-        delete t_content;\r
-        if (gDevDebug) Console->Print( "%s [PNPC::LoadLUAScript] Loaded LUA Script %s", Console->ColorText( GREEN, BLACK, "[SUCCESS]" ), tLuaFile.c_str() );\r
-        //Console->Print( "%s", mLUAFile.c_str() );\r
-    }\r
-    else\r
-    {\r
-        Console->Print( "%s [PNPC::LoadLUAScript] Unable to load LUA Script %s NPC is now DISABLED for scripting", Console->ColorText( RED, BLACK, "[ERROR]" ), tLuaFile.c_str() );\r
-        // We encountered an error while loading. Make sure this NPC will never act as Dialog NPC!\r
-        mLUAFile = "";\r
-        mCustomLua = "";\r
-        mDialogScript = "";\r
-        return false;\r
-    }\r
-    // LUA file prepared. Check if LUA file is valid\r
-    if(LuaEngine->CheckLUAFile(mLUAFile) == true)\r
-    {\r
-        // Everything is fine. NPC is ready for action\r
-        return true;\r
-    }\r
-    else\r
-    {\r
-        // LUA file seems to be corrupt\r
-        mLUAFile = "";\r
-        mCustomLua = "";\r
-        mDialogScript = "";\r
-        return false;\r
-    }\r
-}\r
+
+bool PNPC::SQL_Load()
+{
+    if ( gDevDebug ) Console->Print( "[DEBUG] Now loading NPC data for NPC id %d from SQL", mID );
+    MYSQL_RES *result = NULL;
+    MYSQL_ROW row;
+    char query[100];
+
+    snprintf( query, 100, "SELECT * FROM `npc_spawns` WHERE `npc_id` = %d", mID );
+    if ( gDevDebug ) Console->Print( "[DEBUG] Executing query %s", query );
+    result = MySQL->GameResQuery( query );
+    if ( result == NULL )
+    {
+        Console->Print( RED, BLACK, "PNPC::SQL_Load could not load NPC definition" );
+        Console->Print( "Query was:" );
+        Console->Print( "%s", query );
+        MySQL->ShowGameSQLError();
+        return false;
+    }
+    if ( mysql_num_rows( result ) == 0 )
+    {
+        if ( gDevDebug ) Console->Print( "[DEBUG] No NPCs found, returning false" );
+        MySQL->FreeGameSQLResult( result );
+        return false;
+    }
+    else if ( mysql_num_rows( result ) > 1 )
+    {
+        Console->Print( RED, BLACK, "PNPC::SQL_Load Duplicate entry for NPC %d", mID );
+        MySQL->FreeGameSQLResult( result );
+        return false;
+    }
+    if ( gDevDebug ) Console->Print( "[DEBUG] One NPC found for my ID. Now grabbing data..." );
+    row = mysql_fetch_row( result );
+
+    mWorldID = atoi( row[npc_worldid] );
+    mNameID = atoi( row[npc_nameid] );
+    mTypeID = atoi( row[npc_typeid] );
+    mClothing = atoi( row[npc_clothing] );
+    mPosX = atoi( row[npc_x] );
+    mPosY = atoi( row[npc_y] );
+    mPosZ = atoi( row[npc_z] );
+    mAngle = atoi( row[npc_angle] );
+    mLoot = atoi( row[npc_loot] );
+    mHealth = atoi( row[npc_unknown] );
+    mMaxHealth = mHealth;
+    mTrader = atoi( row[npc_trader] );
+    mItemQuality = atoi( row[npc_shop_quality] );
+    if(atoi(row[npc_scripting]) == 1)
+        mScripting = true;
+    else
+        mScripting = false;
+
+    if ( row[npc_name] != NULL )
+        mName = row[npc_name];
+
+    if ( row[npc_customname] != NULL )
+        mCustomName = row[npc_customname];
+
+    if ( row[npc_customscript] != NULL )
+        mCustomLua = row[npc_customscript];
+
+    // Now make sure we have an valid NPC here. Besides we need some more information
+    const PDefNpc* t_npc = GameDefs->Npcs()->GetDef(mNameID);
+    if(!t_npc)
+    {
+        Console->Print( RED, BLACK, "PNPC::SQL_Load Invalid NPC Type found; SQL ID: %d", mID );
+        return false;
+    }
+    mFaction = t_npc->GetFaction();
+
+    // Load dialogscript for this NPC right uppon startup
+    // !-> Only if no custom lua script is attached <-!
+    if(mCustomLua.length() < 1)
+    {
+        if(t_npc->GetDialogScript().length() > 3)
+        {
+            size_t tfound;
+            std::string t_dialogscript = t_npc->GetDialogScript();
+            std::string t_replacechr ("\"");
+
+            tfound = t_dialogscript.find(t_replacechr);
+            while(tfound != std::string::npos)
+            {
+                t_dialogscript.replace(tfound, 1, " ");
+                tfound = t_dialogscript.find( t_replacechr, tfound +1 );
+            }
+            Trim(&t_dialogscript);
+            if(t_dialogscript.length() > 1)
+            {
+                mDialogScript = t_dialogscript;
+            }
+        }
+    }
+    // Try to load any lua scripts
+    // Checks are done in target function
+    LoadLUAScript();
+
+    if ( gDevDebug ) Console->Print( "[DEBUG] NPC: WID:%d NID:%d TID:%d CL:%d PX:%d PY:%d PZ:%d ", mWorldID, mNameID, mTypeID, mClothing, mPosX, mPosY, mPosZ);
+    if ( gDevDebug ) Console->Print( "ANG:%d HITPTS:%d TRADE:%d LOOT:%d NAME:%s CNAME:%s CUSTOMSCRIPT:%s", mAngle, mHealth, mTrader, mLoot, mName.c_str(), mCustomName.c_str(), mCustomLua.c_str() );
+    if ( gDevDebug ) Console->Print( "DIALOGSCR:%s", mDialogScript.c_str() );
+    MySQL->FreeGameSQLResult( result );
+    return true;
+}
+
+bool PNPC::LoadLUAScript()
+{
+    uint32_t tFileLen = 0;
+    PFile* fLua = NULL;
+    std::string tLuaFile = "";
+    std::string tHDRFile = "";
+
+    // Load LUA script and include the correct header file
+    // based in mDialogScript
+    // if mDialogScript is empty, look at mCustomLua and load this file. Standart include header for custom
+    // script files is dialogheader.lua since we dont know (yet) what standart header the NC Client uses
+    // for custom loaded scripts.
+
+    if(mDialogScript.length() > 1)
+    {
+        // Get LUA filename from defs
+        const PDefScripts* tDefScripts = NULL;
+        std::map<int, PDefScripts*>::const_iterator itScrStart = GameDefs->Scripts()->ConstIteratorBegin();
+        std::map<int, PDefScripts*>::const_iterator itScrEnd = GameDefs->Scripts()->ConstIteratorEnd();
+        for ( std::map<int, PDefScripts*>::const_iterator i = itScrStart; i != itScrEnd; i++ )
+        {
+            tDefScripts = i->second;
+    //        Console->Print("[DEBUG PNPC::LoadLUAScript] Identifier: [%s] LUA: [%s]", tDefScripts->GetIdentifier().c_str(), tDefScripts->GetLuaFile().c_str());
+
+            if(tDefScripts->GetIdentifier().compare(mDialogScript) == 0)
+            {
+                break;
+            }
+        }
+        // If we left the loop without an positive match.. false!
+        if(tDefScripts->GetIdentifier().compare(mDialogScript) != 0)
+        {
+            return false;
+        }
+
+        // Assign our LUA file to load later
+        tLuaFile = tDefScripts->GetLuaFile();
+        // MaKe ThE sTrInG aLl lowercase! :)
+        std::transform(tLuaFile.begin(), tLuaFile.end(), tLuaFile.begin(), (int(*)(int))std::tolower);
+
+
+        // We only have 2 headerfiles, so this one is hardcoded
+        if(tDefScripts->GetScriptHeader() == "DIALOGHEADER")
+        {
+            tHDRFile = "scripts/lua/dialogheader.lua";
+        }
+        else if(tDefScripts->GetScriptHeader() == "MISSIONHEADER")
+        {
+            tHDRFile = "scripts/lua/missionheader.lua";
+        }
+    }
+    // Customlua is set?
+    else if(mCustomLua.length() > 1)
+    {
+        // Assign lua file and header
+        tLuaFile = mCustomLua;
+        tHDRFile = "scripts/lua/dialogheader.lua";
+    }
+    else
+    {
+        // No LUA Scripts to load. Skipping
+        return true;
+    }
+
+    // Load HEADER file
+    fLua = Filesystem->Open( "", tHDRFile.c_str(), Config->GetOption( "nc_data_path" ) );
+    if(fLua)
+    {
+        tFileLen = fLua->GetSize();
+        char* t_content = new char[tFileLen+1];
+        memset(t_content, '\0', tFileLen+1);
+
+        fLua->Read( t_content, tFileLen );
+        Filesystem->Close( fLua );
+        mLUAFile = t_content;
+        delete t_content;
+        if (gDevDebug) Console->Print( "%s [PNPC::LoadLUAScript] Loaded LUA Header Script %s", Console->ColorText( GREEN, BLACK, "[SUCCESS]" ), tHDRFile.c_str() );
+    }
+    else
+    {
+        Console->Print( "%s [PNPC::LoadLUAScript] Unable to load LUA Header script %s NPC is now DISABLED for scripting", Console->ColorText( RED, BLACK, "[ERROR]" ), tLuaFile.c_str() );
+        // We encountered an error while loading. Make sure this NPC will never act as Dialog NPC!
+        mLUAFile = "";
+        mCustomLua = "";
+        mDialogScript = "";
+        return false;
+    }
+
+    // Reset vars
+    tFileLen = 0;
+    fLua = NULL;
+
+    fLua = Filesystem->Open( "", tLuaFile.c_str(), Config->GetOption( "nc_data_path" ) );
+    if(fLua)
+    {
+        tFileLen = fLua->GetSize();
+        char* t_content = new char[tFileLen+1];
+        memset(t_content, '\0', tFileLen+1);
+
+        fLua->Read( t_content, tFileLen );
+        Filesystem->Close( fLua );
+        mLUAFile += t_content;  // APPEND the script to our existing lua headerfile
+        delete t_content;
+        if (gDevDebug) Console->Print( "%s [PNPC::LoadLUAScript] Loaded LUA Script %s", Console->ColorText( GREEN, BLACK, "[SUCCESS]" ), tLuaFile.c_str() );
+        //Console->Print( "%s", mLUAFile.c_str() );
+    }
+    else
+    {
+        Console->Print( "%s [PNPC::LoadLUAScript] Unable to load LUA Script %s NPC is now DISABLED for scripting", Console->ColorText( RED, BLACK, "[ERROR]" ), tLuaFile.c_str() );
+        // We encountered an error while loading. Make sure this NPC will never act as Dialog NPC!
+        mLUAFile = "";
+        mCustomLua = "";
+        mDialogScript = "";
+        return false;
+    }
+    // LUA file prepared. Check if LUA file is valid
+    if(LuaEngine->CheckLUAFile(mLUAFile) == true)
+    {
+        // Everything is fine. NPC is ready for action
+        return true;
+    }
+    else
+    {
+        // LUA file seems to be corrupt
+        mLUAFile = "";
+        mCustomLua = "";
+        mDialogScript = "";
+        return false;
+    }
+}
 
  void PNPC::Die()
  {
@@ -310,18 +310,18 @@ bool PNPC::LoadLUAScript()
  }
 
  void PNPC::Update()
-{\r
+{
     // Has to be changed for mobs later
     if ( std::time( NULL ) >= mRespawn && (mAction&NPC_ACTIONSTATE_DEATH) )
-    {\r
+    {
         if ( gDevDebug ) Console->Print( "[DEBUG] NPC Update: Respawn timer triggered! Setting NPC back to life" );
         mHealth = mMaxHealth;
-        mAction = NPC_ACTIONSTATE_IDLE;\r
+        mAction = NPC_ACTIONSTATE_IDLE;
         mWeaponStatus = NPC_SHOOT_IDLE;
         mDirty = true;
-    }\r
+    }
 }
-\r
+
 void PNPC::InitVars()
  {
     mID = 0;
@@ -333,39 +333,39 @@ void PNPC::InitVars()
     mPosY = 0;
     mPosZ = 0;
     mAngle = 0;
-    mHealth = 0;\r
+    mHealth = 0;
     mUnknown = 0;
     mTrader = 0;
-    mLoot = 0;\r
+    mLoot = 0;
     mDialogScript = "";
     mName = "";
     mCustomName = "";
     mCustomLua = "";
-    mAction = NPC_ACTIONSTATE_IDLE;\r
+    mAction = NPC_ACTIONSTATE_IDLE;
     mWeaponStatus = NPC_SHOOT_IDLE;
     //mDeath = false;
     mTarget = 0;
     mDirty = false; // No need to send instand update
     // WorldID Fix 10.10.2009
-    mFromDEF = false;\r
-    mItemQuality = 50;\r
-    mScripting = true;\r
-    mFaction = 0;\r
-\r
-    // Set next update timer for this NPC to 10 - 30 seconds\r
-    // Note: this is for regular heartbeats only. If npc is dirty,\r
-    // an update is sent anyway\r
+    mFromDEF = false;
+    mItemQuality = 50;
+    mScripting = true;
+    mFaction = 0;
+
+    // Set next update timer for this NPC to 10 - 30 seconds
+    // Note: this is for regular heartbeats only. If npc is dirty,
+    // an update is sent anyway
     mNextUpdate = std::time(NULL) + GetRandom(30, 10);
  }
-\r
-void PNPC::Attack( uint32_t nWorldID, uint8_t nType, uint8_t nUnknown )\r
-{\r
-    mDirty = true;\r
-    mTarget = nWorldID;\r
-    mAction = NPC_ACTIONSTATE_ATTACK;\r
-    mWeaponStatus = nType;\r
-    mUnknown = nUnknown;\r
-}\r
+
+void PNPC::Attack( uint32_t nWorldID, uint8_t nType, uint8_t nUnknown )
+{
+    mDirty = true;
+    mTarget = nWorldID;
+    mAction = NPC_ACTIONSTATE_ATTACK;
+    mWeaponStatus = nType;
+    mUnknown = nUnknown;
+}
 
  PNPC::PNPC( int nSQLID )
  {
@@ -408,83 +408,83 @@ PNPC::PNPC( int nDEFID, uint32_t nWorldID )
 */
  ///***********************************************************************
  ///***********************************************************************
-\r
-// Broadcast a single NPC\r
-void PNPCWorld::BroadcastNewNPC(PNPC* nNpc)\r
-{\r
-    std::string tAngleStr = Ssprintf( "%d", nNpc->mAngle );\r
-    PMessage* tmpMsg = MsgBuilder->BuildNPCMassInfoMsg (nNpc->mWorldID, nNpc->mTypeID, nNpc->mClothing, nNpc->mNameID, nNpc->mPosY,\r
-                                                        nNpc->mPosZ, nNpc->mPosX, nNpc->mHealth, nNpc->mTrader, &tAngleStr,\r
-                                                        &nNpc->mName, &nNpc->mCustomName);\r
-\r
-    ClientManager->UDPBroadcast( tmpMsg, mWorldID );\r
-}\r
-\r
-\r
-bool PNPCWorld::AddNPC(uint32_t nSQL_ID, uint32_t nRaw_ID)\r
-{\r
-    PNPC* tmpNpc = new PNPC( nSQL_ID );\r
-    if(tmpNpc->mSuccess == true)\r
-    {\r
-        // Now broadcast the new NPC to all clients\r
-        BroadcastNewNPC(tmpNpc);\r
-        mNPCs.insert( std::make_pair( nRaw_ID, tmpNpc ) );\r
-        tmpNpc = NULL;\r
-        if ( gDevDebug ) Console->Print( "[PNPCWorld::AddNPC] Custom NPC added" );\r
-    }\r
-    else\r
-    {\r
-        if ( gDevDebug ) Console->Print( "[PNPCWorld::AddNPC] Custom NPC not added due error" );\r
-        delete tmpNpc;\r
-        return false;\r
-    }\r
-\r
-    return true;\r
-}\r
-\r
-void PNPCWorld::DelNPC(uint32_t nWorldID)\r
-{\r
-    PNPCMap::iterator it = mNPCs.find( nWorldID );\r
-    if ( it == mNPCs.end() )\r
-        return;\r
-\r
-    // Delete NPC from Map\r
-    mNPCs.erase(it);\r
-\r
-    // Send Vanish message to clients\r
-    PMessage* tmpMsg = MsgBuilder->BuildRemoveWorldObjectMsg(nWorldID);\r
-    ClientManager->UDPBroadcast( tmpMsg, mWorldID );\r
-\r
-    return;\r
-}\r
-\r
-void PNPCWorld::SendSingleNPCInfo( PClient* nClient, PNPC* nNpc )\r
-{\r
-    std::string tAngleStr = Ssprintf( "%d", nNpc->mAngle );\r
-    PMessage* tmpMsg = MsgBuilder->BuildNPCSingleInfoMsg (nClient, nNpc->GetRealWorldID(), nNpc->mTypeID, nNpc->mClothing, nNpc->mNameID, nNpc->mPosY,\r
-                                                        nNpc->mPosZ, nNpc->mPosX, nNpc->mHealth, nNpc->mTrader, &tAngleStr,\r
-                                                        &nNpc->mName, &nNpc->mCustomName);\r
-\r
-    nClient->SendUDPMessage( tmpMsg );\r
-    return;\r
-}\r
+
+// Broadcast a single NPC
+void PNPCWorld::BroadcastNewNPC(PNPC* nNpc)
+{
+    std::string tAngleStr = Ssprintf( "%d", nNpc->mAngle );
+    PMessage* tmpMsg = MsgBuilder->BuildNPCMassInfoMsg (nNpc->mWorldID, nNpc->mTypeID, nNpc->mClothing, nNpc->mNameID, nNpc->mPosY,
+                                                        nNpc->mPosZ, nNpc->mPosX, nNpc->mHealth, nNpc->mTrader, &tAngleStr,
+                                                        &nNpc->mName, &nNpc->mCustomName);
+
+    ClientManager->UDPBroadcast( tmpMsg, mWorldID );
+}
+
+
+bool PNPCWorld::AddNPC(uint32_t nSQL_ID, uint32_t nRaw_ID)
+{
+    PNPC* tmpNpc = new PNPC( nSQL_ID );
+    if(tmpNpc->mSuccess == true)
+    {
+        // Now broadcast the new NPC to all clients
+        BroadcastNewNPC(tmpNpc);
+        mNPCs.insert( std::make_pair( nRaw_ID, tmpNpc ) );
+        tmpNpc = NULL;
+        if ( gDevDebug ) Console->Print( "[PNPCWorld::AddNPC] Custom NPC added" );
+    }
+    else
+    {
+        if ( gDevDebug ) Console->Print( "[PNPCWorld::AddNPC] Custom NPC not added due error" );
+        delete tmpNpc;
+        return false;
+    }
+
+    return true;
+}
+
+void PNPCWorld::DelNPC(uint32_t nWorldID)
+{
+    PNPCMap::iterator it = mNPCs.find( nWorldID );
+    if ( it == mNPCs.end() )
+        return;
+
+    // Delete NPC from Map
+    mNPCs.erase(it);
+
+    // Send Vanish message to clients
+    PMessage* tmpMsg = MsgBuilder->BuildRemoveWorldObjectMsg(nWorldID);
+    ClientManager->UDPBroadcast( tmpMsg, mWorldID );
+
+    return;
+}
+
+void PNPCWorld::SendSingleNPCInfo( PClient* nClient, PNPC* nNpc )
+{
+    std::string tAngleStr = Ssprintf( "%d", nNpc->mAngle );
+    PMessage* tmpMsg = MsgBuilder->BuildNPCSingleInfoMsg (nClient, nNpc->GetRealWorldID(), nNpc->mTypeID, nNpc->mClothing, nNpc->mNameID, nNpc->mPosY,
+                                                        nNpc->mPosZ, nNpc->mPosX, nNpc->mHealth, nNpc->mTrader, &tAngleStr,
+                                                        &nNpc->mName, &nNpc->mCustomName);
+
+    nClient->SendUDPMessage( tmpMsg );
+    return;
+}
 
  void PNPCWorld::MSG_SendNPCs( PClient* nClient )
-{\r
-    PNPC* nNpc = NULL;\r
-    for ( PNPCMap::iterator it = mNPCs.begin(); it != mNPCs.end(); it++ )\r
-    {\r
-        nNpc = it->second;\r
-\r
-        std::string tAngleStr = Ssprintf( "%d", nNpc->mAngle );\r
-        PMessage* tmpMsg = MsgBuilder->BuildNPCSingleInfoMsg (nClient, nNpc->GetRealWorldID(), nNpc->mTypeID, nNpc->mClothing, nNpc->mNameID, nNpc->mPosY,\r
-                                                            nNpc->mPosZ, nNpc->mPosX, nNpc->mHealth, nNpc->mTrader, &tAngleStr,\r
-                                                            &nNpc->mName, &nNpc->mCustomName);\r
-\r
-        nClient->SendUDPMessage( tmpMsg );\r
-    }\r
-\r
-    return;\r
+{
+    PNPC* nNpc = NULL;
+    for ( PNPCMap::iterator it = mNPCs.begin(); it != mNPCs.end(); it++ )
+    {
+        nNpc = it->second;
+
+        std::string tAngleStr = Ssprintf( "%d", nNpc->mAngle );
+        PMessage* tmpMsg = MsgBuilder->BuildNPCSingleInfoMsg (nClient, nNpc->GetRealWorldID(), nNpc->mTypeID, nNpc->mClothing, nNpc->mNameID, nNpc->mPosY,
+                                                            nNpc->mPosZ, nNpc->mPosX, nNpc->mHealth, nNpc->mTrader, &tAngleStr,
+                                                            &nNpc->mName, &nNpc->mCustomName);
+
+        nClient->SendUDPMessage( tmpMsg );
+    }
+
+    return;
 }
 
 bool PNPCWorld::LoadNPCfromSQL()
@@ -584,89 +584,89 @@ bool PNPCWorld::LoadNPCfromDEF()
         delete it->second;
         mNPCs.erase( it );
      }
-}\r
-\r
-void PNPCWorld::Update() // v2; New send function\r
-{\r
-    // Updates NPC in a World.\r
-    // If NPC is dirty, send "large" update. Else\r
-    // send small "i'm alive" message\r
-    std::time_t tNow = std::time(NULL);\r
-    PNPC* tNPC = NULL;\r
-    for ( PNPCMap::iterator it = mNPCs.begin(); it != mNPCs.end(); it++ )\r
-    {\r
-        if ( it->second )\r
-        {\r
-            tNPC = it->second;\r
-            // Check for enemies nearby\r
-            CheckForEnemies(tNPC);\r
-            // Let NPC make themselfs "dirty"\r
-            tNPC->Update();\r
-            // Only update dirty npcs\r
-            if ( tNPC->mDirty == true || tNPC->mNextUpdate <= tNow)\r
-            {\r
-                PMessage* tmpMsg = MsgBuilder->BuildNPCUpdateMsg(tNPC->GetRealWorldID(),\r
-                                                                 tNPC->mPosY,\r
-                                                                 tNPC->mPosZ,\r
-                                                                 tNPC->mPosX,\r
-                                                                 tNPC->GetActionStatus(),\r
-                                                                 tNPC->mHealth,\r
-                                                                 tNPC->GetWeaponStatus(),\r
-                                                                 tNPC->mUnknown,\r
-                                                                 tNPC->mTarget);\r
-\r
-                ClientManager->UDPBroadcast( tmpMsg, mWorldID );\r
-                tNPC->mDirty = false;\r
-                tNPC->PushUpdateTimer();\r
-            }\r
-        }\r
-    }\r
-\r
-    return;\r
+}
+
+void PNPCWorld::Update() // v2; New send function
+{
+    // Updates NPC in a World.
+    // If NPC is dirty, send "large" update. Else
+    // send small "i'm alive" message
+    std::time_t tNow = std::time(NULL);
+    PNPC* tNPC = NULL;
+    for ( PNPCMap::iterator it = mNPCs.begin(); it != mNPCs.end(); it++ )
+    {
+        if ( it->second )
+        {
+            tNPC = it->second;
+            // Check for enemies nearby
+            CheckForEnemies(tNPC);
+            // Let NPC make themselfs "dirty"
+            tNPC->Update();
+            // Only update dirty npcs
+            if ( tNPC->mDirty == true || tNPC->mNextUpdate <= tNow)
+            {
+                PMessage* tmpMsg = MsgBuilder->BuildNPCUpdateMsg(tNPC->GetRealWorldID(),
+                                                                 tNPC->mPosY,
+                                                                 tNPC->mPosZ,
+                                                                 tNPC->mPosX,
+                                                                 tNPC->GetActionStatus(),
+                                                                 tNPC->mHealth,
+                                                                 tNPC->GetWeaponStatus(),
+                                                                 tNPC->mUnknown,
+                                                                 tNPC->mTarget);
+
+                ClientManager->UDPBroadcast( tmpMsg, mWorldID );
+                tNPC->mDirty = false;
+                tNPC->PushUpdateTimer();
+            }
+        }
+    }
+
+    return;
  }
 
-/*\r
+/*
 void PNPCWorld::Update()
-{\r
-    // Updates NPC in a World.\r
-    // If NPC is dirty, send "large" update. Else\r
-    // send small "i'm alive" message\r
-    std::time_t tNow = std::time(NULL);\r
-    PNPC* tNPC = NULL;\r
-    for ( PNPCMap::iterator it = mNPCs.begin(); it != mNPCs.end(); it++ )\r
-    {\r
-        if ( it->second )\r
-        {\r
-            tNPC = it->second;\r
-            // Check for enemies nearby\r
-            CheckForEnemies(tNPC);\r
-            // Let NPC make themselfs "dirty"\r
-            tNPC->Update();\r
-            // Only update dirty npcs\r
-            if ( tNPC->mDirty == true )\r
-            {\r
-                PMessage* tmpMsg = MsgBuilder->BuildNPCMassUpdateMsg( tNPC->GetRealWorldID(), tNPC->mPosX, tNPC->mPosY,\r
-                                                                     tNPC->mPosZ, tNPC->GetActionStatus(), tNPC->mHealth, tNPC->mTarget, tNPC->mAction);\r
-\r
-                ClientManager->UDPBroadcast( tmpMsg, mWorldID );\r
-                tNPC->mDirty = false;\r
-                // Large update also counts as small one, inc update counter\r
-                tNPC->PushUpdateTimer();\r
-            }\r
-            else if(tNPC->mNextUpdate <= tNow)\r
-            {\r
-                PMessage* tmpMsg = MsgBuilder->BuildNPCMassAliveMsg( tNPC->GetRealWorldID(), tNPC->mPosX, tNPC->mPosY,\r
-                                                                     tNPC->mPosZ, tNPC->GetActionStatus(), tNPC->mHealth, tNPC->mAction);\r
-\r
-                ClientManager->UDPBroadcast( tmpMsg, mWorldID );\r
-                tNPC->PushUpdateTimer();\r
-            }\r
-        }\r
-    }\r
-\r
-    return;\r
+{
+    // Updates NPC in a World.
+    // If NPC is dirty, send "large" update. Else
+    // send small "i'm alive" message
+    std::time_t tNow = std::time(NULL);
+    PNPC* tNPC = NULL;
+    for ( PNPCMap::iterator it = mNPCs.begin(); it != mNPCs.end(); it++ )
+    {
+        if ( it->second )
+        {
+            tNPC = it->second;
+            // Check for enemies nearby
+            CheckForEnemies(tNPC);
+            // Let NPC make themselfs "dirty"
+            tNPC->Update();
+            // Only update dirty npcs
+            if ( tNPC->mDirty == true )
+            {
+                PMessage* tmpMsg = MsgBuilder->BuildNPCMassUpdateMsg( tNPC->GetRealWorldID(), tNPC->mPosX, tNPC->mPosY,
+                                                                     tNPC->mPosZ, tNPC->GetActionStatus(), tNPC->mHealth, tNPC->mTarget, tNPC->mAction);
+
+                ClientManager->UDPBroadcast( tmpMsg, mWorldID );
+                tNPC->mDirty = false;
+                // Large update also counts as small one, inc update counter
+                tNPC->PushUpdateTimer();
+            }
+            else if(tNPC->mNextUpdate <= tNow)
+            {
+                PMessage* tmpMsg = MsgBuilder->BuildNPCMassAliveMsg( tNPC->GetRealWorldID(), tNPC->mPosX, tNPC->mPosY,
+                                                                     tNPC->mPosZ, tNPC->GetActionStatus(), tNPC->mHealth, tNPC->mAction);
+
+                ClientManager->UDPBroadcast( tmpMsg, mWorldID );
+                tNPC->PushUpdateTimer();
+            }
+        }
+    }
+
+    return;
 }
-*/\r
+*/
  PNPC* PNPCWorld::GetNPC( uint32_t nNPCID )
  {
     if ( gDevDebug ) Console->Print( "[DEBUG] Searching for NPC %d in list", nNPCID );
index 30835d2..678f804 100644 (file)
@@ -6,18 +6,18 @@
 #include <vector>
 #include <string>
 
-// Healthfactor for NPCs (see old npc.def)\r
-#define NPC_HEALTHFACTOR 15\r
\r
-// Minimum time in seconds that has to pass before an NPC\r
-// gets his heartbeat send\r
-#define NPC_HEARTBEAT_MIN 5\r
-// Maximum time in seconds that is allowed to pass without\r
-// an NPC heartbeat\r
-#define NPC_HEARTBEAT_MAX 20\r
\r
-// If no custom NPC is set in this Zone, what ID to start with?\r
-#define NEW_NPC_ZONEID_START 1000\r
+// Healthfactor for NPCs (see old npc.def)
+#define NPC_HEALTHFACTOR 15
+// Minimum time in seconds that has to pass before an NPC
+// gets his heartbeat send
+#define NPC_HEARTBEAT_MIN 5
+// Maximum time in seconds that is allowed to pass without
+// an NPC heartbeat
+#define NPC_HEARTBEAT_MAX 20
+// If no custom NPC is set in this Zone, what ID to start with?
+#define NEW_NPC_ZONEID_START 1000
 
 // How many seconds have to pass until the zone gets reset?
 // Reset in: NPCs and PWorld object gets deleted and reloaded when
 
 // How many seconds have to pass until we need an NPC "keepalive" packet?
 #define NPC_ALIVE_MSG 15
\r
-// How often a NPC should check if an enemy is nearby?\r
-#define NPC_ENEMYCHECK 5\r
\r
-#define NPC_ACTIONSTATE_SITGND  0x00\r
-#define NPC_ACTIONSTATE_ATTACK  0x01\r
-//#define NPC_ACTIONSTATE_?       0x02\r
-//#define NPC_ACTIONSTATE_?       0x04\r
-//#define NPC_ACTIONSTATE_?       0x08\r
-#define NPC_ACTIONSTATE_KNEEL   0x10\r
-#define NPC_ACTIONSTATE_PASSIVE 0x20\r
-#define NPC_ACTIONSTATE_IDLE    0x40\r
-#define NPC_ACTIONSTATE_DEATH   0x80\r
\r
-#define NPC_SHOOT_IDLE      15\r
-#define NPC_SHOOT_SINGLE    16\r
-#define NPC_SHOOT_AUTO1     17\r
-#define NPC_SHOOT_AUTO2     18\r
\r
+// How often a NPC should check if an enemy is nearby?
+#define NPC_ENEMYCHECK 5
+#define NPC_ACTIONSTATE_SITGND  0x00
+#define NPC_ACTIONSTATE_ATTACK  0x01
+//#define NPC_ACTIONSTATE_?       0x02
+//#define NPC_ACTIONSTATE_?       0x04
+//#define NPC_ACTIONSTATE_?       0x08
+#define NPC_ACTIONSTATE_KNEEL   0x10
+#define NPC_ACTIONSTATE_PASSIVE 0x20
+#define NPC_ACTIONSTATE_IDLE    0x40
+#define NPC_ACTIONSTATE_DEATH   0x80
+#define NPC_SHOOT_IDLE      15
+#define NPC_SHOOT_SINGLE    16
+#define NPC_SHOOT_AUTO1     17
+#define NPC_SHOOT_AUTO2     18
 class PNPC;
 class PNPCWorld;
 
 typedef std::map<uint32_t, PNPC*> PNPCMap;
 typedef std::map<uint32_t, PNPCWorld*> PNPCWorldMap;
\r
 typedef struct
 {
-    uint16_t ItemID;\r
+    uint16_t ItemID;
     uint32_t Price;
 } stShopListEntry;
\r
 class PNPC
 {
 private:
@@ -81,13 +81,13 @@ private:
         npc_unknown,
         npc_trader,  // trader.def entry, or clan/faction data!
         npc_customname,
-        npc_customscript,\r
-        npc_shop_quality,\r
+        npc_customscript,
+        npc_shop_quality,
         npc_scripting
     };
\r
-    time_t mNextUpdate;    // Timestamp for next heartbeat\r
-    time_t mNextEnemyCheck; // Timestamp for next enemycheck\r
+    time_t mNextUpdate;    // Timestamp for next heartbeat
+    time_t mNextEnemyCheck; // Timestamp for next enemycheck
     void PushUpdateTimer();
 
     // SQL values
@@ -101,18 +101,18 @@ private:
     uint16_t mPosZ;
     int8_t mAngle;
     uint16_t mLoot;
-    uint16_t mTrader;\r
-    uint8_t mItemQuality; // Used for Shopping stuff\r
-    uint8_t mUnknown;\r
\r
-    std::string mDialogScript;\r
-    std::string mLUAFile; // Load File; Preloaded uppon NPC creation\r
\r
-    std::vector<stShopListEntry> mVectItemsInShop;    // We need to keep track of the itemorder for shopping\r
-    void AddToVectorList(uint16_t nItemID, uint32_t nPrice);\r
-    inline const stShopListEntry* GetItemNum(uint32_t nIdx) const { if(nIdx > mVectItemsInShop.size()) { return NULL; } else { return &mVectItemsInShop[nIdx]; }};\r
\r
-    bool mScripting;    // Manual override to disable scripting for an NPC TRUE: Scripts will be executed FALSE: Scripts will be ignored\r
+    uint16_t mTrader;
+    uint8_t mItemQuality; // Used for Shopping stuff
+    uint8_t mUnknown;
+    std::string mDialogScript;
+    std::string mLUAFile; // Load File; Preloaded uppon NPC creation
+    std::vector<stShopListEntry> mVectItemsInShop;    // We need to keep track of the itemorder for shopping
+    void AddToVectorList(uint16_t nItemID, uint32_t nPrice);
+    inline const stShopListEntry* GetItemNum(uint32_t nIdx) const { if(nIdx > mVectItemsInShop.size()) { return NULL; } else { return &mVectItemsInShop[nIdx]; }};
+    bool mScripting;    // Manual override to disable scripting for an NPC TRUE: Scripts will be executed FALSE: Scripts will be ignored
 
     std::string mName;
     std::string mCustomName;
@@ -121,63 +121,63 @@ private:
     time_t mRespawn;    // Respawn timer
 
     // Runtime values
-    //bool mDeath;        // Death...\r
-    uint8_t mFaction;        // NPC's faction\r
+    //bool mDeath;        // Death...
+    uint8_t mFaction;        // NPC's faction
 
-    uint16_t mHealth;         // NPC Current Health-Value\r
-    uint16_t mMaxHealth;      // NPC Max Health value\r
+    uint16_t mHealth;         // NPC Current Health-Value
+    uint16_t mMaxHealth;      // NPC Max Health value
     uint32_t mTarget;        // Current focused player
     bool mDirty;        // Needs update to clients
 
     // WorldID Fix 10.10.2009
     bool mFromDEF;      // to differ DEF NPCs from SQL NPCs
-    bool mSuccess;      // NPC load successfull?\r
\r
-
-     uint8_t mAction;         // Current action\r
-    inline uint8_t GetActionStatus() const { return mAction; };\r
-    // 00000001 (  1) 0x01: Attack-Mode (Depends on WeaponStatus)\r
-    // 00000010 (  2) 0x02: ?\r
-    // 00000100 (  4) 0x04: ?\r
-    // 00001000 (  8) 0x08: ?\r
-    // 00010000 ( 16) 0x10: kneel\r
-    // 00100000 ( 32) 0x20: Passive-Mode  (Depends on WeaponStatus. Difference between 0x01: NPC does NOT open fire)\r
-    // 01000000 ( 64) 0x40: Idle\r
-    // 10000000 (128) 0x80: Die\r
\r
-    uint8_t mWeaponStatus;\r
-    inline uint8_t GetWeaponStatus() const { return mWeaponStatus; };\r
-    // 00001111 (15) 0x0F: Follow given target with eyes / Put weapon away if pulled\r
-    // 00010000 (16) 0x10: Pull weapon if not pulled / If pulled, attack\r
-    // 00010001 (17) 0x11: Pull weapon and attack\r
-
\r
+    bool mSuccess;      // NPC load successfull?
+
+     uint8_t mAction;         // Current action
+    inline uint8_t GetActionStatus() const { return mAction; };
+    // 00000001 (  1) 0x01: Attack-Mode (Depends on WeaponStatus)
+    // 00000010 (  2) 0x02: ?
+    // 00000100 (  4) 0x04: ?
+    // 00001000 (  8) 0x08: ?
+    // 00010000 ( 16) 0x10: kneel
+    // 00100000 ( 32) 0x20: Passive-Mode  (Depends on WeaponStatus. Difference between 0x01: NPC does NOT open fire)
+    // 01000000 ( 64) 0x40: Idle
+    // 10000000 (128) 0x80: Die
+    uint8_t mWeaponStatus;
+    inline uint8_t GetWeaponStatus() const { return mWeaponStatus; };
+    // 00001111 (15) 0x0F: Follow given target with eyes / Put weapon away if pulled
+    // 00010000 (16) 0x10: Pull weapon if not pulled / If pulled, attack
+    // 00010001 (17) 0x11: Pull weapon and attack
+
     bool SQL_Load();
     bool DEF_Load(uint32_t nWorldID);
\r
-     PNPC( int nSQLID );\r
-    PNPC( int nDEFID, uint32_t nWorldID );\r
-     ~PNPC();\r
\r
-    void InitVars();\r
-    void ContentListAddItem(PMessage* nContentList, uint16_t nItemID, uint32_t nBasePrice = 0, bool nAddToList = true);\r
-    void ContentListAddItemGroup(PMessage* nContentList, uint32_t nItemGroupID);\r
-    void StartDialog( PClient* nClient/*, string &nDialogscript */);\r
\r
-    bool DoSQLShoppingList( PClient* nClient, PMessage* nContentList );\r
-    bool HasSQLShoppingList( PClient* nClient );\r
-    bool IsAllbuyer( PClient* nClient );\r
-    bool LoadLUAScript();\r
\r
+     PNPC( int nSQLID );
+    PNPC( int nDEFID, uint32_t nWorldID );
+     ~PNPC();
+    void InitVars();
+    void ContentListAddItem(PMessage* nContentList, uint16_t nItemID, uint32_t nBasePrice = 0, bool nAddToList = true);
+    void ContentListAddItemGroup(PMessage* nContentList, uint32_t nItemGroupID);
+    void StartDialog( PClient* nClient/*, string &nDialogscript */);
+    bool DoSQLShoppingList( PClient* nClient, PMessage* nContentList );
+    bool HasSQLShoppingList( PClient* nClient );
+    bool IsAllbuyer( PClient* nClient );
+    bool LoadLUAScript();
     inline uint32_t GetRealWorldID() { if(mFromDEF == true) return mWorldID+255; else return mWorldID; };
 
 public:
     friend class PNPCWorld;
\r
-    inline void StopAttack() { mDirty = true; mAction = NPC_ACTIONSTATE_IDLE; mWeaponStatus = NPC_SHOOT_IDLE; };\r
-    inline void Attack( PClient* nClient, uint8_t nType = NPC_SHOOT_SINGLE, uint8_t nUnknown = 90 ) { Attack(nClient->GetChar()->GetID(), nType, nUnknown); };\r
-    void Attack( uint32_t nWorldID, uint8_t nType = NPC_SHOOT_SINGLE, uint8_t nUnknown = 90 );\r
\r
+    inline void StopAttack() { mDirty = true; mAction = NPC_ACTIONSTATE_IDLE; mWeaponStatus = NPC_SHOOT_IDLE; };
+    inline void Attack( PClient* nClient, uint8_t nType = NPC_SHOOT_SINGLE, uint8_t nUnknown = 90 ) { Attack(nClient->GetChar()->GetID(), nType, nUnknown); };
+    void Attack( uint32_t nWorldID, uint8_t nType = NPC_SHOOT_SINGLE, uint8_t nUnknown = 90 );
     inline void Move( uint16_t nNewX, uint16_t nNewY, uint16_t nNewZ )
     {
         mPosX = nNewX;
@@ -188,19 +188,19 @@ public:
 
     void Die(); // ... die?
     void Update(); // Check respawn timer
-    void StartConversation( PClient* nClient );\r
-    void DoConversation( PClient* nClient, uint8_t nAnswer ) ;\r
\r
-    // GameCommands\r
-    bool ReloadLUAScript();\r
-    bool ReloadShopList();\r
-    bool SetShopQuality(uint8_t nNewVal);\r
-    inline bool IsSQLNPC() const { return !mFromDEF; };\r
-    inline int GetNPCID() const { return mWorldID; };\r
-    inline int GetNPCSQLID() const { return mID; };\r
-    inline void SetTrader( uint16_t nTraderDef ) { mTrader = nTraderDef; };\r
-    inline void SetScripting(bool nVal) { mScripting = nVal; };\r
-    inline uint8_t GetFaction() const { return mFaction; };\r
+    void StartConversation( PClient* nClient );
+    void DoConversation( PClient* nClient, uint8_t nAnswer ) ;
+    // GameCommands
+    bool ReloadLUAScript();
+    bool ReloadShopList();
+    bool SetShopQuality(uint8_t nNewVal);
+    inline bool IsSQLNPC() const { return !mFromDEF; };
+    inline int GetNPCID() const { return mWorldID; };
+    inline int GetNPCSQLID() const { return mID; };
+    inline void SetTrader( uint16_t nTraderDef ) { mTrader = nTraderDef; };
+    inline void SetScripting(bool nVal) { mScripting = nVal; };
+    inline uint8_t GetFaction() const { return mFaction; };
 };
 
 // *****************************************
@@ -236,19 +236,19 @@ private:
     //void MSG_SendAlive();
 
     bool LoadNPCfromSQL();
-    bool LoadNPCfromDEF();\r
\r
-    void BroadcastNewNPC(PNPC* nNpc);\r
+    bool LoadNPCfromDEF();
+    void BroadcastNewNPC(PNPC* nNpc);
     void CheckForEnemies(PNPC* nNPC);
 
 public:
     friend class PNPCManager;
-     PNPC* GetNPC( uint32_t nNPCID );\r
\r
-    // Functions to add/remove an NPC while server is running\r
-    void SendSingleNPCInfo( PClient* nClient, PNPC* nNpc ); // Send\r
-    bool AddNPC(uint32_t nSQL_ID, uint32_t nRaw_ID); // Load single SQL NPC from given SQL ID\r
-    void DelNPC(uint32_t nWorldID); // Remove given NPC from list. Works for *all* npcs\r
+     PNPC* GetNPC( uint32_t nNPCID );
+    // Functions to add/remove an NPC while server is running
+    void SendSingleNPCInfo( PClient* nClient, PNPC* nNpc ); // Send
+    bool AddNPC(uint32_t nSQL_ID, uint32_t nRaw_ID); // Load single SQL NPC from given SQL ID
+    void DelNPC(uint32_t nWorldID); // Remove given NPC from list. Works for *all* npcs
                                                      // but uppon zone reset they're back.
 };
 
index 3417479..a03dbd4 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-#if 0\r
-static const int RCON_INPUTLEN = 512;\r
-\r
-struct PRConClient\r
-{\r
-    enum\r
-    {\r
-        RCCS_AUTH,\r
-        RCCS_AUTH_USER,\r
-        RCCS_AUTH_PASS,\r
-        RCCS_VALID,\r
-        RCCS_DISCONNECT\r
-    } mState;\r
-\r
-    PSocket *mSocket;\r
-    PAccount *mAccount;\r
-    char mInput[RCON_INPUTLEN];\r
-    int mInputLen;\r
-    bool mEcho;\r
-    std::clock_t mSleep, mSleepStart;\r
-    int mNumFailures;\r
-\r
-    inline PRConClient(NLsocket &Sock)\r
-    {\r
-        mSocket = new PSocket(Sock);\r
-        mAccount = 0;\r
-        mInputLen = 0;\r
-        mEcho = true;\r
-        mSleep = 0;\r
-        mSleepStart = 0;\r
-        mNumFailures = 0;\r
-    }\r
-\r
-    inline ~PRConClient()\r
-    {\r
-        delete mSocket;\r
-    }\r
-\r
-    inline void Print(const char *Fmt, ...)\r
-    {\r
-        static char Str[256];\r
-        va_list args;\r
-        va_start(args, Fmt);\r
-        vsnprintf(Str, 255, Fmt, args);\r
-        va_end(args);\r
-        mSocket->Write(Str);\r
-    }\r
-\r
-};\r
-\r
-PRConsole::PRConsole()\r
-{\r
-    mListener = NL_INVALID;\r
-}\r
-\r
-PRConsole::~PRConsole()\r
-{\r
-    if(mListener != NL_INVALID)\r
-        nlClose(mListener);\r
-\r
-    for(ClientList::iterator i=mClients.begin(); i!=mClients.end(); i++)\r
-        delete *i;\r
-}\r
-\r
-void PRConsole::Start()\r
-{\r
-  // CHECK FOR rconsole enabled!!!\r
-    Console->LPrint("Starting remote console...");\r
-    uint16_t Port = Config->GetOptionInt("rconsole_port");\r
-    mListener = nlOpen(Port, NL_TCP);\r
-    if(mListener == NL_INVALID)\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LPrint(" Remote console failed");\r
-        Console->LClose();\r
-        return;\r
-    }\r
-\r
-    Console->LPrint(GREEN, BLACK, "Success");\r
-    Console->LClose();\r
-    nlListen(mListener);\r
-}\r
-\r
-void PRConsole::Update()\r
-{\r
-    if(mListener==NL_INVALID)\r
-        return;\r
-\r
-    NLsocket temp = nlAcceptConnection(mListener);\r
-    if(temp != NL_INVALID)\r
-    {\r
-        // TODO: print client ip addr\r
-        Console->Print("RConsole: client connected");\r
-        PRConClient *cl = new PRConClient(temp);\r
-        cl->mState = PRConClient::RCCS_AUTH;\r
-        mClients.push_back(cl);\r
-        cl->Print("TinNS shell [%s]\r\n", TINNS_VERSION);\r
-    }\r
-\r
-    for(ClientList::iterator i=mClients.begin(); i!=mClients.end();)\r
-    {\r
-        ClientList::iterator j=i;\r
-        PRConClient *cl = *i;\r
-        ++i;\r
-        if(!cl->mSocket->Update() || cl->mSocket->TimeOut())\r
-        {\r
-            Console->Print("RConsole: client disconnected");\r
-            mClients.erase(j);\r
-            delete cl;\r
-            continue;\r
-        }\r
-\r
-        if(cl->mSleep > 0)\r
-        {\r
-            std::clock_t t = std::clock();\r
-            cl->mSleep -= (t-cl->mSleepStart);\r
-            cl->mSleepStart = t;\r
-\r
-            if(cl->mSleep < 0)\r
-                cl->mSleep = 0;\r
-\r
-            // flush socket while sleeping\r
-            int Size=0;\r
-            cl->mSocket->Read(&Size);\r
-\r
-            continue;\r
-        }\r
-\r
-        if(cl->mState==PRConClient::RCCS_AUTH)\r
-        {\r
-            cl->Print("\r\nlogin: ");\r
-            cl->mState = PRConClient::RCCS_AUTH_USER;\r
-        }\r
-\r
-        const uint8_t *Buf = 0;\r
-        int Size=0;\r
-        if((bool)(Buf = cl->mSocket->Read(&Size)))\r
-        {\r
-            for(int i=0; i<Size; i++)\r
-                if(cl->mInputLen < RCON_INPUTLEN)\r
-                {\r
-                    switch(Buf[i])\r
-                    {\r
-                        case 0x08 :\r
-                        {\r
-                            if(cl->mInputLen > 0)\r
-                            {\r
-                                if(cl->mEcho)\r
-                                    cl->mSocket->Write(Buf[i]);\r
-                                cl->mInput[cl->mInputLen]=0;\r
-                                --cl->mInputLen;\r
-                            }\r
-                            break;\r
-                        }\r
-\r
-                        case '\n' :\r
-                        {\r
-                            if(cl->mEcho)\r
-                                cl->mSocket->Write(Buf[i]);\r
-                            cl->mInput[cl->mInputLen]=0;\r
-                            ProcessClient(cl);\r
-                            cl->mInputLen = 0;\r
-                            break;\r
-                        }\r
-\r
-                        default :\r
-                        {\r
-                            cl->mInput[cl->mInputLen++]=Buf[i];\r
-                            if(cl->mEcho)\r
-                                cl->mSocket->Write(Buf[i]);\r
-                            break;\r
-                        }\r
-                    }\r
-                }\r
-        }\r
-    }\r
-}\r
-\r
-void PRConsole::ProcessClient(PRConClient* Client)\r
-{\r
-    Console->Print(">%s", Client->mInput);\r
-    if(Client->mInputLen > 1)\r
-    {\r
-        if(Client->mInput[Client->mInputLen-1] == '\r')\r
-            Client->mInput[Client->mInputLen-1]=0;\r
-\r
-        if(Client->mState == PRConClient::RCCS_AUTH_USER)\r
-        {\r
-            Client->mAccount = Database->GetAccount(Client->mInput);\r
-            Client->mState = PRConClient::RCCS_AUTH_PASS;\r
-            Client->Print("password: ");\r
-            Client->mEcho = false;\r
-        } else\r
-        if(Client->mState == PRConClient::RCCS_AUTH_PASS)\r
-        {\r
-            Client->mEcho = true;\r
-            if((!Client->mAccount) || (Client->mAccount->GetPassword() != Client->mInput) || (!Client->mAccount->IsConsoleAllowed()))\r
-            {\r
-                Client->Print("Invalid user or password\r\n");\r
-                Client->mSleepStart = std::clock();\r
-                ++Client->mNumFailures;\r
-                if(Client->mNumFailures >= 3)\r
-                {\r
-                    // sleep 1 minute\r
-                    Client->mSleep = 60*CLOCKS_PER_SEC;\r
-                    Client->mNumFailures = 0;\r
-                } else\r
-                    Client->mSleep = 5*CLOCKS_PER_SEC;\r
-\r
-                Client->mState = PRConClient::RCCS_AUTH;\r
-            } else\r
-            {\r
-                Client->Print("\r\n\nUser %s logged in\r\n", Client->mAccount->GetName().c_str());\r
-                Client->mState = PRConClient::RCCS_VALID;\r
-                // disconnect after 30 minutes lacking socket activity\r
-                Client->mSocket->SetTimeOutValue(1800);\r
-                Prompt(Client);\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PRConsole::Prompt(PRConClient *Client)\r
-{\r
-    Client->Print("$ ", Client->mAccount->GetName().c_str(), Config->GetOption("server_name").c_str());\r
-}\r
-#endif\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+#if 0
+static const int RCON_INPUTLEN = 512;
+
+struct PRConClient
+{
+    enum
+    {
+        RCCS_AUTH,
+        RCCS_AUTH_USER,
+        RCCS_AUTH_PASS,
+        RCCS_VALID,
+        RCCS_DISCONNECT
+    } mState;
+
+    PSocket *mSocket;
+    PAccount *mAccount;
+    char mInput[RCON_INPUTLEN];
+    int mInputLen;
+    bool mEcho;
+    std::clock_t mSleep, mSleepStart;
+    int mNumFailures;
+
+    inline PRConClient(NLsocket &Sock)
+    {
+        mSocket = new PSocket(Sock);
+        mAccount = 0;
+        mInputLen = 0;
+        mEcho = true;
+        mSleep = 0;
+        mSleepStart = 0;
+        mNumFailures = 0;
+    }
+
+    inline ~PRConClient()
+    {
+        delete mSocket;
+    }
+
+    inline void Print(const char *Fmt, ...)
+    {
+        static char Str[256];
+        va_list args;
+        va_start(args, Fmt);
+        vsnprintf(Str, 255, Fmt, args);
+        va_end(args);
+        mSocket->Write(Str);
+    }
+
+};
+
+PRConsole::PRConsole()
+{
+    mListener = NL_INVALID;
+}
+
+PRConsole::~PRConsole()
+{
+    if(mListener != NL_INVALID)
+        nlClose(mListener);
+
+    for(ClientList::iterator i=mClients.begin(); i!=mClients.end(); i++)
+        delete *i;
+}
+
+void PRConsole::Start()
+{
+  // CHECK FOR rconsole enabled!!!
+    Console->LPrint("Starting remote console...");
+    uint16_t Port = Config->GetOptionInt("rconsole_port");
+    mListener = nlOpen(Port, NL_TCP);
+    if(mListener == NL_INVALID)
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LPrint(" Remote console failed");
+        Console->LClose();
+        return;
+    }
+
+    Console->LPrint(GREEN, BLACK, "Success");
+    Console->LClose();
+    nlListen(mListener);
+}
+
+void PRConsole::Update()
+{
+    if(mListener==NL_INVALID)
+        return;
+
+    NLsocket temp = nlAcceptConnection(mListener);
+    if(temp != NL_INVALID)
+    {
+        // TODO: print client ip addr
+        Console->Print("RConsole: client connected");
+        PRConClient *cl = new PRConClient(temp);
+        cl->mState = PRConClient::RCCS_AUTH;
+        mClients.push_back(cl);
+        cl->Print("TinNS shell [%s]\r\n", TINNS_VERSION);
+    }
+
+    for(ClientList::iterator i=mClients.begin(); i!=mClients.end();)
+    {
+        ClientList::iterator j=i;
+        PRConClient *cl = *i;
+        ++i;
+        if(!cl->mSocket->Update() || cl->mSocket->TimeOut())
+        {
+            Console->Print("RConsole: client disconnected");
+            mClients.erase(j);
+            delete cl;
+            continue;
+        }
+
+        if(cl->mSleep > 0)
+        {
+            std::clock_t t = std::clock();
+            cl->mSleep -= (t-cl->mSleepStart);
+            cl->mSleepStart = t;
+
+            if(cl->mSleep < 0)
+                cl->mSleep = 0;
+
+            // flush socket while sleeping
+            int Size=0;
+            cl->mSocket->Read(&Size);
+
+            continue;
+        }
+
+        if(cl->mState==PRConClient::RCCS_AUTH)
+        {
+            cl->Print("\r\nlogin: ");
+            cl->mState = PRConClient::RCCS_AUTH_USER;
+        }
+
+        const uint8_t *Buf = 0;
+        int Size=0;
+        if((bool)(Buf = cl->mSocket->Read(&Size)))
+        {
+            for(int i=0; i<Size; i++)
+                if(cl->mInputLen < RCON_INPUTLEN)
+                {
+                    switch(Buf[i])
+                    {
+                        case 0x08 :
+                        {
+                            if(cl->mInputLen > 0)
+                            {
+                                if(cl->mEcho)
+                                    cl->mSocket->Write(Buf[i]);
+                                cl->mInput[cl->mInputLen]=0;
+                                --cl->mInputLen;
+                            }
+                            break;
+                        }
+
+                        case '\n' :
+                        {
+                            if(cl->mEcho)
+                                cl->mSocket->Write(Buf[i]);
+                            cl->mInput[cl->mInputLen]=0;
+                            ProcessClient(cl);
+                            cl->mInputLen = 0;
+                            break;
+                        }
+
+                        default :
+                        {
+                            cl->mInput[cl->mInputLen++]=Buf[i];
+                            if(cl->mEcho)
+                                cl->mSocket->Write(Buf[i]);
+                            break;
+                        }
+                    }
+                }
+        }
+    }
+}
+
+void PRConsole::ProcessClient(PRConClient* Client)
+{
+    Console->Print(">%s", Client->mInput);
+    if(Client->mInputLen > 1)
+    {
+        if(Client->mInput[Client->mInputLen-1] == '\r')
+            Client->mInput[Client->mInputLen-1]=0;
+
+        if(Client->mState == PRConClient::RCCS_AUTH_USER)
+        {
+            Client->mAccount = Database->GetAccount(Client->mInput);
+            Client->mState = PRConClient::RCCS_AUTH_PASS;
+            Client->Print("password: ");
+            Client->mEcho = false;
+        } else
+        if(Client->mState == PRConClient::RCCS_AUTH_PASS)
+        {
+            Client->mEcho = true;
+            if((!Client->mAccount) || (Client->mAccount->GetPassword() != Client->mInput) || (!Client->mAccount->IsConsoleAllowed()))
+            {
+                Client->Print("Invalid user or password\r\n");
+                Client->mSleepStart = std::clock();
+                ++Client->mNumFailures;
+                if(Client->mNumFailures >= 3)
+                {
+                    // sleep 1 minute
+                    Client->mSleep = 60*CLOCKS_PER_SEC;
+                    Client->mNumFailures = 0;
+                } else
+                    Client->mSleep = 5*CLOCKS_PER_SEC;
+
+                Client->mState = PRConClient::RCCS_AUTH;
+            } else
+            {
+                Client->Print("\r\n\nUser %s logged in\r\n", Client->mAccount->GetName().c_str());
+                Client->mState = PRConClient::RCCS_VALID;
+                // disconnect after 30 minutes lacking socket activity
+                Client->mSocket->SetTimeOutValue(1800);
+                Prompt(Client);
+            }
+        }
+    }
+}
+
+void PRConsole::Prompt(PRConClient *Client)
+{
+    Client->Print("$ ", Client->mAccount->GetName().c_str(), Config->GetOption("server_name").c_str());
+}
+#endif
index 82bea20..752e21a 100644 (file)
@@ -1,22 +1,22 @@
-#pragma once\r
-\r
-#if 0\r
-#include <list>\r
-\r
-struct PRConClient;\r
-\r
-class PRConsole {\r
-private :\r
-    typedef std::list<PRConClient *> ClientList;\r
-    ClientList mClients;\r
-\r
-    void ProcessClient(PRConClient* Client);\r
-    void Prompt(PRConClient *Client);\r
-public :\r
-    PRConsole();\r
-    ~PRConsole();\r
-\r
-    void Start();\r
-    void Update();\r
-};\r
-#endif\r
+#pragma once
+
+#if 0
+#include <list>
+
+struct PRConClient;
+
+class PRConsole {
+private :
+    typedef std::list<PRConClient *> ClientList;
+    ClientList mClients;
+
+    void ProcessClient(PRConClient* Client);
+    void Prompt(PRConClient *Client);
+public :
+    PRConsole();
+    ~PRConsole();
+
+    void Start();
+    void Update();
+};
+#endif
index a5f9932..3adb838 100644 (file)
@@ -1,82 +1,82 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PServer::PServer()\r
-{\r
-    mNumClients = 0;\r
-    mMaxClients = Config->GetOptionInt("maxclients");\r
-    mGMSlots = Config->GetOptionInt("gm_slots");\r
-    if(mMaxClients==0)\r
-        mMaxClients=1;\r
-    if(mGMSlots==0)\r
-        mGMSlots=1;\r
-    Console->Print("Max clients: %i / GM slots: %i", mMaxClients, mGMSlots);\r
-    mClients.reserve(mMaxClients + mGMSlots);\r
-    for(int i=0; i<mMaxClients+mGMSlots; i++)\r
-        mClients[i]=0;\r
-}\r
-\r
-PServer::~PServer()\r
-{\r
-    for(int i=0; i<mMaxClients+mGMSlots; i++)\r
-        delete mClients[i];\r
-}\r
-\r
-int PServer::NewClient()\r
-{\r
-    if(mNumClients==mMaxClients+mGMSlots)\r
-        return -1;\r
-\r
-    for(int i=0; i<mMaxClients+mGMSlots; i++)\r
-    {\r
-        if(!mClients[i])\r
-        {\r
-            mClients[i]=new PClient(i);\r
-            ++mNumClients;\r
-            return i;\r
-        }\r
-    }\r
-    return -1;\r
-}\r
-\r
-PClient *PServer::GetClient(int Client) const\r
-{\r
-    if(Client < 0 || Client >= mMaxClients+mGMSlots)\r
-        return 0;\r
-\r
-    return mClients[Client];\r
-}\r
-\r
-void PServer::Update()\r
-{\r
-    for(int i=0; i<mMaxClients+mGMSlots; i++)\r
-    {\r
-        if(mClients[i])\r
-        {\r
-            mClients[i]->Update();\r
-            if(mClients[i]->GetConnection()==PCC_NONE && mClients[i]->getTCPConn() == 0)\r
-            {\r
-                Console->Print("Removing client %i...", i);\r
-                delete mClients[i];\r
-                mClients[i]=0;\r
-                --mNumClients;\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PServer::Shutdown()\r
-{\r
-    Console->Print("======================");\r
-    Console->Print("Shutting down Gameserver...");\r
-    for(int i=0; i<mMaxClients+mGMSlots; i++)\r
-    {\r
-        if(mClients[i])\r
-        {\r
-            delete mClients[i];\r
-            mClients[i]=0;\r
-        }\r
-    }\r
-}\r
-\r
-//SELECT `s_name` , NOW( ) , `s_lastupdate` , NOW( ) - `s_lastupdate` FROM `server_list` \r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PServer::PServer()
+{
+    mNumClients = 0;
+    mMaxClients = Config->GetOptionInt("maxclients");
+    mGMSlots = Config->GetOptionInt("gm_slots");
+    if(mMaxClients==0)
+        mMaxClients=1;
+    if(mGMSlots==0)
+        mGMSlots=1;
+    Console->Print("Max clients: %i / GM slots: %i", mMaxClients, mGMSlots);
+    mClients.reserve(mMaxClients + mGMSlots);
+    for(int i=0; i<mMaxClients+mGMSlots; i++)
+        mClients[i]=0;
+}
+
+PServer::~PServer()
+{
+    for(int i=0; i<mMaxClients+mGMSlots; i++)
+        delete mClients[i];
+}
+
+int PServer::NewClient()
+{
+    if(mNumClients==mMaxClients+mGMSlots)
+        return -1;
+
+    for(int i=0; i<mMaxClients+mGMSlots; i++)
+    {
+        if(!mClients[i])
+        {
+            mClients[i]=new PClient(i);
+            ++mNumClients;
+            return i;
+        }
+    }
+    return -1;
+}
+
+PClient *PServer::GetClient(int Client) const
+{
+    if(Client < 0 || Client >= mMaxClients+mGMSlots)
+        return 0;
+
+    return mClients[Client];
+}
+
+void PServer::Update()
+{
+    for(int i=0; i<mMaxClients+mGMSlots; i++)
+    {
+        if(mClients[i])
+        {
+            mClients[i]->Update();
+            if(mClients[i]->GetConnection()==PCC_NONE && mClients[i]->getTCPConn() == 0)
+            {
+                Console->Print("Removing client %i...", i);
+                delete mClients[i];
+                mClients[i]=0;
+                --mNumClients;
+            }
+        }
+    }
+}
+
+void PServer::Shutdown()
+{
+    Console->Print("======================");
+    Console->Print("Shutting down Gameserver...");
+    for(int i=0; i<mMaxClients+mGMSlots; i++)
+    {
+        if(mClients[i])
+        {
+            delete mClients[i];
+            mClients[i]=0;
+        }
+    }
+}
+
+//SELECT `s_name` , NOW( ) , `s_lastupdate` , NOW( ) - `s_lastupdate` FROM `server_list` 
index 7015ddf..c239804 100644 (file)
@@ -1,26 +1,26 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <vector>\r
-\r
-class PClient;\r
-\r
-class PServer{\r
-private:\r
-    int32_t mMaxClients;\r
-    int32_t mGMSlots;\r
-    int32_t mNumClients;\r
-    std::vector<PClient*> mClients;\r
-\r
-public:\r
-    PServer();\r
-    ~PServer();\r
-\r
-    inline int32_t GetMaxClients() const { return mMaxClients; }\r
-    inline int32_t GetGMSlots() const { return mGMSlots; }\r
-    inline int32_t GetNumClients() const { return mNumClients; }\r
-    int NewClient();\r
-    PClient *GetClient(int Client) const;\r
-    void Update();\r
-    void Shutdown();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+class PClient;
+
+class PServer{
+private:
+    int32_t mMaxClients;
+    int32_t mGMSlots;
+    int32_t mNumClients;
+    std::vector<PClient*> mClients;
+
+public:
+    PServer();
+    ~PServer();
+
+    inline int32_t GetMaxClients() const { return mMaxClients; }
+    inline int32_t GetGMSlots() const { return mGMSlots; }
+    inline int32_t GetNumClients() const { return mNumClients; }
+    int NewClient();
+    PClient *GetClient(int Client) const;
+    void Update();
+    void Shutdown();
+};
index ff2fd8e..9b11437 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PMySQL::PMySQL()\r
-{\r
-    InfoDBInuse = 0;\r
-    GameDBInuse = 0;\r
-    info_port = Config->GetOptionInt("info_sql_port");\r
-    strncpy(info_host, Config->GetOption("info_sql_host").c_str(), 100);\r
-    strncpy(info_userName, Config->GetOption("info_sql_username").c_str(), 100);\r
-    strncpy(info_password, Config->GetOption("info_sql_password").c_str(), 100);\r
-    strncpy(info_database, Config->GetOption("info_sql_database").c_str(), 100);\r
-\r
-    game_port = Config->GetOptionInt("game_sql_port");\r
-    strncpy(game_host, Config->GetOption("game_sql_host").c_str(), 100);\r
-    strncpy(game_userName, Config->GetOption("game_sql_username").c_str(), 100);\r
-    strncpy(game_password, Config->GetOption("game_sql_password").c_str(), 100);\r
-    strncpy(game_database, Config->GetOption("game_sql_database").c_str(), 100);\r
-\r
-    mKeepaliveDelay = (std::time_t) (Config->GetOptionInt("mysql_wait_timeout") * 0.9) ; // we take 90% of the wait_timeout to trigger keepalive\r
-    if (mKeepaliveDelay == 0)\r
-    {\r
-      Console->Print("%s MySQL keepalive disabled by config", Console->ColorText(GREEN, BLACK, "[Info]"));\r
-    }\r
-    else if (mKeepaliveDelay < 60)\r
-    {\r
-      Console->Print("%s Configuration option 'mysql_wait_timeout' is too low (%d sec). Reset to 60 sec.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mKeepaliveDelay);\r
-      mKeepaliveDelay = 60;\r
-    }\r
-    mLastKeepaliveSent = 0;\r
-}\r
-\r
-PMySQL::~PMySQL()\r
-{\r
-    Console->Print("Closing MySQL connection...");\r
-    mysql_close(info_dbHandle);\r
-    mysql_close(game_dbHandle);\r
-}\r
-\r
-void PMySQL::Update()\r
-{\r
-    CheckResCount(); // Check for MYSQL_RES mem leak\r
-\r
-    // MySQL keepalive\r
-    std::time_t t = std::time(NULL);\r
-    if ((mKeepaliveDelay > 0) && ((t - mLastKeepaliveSent) > mKeepaliveDelay))\r
-    {\r
-      MYSQL_RES *result;\r
-      char query[24];\r
-      snprintf (query, 24, "SELECT NOW()");\r
-\r
-      result = GameResQuery(query);\r
-      if(!result)\r
-      {\r
-          Console->Print("%s Can't send GameDB keepalive; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-          ShowGameSQLError();\r
-          return;\r
-      }\r
-      else\r
-        FreeGameSQLResult(result);\r
-\r
-      result = InfoResQuery(query);\r
-      if(!result)\r
-      {\r
-          Console->Print("%s Can't send InfoDB keepalive; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-          ShowInfoSQLError();\r
-          return;\r
-      }\r
-      else\r
-        FreeInfoSQLResult(result);\r
-\r
-      mLastKeepaliveSent = std::time(NULL);\r
-      if (gDevDebug) Console->Print("%s MySQL keepalive sent", Console->ColorText(GREEN, BLACK, "[Debug]"));\r
-    }\r
-}\r
-\r
-void PMySQL::CheckResCount()\r
-{\r
-  static int MaxInfoDBCount = 0;\r
-  static int MaxGameDBCount = 0;\r
-\r
-  if (InfoDBInuse > MaxInfoDBCount)\r
-  {\r
-    Console->Print("%s Max In-use InfoDB Resources number increasing : %d (+%d)", Console->ColorText(YELLOW, BLACK, "[Notice]"), InfoDBInuse, InfoDBInuse-MaxInfoDBCount);\r
-    MaxInfoDBCount = InfoDBInuse;\r
-  }\r
-\r
-  if (GameDBInuse > MaxGameDBCount)\r
-  {\r
-    Console->Print("%s Max In-use GameDB Resources number increasing : %d (+%d)", Console->ColorText(YELLOW, BLACK, "[Notice]"), GameDBInuse, GameDBInuse-MaxGameDBCount);\r
-    MaxGameDBCount = GameDBInuse;\r
-  }\r
-}\r
-\r
-bool PMySQL::Connect()\r
-{\r
-    Console->LPrint("Establishing link to Infoserver Database...");\r
-\r
-    info_dbHandle = mysql_init(NULL);\r
-\r
-    if(!info_dbHandle)\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LClose();\r
-        Console->Print(" Unable to create MySQL-Handle!");\r
-        exit(0);\r
-    }\r
-\r
-    if(!mysql_real_connect(info_dbHandle, info_host, info_userName, info_password, info_database, info_port, NULL, 0))\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LClose();\r
-        Console->Print("Unable to connect to Infoserver Database. MySQL returned: %s", mysql_error(info_dbHandle));\r
-    }\r
-    else\r
-    {\r
-        Console->LPrint(GREEN, BLACK, "Success");\r
-        Console->LClose();\r
-    }\r
-// <><><><><><><><> Gameserver DB <><><><><><><><>\r
-    Console->LPrint("Establishing link to Gameserver Database...");\r
-\r
-    game_dbHandle = mysql_init(NULL);\r
-\r
-    if(!game_dbHandle)\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LClose();\r
-        Console->Print(" Unable to create MySQL-Handle!");\r
-        exit(0);\r
-    }\r
-\r
-    if(!mysql_real_connect(game_dbHandle, game_host, game_userName, game_password, game_database, game_port, NULL, 0))\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LClose();\r
-        Console->Print("Unable to connect to Gameserver Database. MySQL returned: %s", mysql_error(game_dbHandle));\r
-        return false;\r
-    }\r
-    else\r
-    {\r
-        Console->LPrint(GREEN, BLACK, "Success");\r
-        Console->LClose();\r
-        return true;\r
-    }\r
-\r
-}\r
-// ----------------------------------------------------\r
-MYSQL_RES *PMySQL::InfoResQuery(const char *query)\r
-{\r
-    int sql_result = 0;\r
-    MYSQL_RES *result;\r
-\r
-    sql_result = mysql_real_query(info_dbHandle, query, strlen(query));\r
-    if(sql_result)\r
-    {\r
-        return NULL;\r
-    }\r
-    result = mysql_store_result(info_dbHandle);\r
-    if(!result)\r
-    {\r
-        return NULL;\r
-    }\r
-    //if(InfoDBInuse == true)\r
-    /*if(InfoDBInuse > 0)\r
-    {\r
-        Console->Print("%s another (%d) info_dbHandle result is still in use", Console->ColorText(YELLOW, BLACK, "[Warning]"), InfoDBInuse);\r
-    }*/\r
-\r
-    //InfoDBInuse = true;\r
-    InfoDBInuse++;\r
-    return result;\r
-}\r
-\r
-int PMySQL::InfoQuery(const char *query)\r
-{\r
-    int sql_result = 0;\r
-    sql_result = mysql_real_query(info_dbHandle, query, strlen(query));\r
-\r
-    return sql_result;\r
-}\r
-\r
-void PMySQL::ShowInfoSQLError()\r
-{\r
-    Console->Print(RED, BLACK, "MySQL Error: %s", mysql_error(info_dbHandle));\r
-}\r
-void PMySQL::FreeInfoSQLResult(MYSQL_RES *res)\r
-{\r
-    if(InfoDBInuse > 0)\r
-    {\r
-        mysql_free_result(res);\r
-        InfoDBInuse--;\r
-    }\r
-    else\r
-        Console->Print("PMySQL::FreeInfoSQLResult: Nothing to free...");\r
-}\r
-// ----------------------------------------------------\r
-MYSQL_RES *PMySQL::GameResQuery(const char *query)\r
-{\r
-    int sql_result = 0;\r
-    MYSQL_RES *result;\r
-\r
-    sql_result = mysql_real_query(game_dbHandle, query, strlen(query));\r
-    if(sql_result)\r
-    {\r
-        return NULL;\r
-    }\r
-    result = mysql_store_result(game_dbHandle);\r
-    if(!result)\r
-    {\r
-        return NULL;\r
-    }\r
-    /*if(GameDBInuse > 0)\r
-    {\r
-        Console->Print("%s another (%d) game_dbHandle result is still in use", Console->ColorText(YELLOW, BLACK, "[Warning]"), GameDBInuse);\r
-    }*/\r
-\r
-    //GameDBInuse = true;\r
-    GameDBInuse++;\r
-    return result;\r
-}\r
-\r
-int PMySQL::GameQuery(const char *query)\r
-{\r
-    int sql_result = 0;\r
-    sql_result = mysql_real_query(game_dbHandle, query, strlen(query));\r
-\r
-    return sql_result;\r
-}\r
-\r
-void PMySQL::ShowGameSQLError()\r
-{\r
-    Console->Print(RED, BLACK, "MySQL Error: %s", mysql_error(game_dbHandle));\r
-}\r
-\r
-void PMySQL::FreeGameSQLResult(MYSQL_RES *res)\r
-{\r
-    if(GameDBInuse > 0)\r
-    {\r
-        mysql_free_result(res);\r
-        GameDBInuse--;\r
-    }\r
-    else\r
-        Console->Print("PMySQL::FreeGameSQLResult: Nothing to free...");\r
-}\r
-\r
-uint32_t PMySQL::EscapeString(const char* nText, char* dText, uint32_t dMaxLength)\r
-{\r
-  uint32_t nLength = strlen(nText);\r
-  uint32_t tMax = (dMaxLength - 1)/2;\r
-  if(nLength > tMax)\r
-  {\r
-    nLength = tMax;\r
-  }\r
-\r
-  return mysql_real_escape_string(game_dbHandle, dText, nText, nLength);\r
-}\r
-\r
-// ----------------------------------------------------\r
-/*\r
-int PMySQL::GetWorldItemType(unsigned short ID, int Location)\r
-{\r
-    char query[2048];\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-\r
-    if (Location > 100000)\r
-    {\r
-      //int nAppLoc = GetAptLocation(Location);\r
-      int nAppLoc = Location - 100000; // temp as DB doesn't link with App world ID, but with app ID\r
-      if (nAppLoc)\r
-        snprintf(query, 2048, "SELECT ai_type FROM apt_items WHERE ai_apt_id = %d AND ai_apt_map = %d", ID, nAppLoc);\r
-      else\r
-        return 0;\r
-    }\r
-    else\r
-      snprintf(query, 2048, "SELECT wi_type FROM world_items WHERE wi_worlditem_id = %d AND wi_worlditem_map = %d", ID, Location);\r
-\r
-    result = GameResQuery(query);\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get WorldItemType; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        ShowGameSQLError();\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        if(mysql_num_rows(result) > 1)\r
-        {\r
-            FreeGameSQLResult(result);\r
-            return -2;\r
-        }\r
-        else\r
-        {\r
-            row = mysql_fetch_row(result);\r
-            if(row == NULL)\r
-            {\r
-                FreeGameSQLResult(result);\r
-                return -1;\r
-            }\r
-            int ret_val = std::atoi(row[0]);\r
-            FreeGameSQLResult(result);\r
-            return ret_val;\r
-        }\r
-    }\r
-//    else\r
-//  {\r
-//      FreeGameSQLResult(result);\r
-//      return -1;\r
-//  }\r
-//\r
-    return -1;\r
-}\r
-\r
-int PMySQL::GetWorldItemOption(unsigned short ID, int Location, int option)\r
-{\r
-    char query[2048];\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-    if(option != 1 && option != 2 && option != 3)\r
-    {\r
-        return -1;\r
-    }\r
-\r
-    if (Location > 100000)\r
-    {\r
-      //int nAppLoc = GetAptLocation(Location);\r
-      int nAppLoc = Location - 100000; // temp as DB doesn't link with App world ID, but with app ID\r
-      if (nAppLoc)\r
-        snprintf(query, 2048, "SELECT ai_option%d FROM apt_items WHERE ai_apt_id = %d AND ai_apt_map = %d", option, ID, nAppLoc);\r
-      else\r
-        return 0;\r
-    }\r
-    else\r
-      snprintf(query, 2048, "SELECT wi_option%d FROM world_items WHERE wi_worlditem_id = %d AND wi_worlditem_map = %d", option, ID, Location);\r
-\r
-    result = GameResQuery(query);\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get WorldItemOption; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        ShowGameSQLError();\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        if(mysql_num_rows(result) > 1)\r
-        {\r
-            FreeGameSQLResult(result);\r
-            return -2;\r
-        }\r
-        else\r
-        {\r
-            row = mysql_fetch_row(result);\r
-            if(row == NULL)\r
-            {\r
-                FreeGameSQLResult(result);\r
-                return -1;\r
-            }\r
-            int ret_val = std::atoi(row[0]);\r
-            FreeGameSQLResult(result);\r
-            return ret_val;\r
-        }\r
-    }\r
-//\r
-//  else\r
-//  {\r
-//      FreeGameSQLResult(result);\r
-//      return -1;\r
-//  }\r
-\r
-    return -1;\r
-}\r
-\r
-int PMySQL::GetWorldDoorType(unsigned int ID, int Location) // To be removed\r
-{\r
-    char query[2048];\r
-    MYSQL_RES *result;\r
-    MYSQL_ROW row;\r
-\r
-Console->Print(RED, BLACK, "PMySQL::GetWorldDoorType: DATABASE MUST NOT BE USED ANYMORE FOR DOORS INFO !!!");\r
-    if (Location > 100000)\r
-    {\r
-      //int nAppLoc = GetAptLocation(Location);\r
-      int nAppLoc = Location - 100000; // temp as DB doesn't link with App world ID, but with app ID\r
-      if (nAppLoc)\r
-        snprintf(query, 2048, "SELECT ad_type FROM apt_doors, apartments WHERE apt_doors.ad_apt_map = apartments.apt_type AND apt_doors.ad_apt_id = %i AND apartments.apt_id = %i", ID, nAppLoc);\r
-      else\r
-        return 0;\r
-    }\r
-    else\r
-    {\r
-        snprintf(query, 2048, "SELECT wd_type FROM world_doors WHERE wd_world_id = %d AND wd_world_map = %d", ID, Location);\r
-    }\r
-    result = GameResQuery(query);\r
-\r
-    if(!result)\r
-    {\r
-        Console->Print("%s Cannot get WorldDoorType; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-        ShowGameSQLError();\r
-        return 0;\r
-    } else {\r
-        if(mysql_num_rows(result) > 1)\r
-        {\r
-            FreeGameSQLResult(result);\r
-            return -2;\r
-        }\r
-        else\r
-        {\r
-            row = mysql_fetch_row(result);\r
-            if(row == NULL)\r
-            {\r
-                FreeGameSQLResult(result);\r
-                return -1;\r
-            }\r
-            int ret_val = std::atoi(row[0]);\r
-            FreeGameSQLResult(result);\r
-            return ret_val;\r
-        }\r
-    }\r
-//\r
-//    else\r
-//    {\r
-//        FreeGameSQLResult(result);\r
-//        return -1;\r
-//    }\r
-//\r
-    return -1;\r
-}*/\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PMySQL::PMySQL()
+{
+    InfoDBInuse = 0;
+    GameDBInuse = 0;
+    info_port = Config->GetOptionInt("info_sql_port");
+    strncpy(info_host, Config->GetOption("info_sql_host").c_str(), 100);
+    strncpy(info_userName, Config->GetOption("info_sql_username").c_str(), 100);
+    strncpy(info_password, Config->GetOption("info_sql_password").c_str(), 100);
+    strncpy(info_database, Config->GetOption("info_sql_database").c_str(), 100);
+
+    game_port = Config->GetOptionInt("game_sql_port");
+    strncpy(game_host, Config->GetOption("game_sql_host").c_str(), 100);
+    strncpy(game_userName, Config->GetOption("game_sql_username").c_str(), 100);
+    strncpy(game_password, Config->GetOption("game_sql_password").c_str(), 100);
+    strncpy(game_database, Config->GetOption("game_sql_database").c_str(), 100);
+
+    mKeepaliveDelay = (std::time_t) (Config->GetOptionInt("mysql_wait_timeout") * 0.9) ; // we take 90% of the wait_timeout to trigger keepalive
+    if (mKeepaliveDelay == 0)
+    {
+      Console->Print("%s MySQL keepalive disabled by config", Console->ColorText(GREEN, BLACK, "[Info]"));
+    }
+    else if (mKeepaliveDelay < 60)
+    {
+      Console->Print("%s Configuration option 'mysql_wait_timeout' is too low (%d sec). Reset to 60 sec.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mKeepaliveDelay);
+      mKeepaliveDelay = 60;
+    }
+    mLastKeepaliveSent = 0;
+}
+
+PMySQL::~PMySQL()
+{
+    Console->Print("Closing MySQL connection...");
+    mysql_close(info_dbHandle);
+    mysql_close(game_dbHandle);
+}
+
+void PMySQL::Update()
+{
+    CheckResCount(); // Check for MYSQL_RES mem leak
+
+    // MySQL keepalive
+    std::time_t t = std::time(NULL);
+    if ((mKeepaliveDelay > 0) && ((t - mLastKeepaliveSent) > mKeepaliveDelay))
+    {
+      MYSQL_RES *result;
+      char query[24];
+      snprintf (query, 24, "SELECT NOW()");
+
+      result = GameResQuery(query);
+      if(!result)
+      {
+          Console->Print("%s Can't send GameDB keepalive; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+          ShowGameSQLError();
+          return;
+      }
+      else
+        FreeGameSQLResult(result);
+
+      result = InfoResQuery(query);
+      if(!result)
+      {
+          Console->Print("%s Can't send InfoDB keepalive; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+          ShowInfoSQLError();
+          return;
+      }
+      else
+        FreeInfoSQLResult(result);
+
+      mLastKeepaliveSent = std::time(NULL);
+      if (gDevDebug) Console->Print("%s MySQL keepalive sent", Console->ColorText(GREEN, BLACK, "[Debug]"));
+    }
+}
+
+void PMySQL::CheckResCount()
+{
+  static int MaxInfoDBCount = 0;
+  static int MaxGameDBCount = 0;
+
+  if (InfoDBInuse > MaxInfoDBCount)
+  {
+    Console->Print("%s Max In-use InfoDB Resources number increasing : %d (+%d)", Console->ColorText(YELLOW, BLACK, "[Notice]"), InfoDBInuse, InfoDBInuse-MaxInfoDBCount);
+    MaxInfoDBCount = InfoDBInuse;
+  }
+
+  if (GameDBInuse > MaxGameDBCount)
+  {
+    Console->Print("%s Max In-use GameDB Resources number increasing : %d (+%d)", Console->ColorText(YELLOW, BLACK, "[Notice]"), GameDBInuse, GameDBInuse-MaxGameDBCount);
+    MaxGameDBCount = GameDBInuse;
+  }
+}
+
+bool PMySQL::Connect()
+{
+    Console->LPrint("Establishing link to Infoserver Database...");
+
+    info_dbHandle = mysql_init(NULL);
+
+    if(!info_dbHandle)
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LClose();
+        Console->Print(" Unable to create MySQL-Handle!");
+        exit(0);
+    }
+
+    if(!mysql_real_connect(info_dbHandle, info_host, info_userName, info_password, info_database, info_port, NULL, 0))
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LClose();
+        Console->Print("Unable to connect to Infoserver Database. MySQL returned: %s", mysql_error(info_dbHandle));
+    }
+    else
+    {
+        Console->LPrint(GREEN, BLACK, "Success");
+        Console->LClose();
+    }
+// <><><><><><><><> Gameserver DB <><><><><><><><>
+    Console->LPrint("Establishing link to Gameserver Database...");
+
+    game_dbHandle = mysql_init(NULL);
+
+    if(!game_dbHandle)
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LClose();
+        Console->Print(" Unable to create MySQL-Handle!");
+        exit(0);
+    }
+
+    if(!mysql_real_connect(game_dbHandle, game_host, game_userName, game_password, game_database, game_port, NULL, 0))
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LClose();
+        Console->Print("Unable to connect to Gameserver Database. MySQL returned: %s", mysql_error(game_dbHandle));
+        return false;
+    }
+    else
+    {
+        Console->LPrint(GREEN, BLACK, "Success");
+        Console->LClose();
+        return true;
+    }
+
+}
+// ----------------------------------------------------
+MYSQL_RES *PMySQL::InfoResQuery(const char *query)
+{
+    int sql_result = 0;
+    MYSQL_RES *result;
+
+    sql_result = mysql_real_query(info_dbHandle, query, strlen(query));
+    if(sql_result)
+    {
+        return NULL;
+    }
+    result = mysql_store_result(info_dbHandle);
+    if(!result)
+    {
+        return NULL;
+    }
+    //if(InfoDBInuse == true)
+    /*if(InfoDBInuse > 0)
+    {
+        Console->Print("%s another (%d) info_dbHandle result is still in use", Console->ColorText(YELLOW, BLACK, "[Warning]"), InfoDBInuse);
+    }*/
+
+    //InfoDBInuse = true;
+    InfoDBInuse++;
+    return result;
+}
+
+int PMySQL::InfoQuery(const char *query)
+{
+    int sql_result = 0;
+    sql_result = mysql_real_query(info_dbHandle, query, strlen(query));
+
+    return sql_result;
+}
+
+void PMySQL::ShowInfoSQLError()
+{
+    Console->Print(RED, BLACK, "MySQL Error: %s", mysql_error(info_dbHandle));
+}
+void PMySQL::FreeInfoSQLResult(MYSQL_RES *res)
+{
+    if(InfoDBInuse > 0)
+    {
+        mysql_free_result(res);
+        InfoDBInuse--;
+    }
+    else
+        Console->Print("PMySQL::FreeInfoSQLResult: Nothing to free...");
+}
+// ----------------------------------------------------
+MYSQL_RES *PMySQL::GameResQuery(const char *query)
+{
+    int sql_result = 0;
+    MYSQL_RES *result;
+
+    sql_result = mysql_real_query(game_dbHandle, query, strlen(query));
+    if(sql_result)
+    {
+        return NULL;
+    }
+    result = mysql_store_result(game_dbHandle);
+    if(!result)
+    {
+        return NULL;
+    }
+    /*if(GameDBInuse > 0)
+    {
+        Console->Print("%s another (%d) game_dbHandle result is still in use", Console->ColorText(YELLOW, BLACK, "[Warning]"), GameDBInuse);
+    }*/
+
+    //GameDBInuse = true;
+    GameDBInuse++;
+    return result;
+}
+
+int PMySQL::GameQuery(const char *query)
+{
+    int sql_result = 0;
+    sql_result = mysql_real_query(game_dbHandle, query, strlen(query));
+
+    return sql_result;
+}
+
+void PMySQL::ShowGameSQLError()
+{
+    Console->Print(RED, BLACK, "MySQL Error: %s", mysql_error(game_dbHandle));
+}
+
+void PMySQL::FreeGameSQLResult(MYSQL_RES *res)
+{
+    if(GameDBInuse > 0)
+    {
+        mysql_free_result(res);
+        GameDBInuse--;
+    }
+    else
+        Console->Print("PMySQL::FreeGameSQLResult: Nothing to free...");
+}
+
+uint32_t PMySQL::EscapeString(const char* nText, char* dText, uint32_t dMaxLength)
+{
+  uint32_t nLength = strlen(nText);
+  uint32_t tMax = (dMaxLength - 1)/2;
+  if(nLength > tMax)
+  {
+    nLength = tMax;
+  }
+
+  return mysql_real_escape_string(game_dbHandle, dText, nText, nLength);
+}
+
+// ----------------------------------------------------
+/*
+int PMySQL::GetWorldItemType(unsigned short ID, int Location)
+{
+    char query[2048];
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+
+    if (Location > 100000)
+    {
+      //int nAppLoc = GetAptLocation(Location);
+      int nAppLoc = Location - 100000; // temp as DB doesn't link with App world ID, but with app ID
+      if (nAppLoc)
+        snprintf(query, 2048, "SELECT ai_type FROM apt_items WHERE ai_apt_id = %d AND ai_apt_map = %d", ID, nAppLoc);
+      else
+        return 0;
+    }
+    else
+      snprintf(query, 2048, "SELECT wi_type FROM world_items WHERE wi_worlditem_id = %d AND wi_worlditem_map = %d", ID, Location);
+
+    result = GameResQuery(query);
+    if(!result)
+    {
+        Console->Print("%s Cannot get WorldItemType; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        ShowGameSQLError();
+        return 0;
+    }
+    else
+    {
+        if(mysql_num_rows(result) > 1)
+        {
+            FreeGameSQLResult(result);
+            return -2;
+        }
+        else
+        {
+            row = mysql_fetch_row(result);
+            if(row == NULL)
+            {
+                FreeGameSQLResult(result);
+                return -1;
+            }
+            int ret_val = std::atoi(row[0]);
+            FreeGameSQLResult(result);
+            return ret_val;
+        }
+    }
+//    else
+//  {
+//      FreeGameSQLResult(result);
+//      return -1;
+//  }
+//
+    return -1;
+}
+
+int PMySQL::GetWorldItemOption(unsigned short ID, int Location, int option)
+{
+    char query[2048];
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+    if(option != 1 && option != 2 && option != 3)
+    {
+        return -1;
+    }
+
+    if (Location > 100000)
+    {
+      //int nAppLoc = GetAptLocation(Location);
+      int nAppLoc = Location - 100000; // temp as DB doesn't link with App world ID, but with app ID
+      if (nAppLoc)
+        snprintf(query, 2048, "SELECT ai_option%d FROM apt_items WHERE ai_apt_id = %d AND ai_apt_map = %d", option, ID, nAppLoc);
+      else
+        return 0;
+    }
+    else
+      snprintf(query, 2048, "SELECT wi_option%d FROM world_items WHERE wi_worlditem_id = %d AND wi_worlditem_map = %d", option, ID, Location);
+
+    result = GameResQuery(query);
+    if(!result)
+    {
+        Console->Print("%s Cannot get WorldItemOption; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        ShowGameSQLError();
+        return 0;
+    }
+    else
+    {
+        if(mysql_num_rows(result) > 1)
+        {
+            FreeGameSQLResult(result);
+            return -2;
+        }
+        else
+        {
+            row = mysql_fetch_row(result);
+            if(row == NULL)
+            {
+                FreeGameSQLResult(result);
+                return -1;
+            }
+            int ret_val = std::atoi(row[0]);
+            FreeGameSQLResult(result);
+            return ret_val;
+        }
+    }
+//
+//  else
+//  {
+//      FreeGameSQLResult(result);
+//      return -1;
+//  }
+
+    return -1;
+}
+
+int PMySQL::GetWorldDoorType(unsigned int ID, int Location) // To be removed
+{
+    char query[2048];
+    MYSQL_RES *result;
+    MYSQL_ROW row;
+
+Console->Print(RED, BLACK, "PMySQL::GetWorldDoorType: DATABASE MUST NOT BE USED ANYMORE FOR DOORS INFO !!!");
+    if (Location > 100000)
+    {
+      //int nAppLoc = GetAptLocation(Location);
+      int nAppLoc = Location - 100000; // temp as DB doesn't link with App world ID, but with app ID
+      if (nAppLoc)
+        snprintf(query, 2048, "SELECT ad_type FROM apt_doors, apartments WHERE apt_doors.ad_apt_map = apartments.apt_type AND apt_doors.ad_apt_id = %i AND apartments.apt_id = %i", ID, nAppLoc);
+      else
+        return 0;
+    }
+    else
+    {
+        snprintf(query, 2048, "SELECT wd_type FROM world_doors WHERE wd_world_id = %d AND wd_world_map = %d", ID, Location);
+    }
+    result = GameResQuery(query);
+
+    if(!result)
+    {
+        Console->Print("%s Cannot get WorldDoorType; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+        ShowGameSQLError();
+        return 0;
+    } else {
+        if(mysql_num_rows(result) > 1)
+        {
+            FreeGameSQLResult(result);
+            return -2;
+        }
+        else
+        {
+            row = mysql_fetch_row(result);
+            if(row == NULL)
+            {
+                FreeGameSQLResult(result);
+                return -1;
+            }
+            int ret_val = std::atoi(row[0]);
+            FreeGameSQLResult(result);
+            return ret_val;
+        }
+    }
+//
+//    else
+//    {
+//        FreeGameSQLResult(result);
+//        return -1;
+//    }
+//
+    return -1;
+}*/
index ed028b3..603d9fc 100644 (file)
@@ -1,64 +1,64 @@
-#pragma once\r
-\r
-#include <chrono>\r
-#include <cstdint>\r
-#ifdef MYSQL_INC_DIR\r
-#include <mysql/mysql.h>\r
-#else\r
-#include <mysql.h>\r
-#endif\r
-\r
-// TODO: take all non-pure SQL DB access stuff out of this class\r
-\r
-class PMySQL {\r
-private:\r
-    int info_port;\r
-    char info_host[100];\r
-    char info_userName[100];\r
-    char info_password[100];\r
-    char info_database[100];\r
-    MYSQL *info_dbHandle;\r
-    std::time_t mKeepaliveDelay;\r
-    std::time_t mLastKeepaliveSent;\r
-\r
-    int game_port;\r
-    char game_host[100];\r
-    char game_userName[100];\r
-    char game_password[100];\r
-    char game_database[100];\r
-    MYSQL *game_dbHandle;\r
-\r
-    int GameDBInuse;\r
-    int InfoDBInuse;\r
-\r
-public:\r
-    PMySQL();\r
-    ~PMySQL();\r
-\r
-    void Update();\r
-    void CheckResCount();\r
-\r
-    inline MYSQL *GetInfoHandle() { return info_dbHandle; };\r
-    inline MYSQL *GetGameHandle() { return game_dbHandle; };\r
-\r
-    bool Connect();\r
-\r
-    int InfoQuery(const char *query);\r
-    MYSQL_RES *InfoResQuery(const char *query);\r
-    int GameQuery(const char *query);\r
-    MYSQL_RES *GameResQuery(const char *query);\r
-\r
-    /*int GetWorldItemType(unsigned short ID, int Location);\r
-    int GetWorldItemOption(unsigned short ID, int Location, int option);\r
-    int GetWorldDoorType(unsigned int ID, int Location);*/\r
-\r
-    void ShowInfoSQLError();\r
-    void ShowGameSQLError();\r
-    void FreeGameSQLResult(MYSQL_RES *res);\r
-    void FreeInfoSQLResult(MYSQL_RES *res);\r
-\r
-    inline uint32_t GetLastGameInsertId() { return mysql_insert_id(game_dbHandle); };\r
-    inline uint32_t GetLastInfoInsertId() { return mysql_insert_id(info_dbHandle); };\r
-\r
-    uint32_t EscapeString(const char* nText, char* dText, uint32_t dMaxLength);\r
-};\r
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#ifdef MYSQL_INC_DIR
+#include <mysql/mysql.h>
+#else
+#include <mysql.h>
+#endif
+
+// TODO: take all non-pure SQL DB access stuff out of this class
+
+class PMySQL {
+private:
+    int info_port;
+    char info_host[100];
+    char info_userName[100];
+    char info_password[100];
+    char info_database[100];
+    MYSQL *info_dbHandle;
+    std::time_t mKeepaliveDelay;
+    std::time_t mLastKeepaliveSent;
+
+    int game_port;
+    char game_host[100];
+    char game_userName[100];
+    char game_password[100];
+    char game_database[100];
+    MYSQL *game_dbHandle;
+
+    int GameDBInuse;
+    int InfoDBInuse;
+
+public:
+    PMySQL();
+    ~PMySQL();
+
+    void Update();
+    void CheckResCount();
+
+    inline MYSQL *GetInfoHandle() { return info_dbHandle; };
+    inline MYSQL *GetGameHandle() { return game_dbHandle; };
+
+    bool Connect();
+
+    int InfoQuery(const char *query);
+    MYSQL_RES *InfoResQuery(const char *query);
+    int GameQuery(const char *query);
+    MYSQL_RES *GameResQuery(const char *query);
+
+    /*int GetWorldItemType(unsigned short ID, int Location);
+    int GetWorldItemOption(unsigned short ID, int Location, int option);
+    int GetWorldDoorType(unsigned int ID, int Location);*/
+
+    void ShowInfoSQLError();
+    void ShowGameSQLError();
+    void FreeGameSQLResult(MYSQL_RES *res);
+    void FreeInfoSQLResult(MYSQL_RES *res);
+
+    inline uint32_t GetLastGameInsertId() { return mysql_insert_id(game_dbHandle); };
+    inline uint32_t GetLastInfoInsertId() { return mysql_insert_id(info_dbHandle); };
+
+    uint32_t EscapeString(const char* nText, char* dText, uint32_t dMaxLength);
+};
index f2ced03..a8669ff 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/*\r
-(Real time)\r
-Full cycle = 328860 ms\r
-Network delay = TBD\r
-\r
-Offset =MOD(M86-122778+(M85*29896);328860)\r
-*/\r
-\r
-// Determines relative position of cabs, but how ???\r
-const uint16_t PSubway::mSubwayInitData [] = {0x4396, 0x4387, 0x4370, 0x4352, 0x4334, 0x4316, 0x42f0, 0x42b4, 0x4270, 0x41f0, 0x0000};\r
-const uint32_t PSubway::mCabLoopTime = 328860;\r
-const uint32_t PSubway::mCab0TimeOffset = 122778;\r
-const int32_t PSubway::mTimingAdjust = 0;\r
-const uint32_t PSubway::mCabIntervalTime = 29896;\r
-const uint32_t PSubway::mOpenDoorOffset [] = { 0, 42500, 83000, 146800, 170700, 226200, 262800, 303200 };\r
-const uint32_t PSubway::mOpenDoorDuration [] = { 8500, 6900, 12000, 7500, 8800, 9000, 8500, 9300 };\r
-const char* PSubway::mSubwayStationName[] = { "Pla => Oz", "Vr => Oz", "Pp => Oz", "Oz end", "Oz => Pla", "Pp => Pla", "Vr => Pla", "Pla end" };\r
-PCharCoordinates PSubway::mCabExitPositions [2][mStationsNumber];\r
-\r
-\r
-PSubway::PSubway()\r
-{\r
-  for(uint8_t i=0; i<mCabsNumber; i++)\r
-  {\r
-    mSubways[i].mVhcId = mCabsBaseId+i;\r
-    mSubways[i].mPosition = mSubwayInitData[i];\r
-    mSubways[i].mDoorOpened = 0;\r
-    for(uint8_t j=0; j<4; j++)\r
-    {\r
-      mSubways[i].mSeatUsersId[j] = 0;\r
-    }\r
-  }\r
-\r
-  mCabExitPositions[0][0].SetPosition(32000-5205, 32000-608, 32000-4766, 0x80, 0);\r
-  mCabExitPositions[1][0].SetPosition(32000-5764, 32000-608, 32000-4766, 0x80, 0);\r
-\r
-  mCabExitPositions[0][1].SetPosition(32000+7290, 32000-600, 32000-500, 0x80, 45);\r
-  mCabExitPositions[1][1].SetPosition(32000+7290, 32000-600, 32000-0, 0x80, 45);\r
-\r
-  mCabExitPositions[0][2].SetPosition(32000-2300, 32000-600, 32000+7985, 0x80, 0);\r
-  mCabExitPositions[1][2].SetPosition(32000-2850, 32000-600, 32000+7985, 0x80, 0);\r
-\r
-  mCabExitPositions[0][3].SetPosition(32000-1700, 32000-596, 32000+1840, 0x80, 90);\r
-  mCabExitPositions[1][3].SetPosition(32000-1250, 32000-596, 32000+1840, 0x80, 90);\r
-\r
-  mCabExitPositions[0][4].SetPosition(32000-1700, 32000-596, 32000+1570, 0x80, 0);\r
-  mCabExitPositions[1][4].SetPosition(32000-1250, 32000-596, 32000+1570, 0x80, 0);\r
-\r
-  mCabExitPositions[0][5].SetPosition(32000-2300, 32000-600, 32000+8625, 0x80, 90);\r
-  mCabExitPositions[1][5].SetPosition(32000-2850, 32000-600, 32000+8625, 0x80, 90);\r
-\r
-  mCabExitPositions[0][6].SetPosition(32000+7815, 32000-600, 32000-500, 0x80, 135);\r
-  mCabExitPositions[1][6].SetPosition(32000+7815, 32000-600, 32000-0, 0x80, 135);\r
-\r
-  mCabExitPositions[0][7].SetPosition(32000-5205, 32000-608, 32000-4092, 0x80, 0);\r
-  mCabExitPositions[1][7].SetPosition(32000-5764, 32000-608, 32000-4092, 0x80, 0);\r
-}\r
-\r
-uint32_t PSubway::GetTimeOffset(uint32_t nVhcId, uint32_t nTime)\r
-{\r
-  uint8_t tIndex;\r
-\r
-  if(!GetInfoIndex(nVhcId, &tIndex))\r
-  {\r
-    Console->Print(RED, BLACK, "[Error] PSubway::GetTimeOffset : invalid cab VhcId %d", nVhcId);\r
-    return 0;\r
-  }\r
-\r
-  return ((nTime + mCabLoopTime - mCab0TimeOffset + mTimingAdjust + (tIndex * mCabIntervalTime)) % mCabLoopTime);\r
-}\r
-\r
-uint8_t PSubway::GetStation(uint32_t nVhcId, uint32_t nTime, uint32_t* TimeOffset)\r
-{\r
-  int8_t i;\r
-\r
-  uint32_t tTimeOffset = GetTimeOffset(nVhcId, nTime);\r
-  if(TimeOffset)\r
-  {\r
-    *TimeOffset = tTimeOffset;\r
-  }\r
-\r
-  for(i = mStationsNumber-1; (i >= 0) && (tTimeOffset < mOpenDoorOffset[i]); --i) ;\r
-\r
-  return i;\r
-}\r
-\r
-bool PSubway::IsDoorOpen(uint32_t nVhcId, uint32_t nTime)\r
-{\r
-  uint32_t TimeOffset;\r
-  uint8_t tStation;\r
-\r
-  if(!GetInfoIndex(nVhcId))\r
-  {\r
-    Console->Print(RED, BLACK, "[Error] PSubway::IsDoorOpen : invalid cab VhcId %d", nVhcId);\r
-    return false;\r
-  }\r
-  else\r
-  {\r
-    tStation = GetStation(nVhcId, nTime, &TimeOffset);\r
-    return ((TimeOffset-mOpenDoorOffset[tStation]) <= mOpenDoorDuration[tStation]);\r
-  }\r
-}\r
-\r
-std::string* PSubway::GetStationName(uint8_t nStationId)\r
-{\r
-  if(nStationId < mStationsNumber)\r
-  {\r
-    return new std::string(mSubwayStationName[nStationId]);\r
-  }\r
-  else\r
-  {\r
-    Console->Print(RED, BLACK, "[Error] PSubway::GetStationName : invalid subway station %d", nStationId);\r
-    return new std::string("Error");\r
-  }\r
-}\r
-\r
-bool PSubway::GetStationExitPosition(PCharCoordinates* nPosition, uint8_t nStationId, float nCoef)\r
-{\r
-  if(nStationId < mStationsNumber)\r
-  {\r
-    nPosition->SetInterpolate(mCabExitPositions[0][nStationId], mCabExitPositions[1][nStationId], nCoef);\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    Console->Print(RED, BLACK, "[Error] PSubway::SetStationExitPosition : invalid subway station %d", nStationId);\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PSubway::GetInfoIndex(uint32_t nVhcId, uint8_t *Index)\r
-{\r
-  int32_t tIndex = nVhcId - mCabsBaseId;\r
-  if ((tIndex >= 0) && (tIndex < mCabsNumber))\r
-  {\r
-    if(Index)\r
-    {\r
-      *Index = (uint8_t)tIndex;\r
-    }\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-bool PSubway::UpdateInfo(uint32_t nVhcId, uint16_t nPosition, uint8_t nDoorOpened)\r
-{\r
-  uint8_t tIndex;\r
-  if(GetInfoIndex(nVhcId, &tIndex))\r
-  {\r
-    mSubways[tIndex].mPosition = nPosition;\r
-//if(mSubways[tIndex].mDoorOpened != nDoorOpened)\r
-//  Console->Print("[DEBUG] Subway cab %08x : door now %s ", nVhcId, nDoorOpened ? "opened" : "closed" );\r
-\r
-    mSubways[tIndex].mDoorOpened = nDoorOpened;\r
-\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-uint16_t PSubway::GetPosition(uint32_t nVhcId)\r
-{\r
-  uint8_t tIndex;\r
-  if(GetInfoIndex(nVhcId, &tIndex))\r
-  {\r
-    return mSubways[tIndex].mPosition;\r
-  }\r
-  else\r
-    return 0;\r
-}\r
-\r
-uint8_t PSubway::GetFreeSeat(uint32_t nVhcId)\r
-{\r
-  uint8_t tIndex;\r
-  uint8_t tSeatFound = 0;\r
-  if(GetInfoIndex(nVhcId, &tIndex))\r
-  {\r
-    for(uint8_t j=0; j<4; j++)\r
-    {\r
-      if(! mSubways[tIndex].mSeatUsersId[j])\r
-      {\r
-        tSeatFound = j+1;\r
-        break;\r
-      }\r
-    }\r
-    return tSeatFound;\r
-  }\r
-  else\r
-    return 0;\r
-}\r
-\r
-bool PSubway::SetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId)\r
-{\r
-  uint8_t tIndex;\r
-\r
-  if(GetInfoIndex(nVhcId, &tIndex) && (nSeat >= 1) && (nSeat <= 4))\r
-  {\r
-    if(! mSubways[tIndex].mSeatUsersId[nSeat-1])\r
-    {\r
-      mSubways[tIndex].mSeatUsersId[nSeat-1] = nCharId;\r
-//Console->Print("[DEBUG] Char %d using seat %d of subway cab %08x, ", nCharId, nSeat, nVhcId);\r
-      return true;\r
-    }\r
-  }\r
-\r
-  return false;\r
-}\r
-\r
-bool PSubway::UnsetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId)\r
-{\r
-  uint8_t tIndex;\r
-\r
-  if(GetInfoIndex(nVhcId, &tIndex) && (nSeat >= 1) && (nSeat <= 4))\r
-  {\r
-    if(mSubways[tIndex].mSeatUsersId[nSeat-1] == nCharId)\r
-    {\r
-      mSubways[tIndex].mSeatUsersId[nSeat-1] = 0;\r
-//Console->Print("[DEBUG] Char %d leaving seat %d of subway cab %08x, ", nCharId, nSeat, nVhcId);\r
-      return true;\r
-    }\r
-  }\r
-\r
-  return false;\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/*
+(Real time)
+Full cycle = 328860 ms
+Network delay = TBD
+
+Offset =MOD(M86-122778+(M85*29896);328860)
+*/
+
+// Determines relative position of cabs, but how ???
+const uint16_t PSubway::mSubwayInitData [] = {0x4396, 0x4387, 0x4370, 0x4352, 0x4334, 0x4316, 0x42f0, 0x42b4, 0x4270, 0x41f0, 0x0000};
+const uint32_t PSubway::mCabLoopTime = 328860;
+const uint32_t PSubway::mCab0TimeOffset = 122778;
+const int32_t PSubway::mTimingAdjust = 0;
+const uint32_t PSubway::mCabIntervalTime = 29896;
+const uint32_t PSubway::mOpenDoorOffset [] = { 0, 42500, 83000, 146800, 170700, 226200, 262800, 303200 };
+const uint32_t PSubway::mOpenDoorDuration [] = { 8500, 6900, 12000, 7500, 8800, 9000, 8500, 9300 };
+const char* PSubway::mSubwayStationName[] = { "Pla => Oz", "Vr => Oz", "Pp => Oz", "Oz end", "Oz => Pla", "Pp => Pla", "Vr => Pla", "Pla end" };
+PCharCoordinates PSubway::mCabExitPositions [2][mStationsNumber];
+
+
+PSubway::PSubway()
+{
+  for(uint8_t i=0; i<mCabsNumber; i++)
+  {
+    mSubways[i].mVhcId = mCabsBaseId+i;
+    mSubways[i].mPosition = mSubwayInitData[i];
+    mSubways[i].mDoorOpened = 0;
+    for(uint8_t j=0; j<4; j++)
+    {
+      mSubways[i].mSeatUsersId[j] = 0;
+    }
+  }
+
+  mCabExitPositions[0][0].SetPosition(32000-5205, 32000-608, 32000-4766, 0x80, 0);
+  mCabExitPositions[1][0].SetPosition(32000-5764, 32000-608, 32000-4766, 0x80, 0);
+
+  mCabExitPositions[0][1].SetPosition(32000+7290, 32000-600, 32000-500, 0x80, 45);
+  mCabExitPositions[1][1].SetPosition(32000+7290, 32000-600, 32000-0, 0x80, 45);
+
+  mCabExitPositions[0][2].SetPosition(32000-2300, 32000-600, 32000+7985, 0x80, 0);
+  mCabExitPositions[1][2].SetPosition(32000-2850, 32000-600, 32000+7985, 0x80, 0);
+
+  mCabExitPositions[0][3].SetPosition(32000-1700, 32000-596, 32000+1840, 0x80, 90);
+  mCabExitPositions[1][3].SetPosition(32000-1250, 32000-596, 32000+1840, 0x80, 90);
+
+  mCabExitPositions[0][4].SetPosition(32000-1700, 32000-596, 32000+1570, 0x80, 0);
+  mCabExitPositions[1][4].SetPosition(32000-1250, 32000-596, 32000+1570, 0x80, 0);
+
+  mCabExitPositions[0][5].SetPosition(32000-2300, 32000-600, 32000+8625, 0x80, 90);
+  mCabExitPositions[1][5].SetPosition(32000-2850, 32000-600, 32000+8625, 0x80, 90);
+
+  mCabExitPositions[0][6].SetPosition(32000+7815, 32000-600, 32000-500, 0x80, 135);
+  mCabExitPositions[1][6].SetPosition(32000+7815, 32000-600, 32000-0, 0x80, 135);
+
+  mCabExitPositions[0][7].SetPosition(32000-5205, 32000-608, 32000-4092, 0x80, 0);
+  mCabExitPositions[1][7].SetPosition(32000-5764, 32000-608, 32000-4092, 0x80, 0);
+}
+
+uint32_t PSubway::GetTimeOffset(uint32_t nVhcId, uint32_t nTime)
+{
+  uint8_t tIndex;
+
+  if(!GetInfoIndex(nVhcId, &tIndex))
+  {
+    Console->Print(RED, BLACK, "[Error] PSubway::GetTimeOffset : invalid cab VhcId %d", nVhcId);
+    return 0;
+  }
+
+  return ((nTime + mCabLoopTime - mCab0TimeOffset + mTimingAdjust + (tIndex * mCabIntervalTime)) % mCabLoopTime);
+}
+
+uint8_t PSubway::GetStation(uint32_t nVhcId, uint32_t nTime, uint32_t* TimeOffset)
+{
+  int8_t i;
+
+  uint32_t tTimeOffset = GetTimeOffset(nVhcId, nTime);
+  if(TimeOffset)
+  {
+    *TimeOffset = tTimeOffset;
+  }
+
+  for(i = mStationsNumber-1; (i >= 0) && (tTimeOffset < mOpenDoorOffset[i]); --i) ;
+
+  return i;
+}
+
+bool PSubway::IsDoorOpen(uint32_t nVhcId, uint32_t nTime)
+{
+  uint32_t TimeOffset;
+  uint8_t tStation;
+
+  if(!GetInfoIndex(nVhcId))
+  {
+    Console->Print(RED, BLACK, "[Error] PSubway::IsDoorOpen : invalid cab VhcId %d", nVhcId);
+    return false;
+  }
+  else
+  {
+    tStation = GetStation(nVhcId, nTime, &TimeOffset);
+    return ((TimeOffset-mOpenDoorOffset[tStation]) <= mOpenDoorDuration[tStation]);
+  }
+}
+
+std::string* PSubway::GetStationName(uint8_t nStationId)
+{
+  if(nStationId < mStationsNumber)
+  {
+    return new std::string(mSubwayStationName[nStationId]);
+  }
+  else
+  {
+    Console->Print(RED, BLACK, "[Error] PSubway::GetStationName : invalid subway station %d", nStationId);
+    return new std::string("Error");
+  }
+}
+
+bool PSubway::GetStationExitPosition(PCharCoordinates* nPosition, uint8_t nStationId, float nCoef)
+{
+  if(nStationId < mStationsNumber)
+  {
+    nPosition->SetInterpolate(mCabExitPositions[0][nStationId], mCabExitPositions[1][nStationId], nCoef);
+    return true;
+  }
+  else
+  {
+    Console->Print(RED, BLACK, "[Error] PSubway::SetStationExitPosition : invalid subway station %d", nStationId);
+    return false;
+  }
+}
+
+bool PSubway::GetInfoIndex(uint32_t nVhcId, uint8_t *Index)
+{
+  int32_t tIndex = nVhcId - mCabsBaseId;
+  if ((tIndex >= 0) && (tIndex < mCabsNumber))
+  {
+    if(Index)
+    {
+      *Index = (uint8_t)tIndex;
+    }
+    return true;
+  }
+  else
+    return false;
+}
+
+bool PSubway::UpdateInfo(uint32_t nVhcId, uint16_t nPosition, uint8_t nDoorOpened)
+{
+  uint8_t tIndex;
+  if(GetInfoIndex(nVhcId, &tIndex))
+  {
+    mSubways[tIndex].mPosition = nPosition;
+//if(mSubways[tIndex].mDoorOpened != nDoorOpened)
+//  Console->Print("[DEBUG] Subway cab %08x : door now %s ", nVhcId, nDoorOpened ? "opened" : "closed" );
+
+    mSubways[tIndex].mDoorOpened = nDoorOpened;
+
+    return true;
+  }
+  else
+    return false;
+}
+
+uint16_t PSubway::GetPosition(uint32_t nVhcId)
+{
+  uint8_t tIndex;
+  if(GetInfoIndex(nVhcId, &tIndex))
+  {
+    return mSubways[tIndex].mPosition;
+  }
+  else
+    return 0;
+}
+
+uint8_t PSubway::GetFreeSeat(uint32_t nVhcId)
+{
+  uint8_t tIndex;
+  uint8_t tSeatFound = 0;
+  if(GetInfoIndex(nVhcId, &tIndex))
+  {
+    for(uint8_t j=0; j<4; j++)
+    {
+      if(! mSubways[tIndex].mSeatUsersId[j])
+      {
+        tSeatFound = j+1;
+        break;
+      }
+    }
+    return tSeatFound;
+  }
+  else
+    return 0;
+}
+
+bool PSubway::SetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId)
+{
+  uint8_t tIndex;
+
+  if(GetInfoIndex(nVhcId, &tIndex) && (nSeat >= 1) && (nSeat <= 4))
+  {
+    if(! mSubways[tIndex].mSeatUsersId[nSeat-1])
+    {
+      mSubways[tIndex].mSeatUsersId[nSeat-1] = nCharId;
+//Console->Print("[DEBUG] Char %d using seat %d of subway cab %08x, ", nCharId, nSeat, nVhcId);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool PSubway::UnsetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId)
+{
+  uint8_t tIndex;
+
+  if(GetInfoIndex(nVhcId, &tIndex) && (nSeat >= 1) && (nSeat <= 4))
+  {
+    if(mSubways[tIndex].mSeatUsersId[nSeat-1] == nCharId)
+    {
+      mSubways[tIndex].mSeatUsersId[nSeat-1] = 0;
+//Console->Print("[DEBUG] Char %d leaving seat %d of subway cab %08x, ", nCharId, nSeat, nVhcId);
+      return true;
+    }
+  }
+
+  return false;
+}
index 40197e3..7f5a48c 100644 (file)
@@ -1,56 +1,56 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <string>\r
-\r
-class PSubway {\r
-  friend class PMsgBuilder;\r
-\r
-  struct PSubwayInfo\r
-  {\r
-    uint16_t mVhcId;\r
-    uint16_t mPosition;\r
-    uint8_t mDoorOpened;\r
-    uint32_t mSeatUsersId[4];\r
-  };\r
-\r
-  public:\r
-    static const uint16_t mCabsNumber = 11;\r
-    static const uint32_t mCabsBaseId = 0x03f2;\r
-    static const uint32_t mCabsBaseHealth = 100; //should take that from .def instead...\r
-    static const uint8_t mStationsNumber = 8;\r
-\r
-  private:\r
-    static const uint16_t mSubwayInitData [];\r
-    static const uint32_t mCabLoopTime;\r
-    static const uint32_t mCab0TimeOffset;\r
-    static const int32_t mTimingAdjust;\r
-    static const uint32_t mCabIntervalTime;\r
-    static const uint32_t mOpenDoorOffset [];\r
-    static const uint32_t mOpenDoorDuration [];\r
-    static const char* mSubwayStationName [];\r
-    static PCharCoordinates mCabExitPositions [2][mStationsNumber];\r
-\r
-    PSubwayInfo mSubways[mCabsNumber];\r
-\r
-public:\r
-    bool GetInfoIndex(uint32_t nVhcId, uint8_t *Index = NULL);\r
-\r
-  public:\r
-    PSubway();\r
-    //~PSubway();\r
-\r
-    inline bool IsValidSubwayCab(uint32_t nVhcId) {return GetInfoIndex(nVhcId); }\r
-    bool UpdateInfo(uint32_t nVhcId, uint16_t nPosition, uint8_t nDoorOpened);\r
-    uint16_t GetPosition(uint32_t nVhcId);\r
-\r
-    uint32_t GetTimeOffset(uint32_t nVhcId, uint32_t nTime);\r
-    uint8_t GetStation(uint32_t nVhcId, uint32_t nTime, uint32_t* TimeOffset = NULL);\r
-    bool IsDoorOpen(uint32_t nVhcId, uint32_t nTime);\r
-    std::string* GetStationName(uint8_t nStationId);\r
-    bool GetStationExitPosition(PCharCoordinates* nPosition, uint8_t nStationId, float nCoef = 0.5);\r
-\r
-    uint8_t GetFreeSeat(uint32_t nVhcId);\r
-    bool SetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId);\r
-    bool UnsetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+class PSubway {
+  friend class PMsgBuilder;
+
+  struct PSubwayInfo
+  {
+    uint16_t mVhcId;
+    uint16_t mPosition;
+    uint8_t mDoorOpened;
+    uint32_t mSeatUsersId[4];
+  };
+
+  public:
+    static const uint16_t mCabsNumber = 11;
+    static const uint32_t mCabsBaseId = 0x03f2;
+    static const uint32_t mCabsBaseHealth = 100; //should take that from .def instead...
+    static const uint8_t mStationsNumber = 8;
+
+  private:
+    static const uint16_t mSubwayInitData [];
+    static const uint32_t mCabLoopTime;
+    static const uint32_t mCab0TimeOffset;
+    static const int32_t mTimingAdjust;
+    static const uint32_t mCabIntervalTime;
+    static const uint32_t mOpenDoorOffset [];
+    static const uint32_t mOpenDoorDuration [];
+    static const char* mSubwayStationName [];
+    static PCharCoordinates mCabExitPositions [2][mStationsNumber];
+
+    PSubwayInfo mSubways[mCabsNumber];
+
+public:
+    bool GetInfoIndex(uint32_t nVhcId, uint8_t *Index = NULL);
+
+  public:
+    PSubway();
+    //~PSubway();
+
+    inline bool IsValidSubwayCab(uint32_t nVhcId) {return GetInfoIndex(nVhcId); }
+    bool UpdateInfo(uint32_t nVhcId, uint16_t nPosition, uint8_t nDoorOpened);
+    uint16_t GetPosition(uint32_t nVhcId);
+
+    uint32_t GetTimeOffset(uint32_t nVhcId, uint32_t nTime);
+    uint8_t GetStation(uint32_t nVhcId, uint32_t nTime, uint32_t* TimeOffset = NULL);
+    bool IsDoorOpen(uint32_t nVhcId, uint32_t nTime);
+    std::string* GetStationName(uint8_t nStationId);
+    bool GetStationExitPosition(PCharCoordinates* nPosition, uint8_t nStationId, float nCoef = 0.5);
+
+    uint8_t GetFreeSeat(uint32_t nVhcId);
+    bool SetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId);
+    bool UnsetSeatUser(uint32_t nVhcId, uint8_t nSeat, uint32_t nCharId);
+};
index 6e92092..888f0a0 100644 (file)
@@ -1,29 +1,29 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class PTerminal {\r
-private:\r
-    void SendTryAccessAnswer(PClient* nClient, char *nArea, bool nAllowed);\r
-    char mSQLQuery[500];\r
-\r
-    int mResultFields;\r
-    void EraseVars();\r
-\r
-    char mConPrefix[50];\r
-\r
-    inline bool ChkOpt(uint8_t nNumOptions, uint8_t nReqOpt) { if(nNumOptions < nReqOpt) return false; else return true; };\r
-    bool DoStockXCheck(PClient* nClient, int nAmountEntered, int nNewAmount);\r
-\r
-public:\r
-    PTerminal();\r
-    //~PTerminal();\r
-    // Check accesslevel of Player for various Terminal actions\r
-    bool CheckAccess(PClient* nClient, char *nArea, uint16_t nCmdNr, char *nOption1, char *nOption2, char *nOption3);\r
-    uint8_t GetNewEmailCount(PClient* nClient, bool nNoticeClient = true);\r
-    // Handle ReceiveDB queries\r
-    bool HandleQueryDB(PClient* nClient, std::string *nDBCommandName, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions);\r
-    bool HandleReceiveDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown);\r
-    bool HandleTryAccess(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown, bool nCheckOnly = false);\r
-    bool HandleUpdateDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown);\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+class PTerminal {
+private:
+    void SendTryAccessAnswer(PClient* nClient, char *nArea, bool nAllowed);
+    char mSQLQuery[500];
+
+    int mResultFields;
+    void EraseVars();
+
+    char mConPrefix[50];
+
+    inline bool ChkOpt(uint8_t nNumOptions, uint8_t nReqOpt) { if(nNumOptions < nReqOpt) return false; else return true; };
+    bool DoStockXCheck(PClient* nClient, int nAmountEntered, int nNewAmount);
+
+public:
+    PTerminal();
+    //~PTerminal();
+    // Check accesslevel of Player for various Terminal actions
+    bool CheckAccess(PClient* nClient, char *nArea, uint16_t nCmdNr, char *nOption1, char *nOption2, char *nOption3);
+    uint8_t GetNewEmailCount(PClient* nClient, bool nNoticeClient = true);
+    // Handle ReceiveDB queries
+    bool HandleQueryDB(PClient* nClient, std::string *nDBCommandName, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions);
+    bool HandleReceiveDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown);
+    bool HandleTryAccess(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown, bool nCheckOnly = false);
+    bool HandleUpdateDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown);
+};
index 29a7c61..e8d8c7b 100644 (file)
-#include <cstring>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-bool PTerminal::HandleReceiveDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown)\r
-{\r
-    EraseVars();\r
-    int nAccessLevel = nClient->GetAccountLevel();\r
-    //Console->Print("DBID: %d", nDBID);\r
-\r
-    switch (nDBID)\r
-    {\r
-    case 8:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 6;\r
-        if(!strncmp(nOptions[0].c_str(), "date", 4))\r
-            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        else\r
-            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 9:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 6;\r
-        if(!strncmp(nOptions[0].c_str(), "date", 4))\r
-            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        else\r
-            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 10:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 6;\r
-        if(!strncmp(nOptions[0].c_str(), "date", 4))\r
-            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        else\r
-            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 11:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 6;\r
-        //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_content FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_id = %d", atoi(nOptions[0].c_str()));\r
-        snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_content FROM `neochronicle` WHERE nc_id = %d", atoi(nOptions[0].c_str()));\r
-        //snprintf (mSQLQuery, 500, "SELECT na_id, \'\', na_datetime, na_author, na_name, na_content FROM `neocron articles` WHERE na_approval = 1 AND na_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 14:\r
-        // 0: ID 1: Short 2: Clanname 3: FactionID 4: Faction Symp\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 6; // TODO: replace 0 with average faction sympathy\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction, \"0\", \"0\" FROM `clans` WHERE cl_name LIKE \"%%%s%%\" LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 16:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        if (!strcmp (nOptions[0].c_str(), "Neocronicle"))\r
-        {\r
-            mResultFields = 5;\r
-            snprintf (mSQLQuery, 500, "SELECT na_id, \'0\', na_datetime, na_author, na_name FROM `neocron articles` WHERE na_approval = 1 LIMIT %s, %s", nOptions[1].c_str(), nOptions[2].c_str());\r
-        }\r
-        else\r
-        {\r
-            mResultFields = 7;\r
-            snprintf (mSQLQuery, 500, "SELECT na_id, \'0\', na_datetime, na_author, na_name, na_approval, \"0\" FROM `neocron articles` LIMIT %s, %s", nOptions[1].c_str(), nOptions[2].c_str());\r
-        }\r
-\r
-        break;\r
-    case 18:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 20:\r
-    case 21:\r
-        // Select either c_"name" or c_"minsympathy". Names taken from option, saves if/else\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT `cl_%s` FROM `clans` WHERE `cl_id` = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 25:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 6; // TODO: replace 0 with average faction sympathy\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction, \"0\", \"0\" FROM clans WHERE cl_name > \"%s\" AND cl_name <=\"%s\" LIMIT %d, %d", nOptions[0].c_str(), nOptions[1].c_str(), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 26:\r
-        // 0: short 1: name 2: money 3: faction 4: fac symp 5: symp_to_join 6: cappid\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_shortdesc, cl_name, cl_money, cl_faction, \"0\", cl_minsympathy, cl_appid FROM `clans` WHERE `cl_id` = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 27:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_description, count(DISTINCT o_outnum), count(DISTINCT c_id) FROM outposts INNER JOIN clans ON (o_clan = cl_id) INNER JOIN characters ON (c_clan = clans.cl_id) WHERE (cl_id = %d) GROUP BY cl_id", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 28:\r
-        // Faction missions? Never seen them even in NC2...\r
-        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d has not been written yet; Factionmissions..? Never seen them", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 29:\r
-        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d Ordercol was missing. Its: [%s]", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID, nOptions[0].c_str());\r
-        break;\r
-    case 34:\r
-        // Name, Add. Info, Profession, Description, Overal Ranking, Soullight, Money, Runner Kills, Creature Kills\r
-        // Note: Add. Info is autogenerated clientside!\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 8;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name, c_profession, \"0\", \"1\", \"127\", c_cash, \"0\", \"0\" FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 38:\r
-        // Faction missions? Never seen them even in NC2...\r
-        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d has not been written yet; Factionmissions..? Never seen them", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 39:\r
-    // 0:id 1:name 2:clan 3:fac.symp\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_clan, \"75\" FROM characters WHERE c_name LIKE \"%s\"", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 41:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT o_outnum, o_outnum, \"0\", \"0\", \"0\" FROM outposts WHERE o_clan = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 46:\r
-        // charid, charname, charclanlevel, clanlevelname, charfactionsymp, char online\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, cll_level, cll_desc, \"0\", c_online FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (cll_clanid = %d) AND (cll_level >= %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 47:\r
-        if(!ChkOpt(nNumOptions, 5)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, cll_desc, 0, c_online FROM characters INNER JOIN clanlevels ON (c_id = cll_charid) WHERE cll_level >= %d AND cll_level <= %d AND c_clan = %d ORDER BY cll_level DESC LIMIT %d, %d", atoi(nOptions[2].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));\r
-\r
-        break;\r
-    case 48:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cll_desc, cll_level FROM clanlevels WHERE cll_clanid = %d AND cll_level = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 49:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 50:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 2; //Fieldnum\r
-        snprintf (mSQLQuery, 500, "SELECT f_showname, f_name FROM forums WHERE f_area = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 51:\r
-        if(!ChkOpt(nNumOptions, 9)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND f_name = \'%s\' AND fp_replyid = 0 LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[7].c_str()), atoi(nOptions[8].c_str()));\r
-\r
-        break;\r
-    case 52:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") AND (fp_id = %d OR fp_replyid = %d)", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 54:\r
-    // id, name, rank, rankname, f.symp\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, cll_level, cll_desc, 0 FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (c_id = %d)", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 60: // Query for OutPost state. Result is <outpost ID> <clan ID>\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT o_outnum, o_clan FROM outposts LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 61: // It should display the clanname, but it doesnt. seems to be clientside bug\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT o_outnum, o_clan, o_clan, o_security FROM outposts WHERE o_outnum = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 75:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cll_desc, cll_level FROM clanlevels WHERE cll_clanid = %d ORDER BY cll_level DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 76:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT count(c_id) FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (cll_clanid = %d AND cll_desc = \"%s\")", atoi(nOptions[0].c_str()),nOptions[1].c_str());\r
-\r
-        break;\r
-    case 85:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 6; // No idea why this Fac.Symp is that high... 1000000 is 100 ingame. But only for this query\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, cll_level, cll_desc, 1000000, c_online FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (c_online = %d OR c_online = 1) AND c_clan = %d LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 86:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        if(!strncmp(nOptions[1].c_str(), "date", 4))\r
-            snprintf (mSQLQuery, 500, "SELECT mt_id, mt_amount, mt_date, c_name FROM moneytransactions INNER JOIN characters ON (mt_player = c_id) WHERE mt_clanid = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-        else\r
-            snprintf (mSQLQuery, 500, "SELECT mt_id, mt_amount, mt_date, c_name FROM moneytransactions INNER JOIN characters ON (mt_player = c_id) WHERE mt_clanid = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 87:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name, mt_date, mt_amount, mt_comment FROM moneytransactions INNER JOIN characters ON (mt_player = c_id) WHERE mt_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 92:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        // Location of player\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT c_location FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 93:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        // Name, Add. Info, Profession, Description\r
-        // Note: Add. Info is autogenerated clientside!\r
-        mResultFields = 3;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name, c_profession, \"0\" FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 96:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT f_showname FROM forums WHERE f_name = \"%s\"", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 98:\r
-        // ID, Name, Online, 0, Soullight\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_online, \"0\", c_soullight FROM characters WHERE c_online = %d AND c_soullight <= -%d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-        break;\r
-    case 99:\r
-        // Terrorist info\r
-        // id, name, faction, clan, clanlevel, location\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_faction, c_clan, cll_level, c_location FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (c_id = %d AND c_soullight <= -%d)", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 108:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_name FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 109:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        // The only case where KK used an DBId twice for completely different things...\r
-        if(nNumOptions < 3)\r
-        {\r
-            mResultFields = 5;\r
-            snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_clan, cll_level, cll_desc FROM characters INNER JOIN clanlevels ON (cll_charid = c_id AND cll_clanid = c_clan) WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-        }\r
-        else if(nNumOptions == 3)\r
-        {\r
-            mResultFields = 2;\r
-            snprintf (mSQLQuery, 500, "SELECT c_id, apt_location FROM apartments INNER JOIN characters ON (apt_owner = c_id) WHERE (c_id = %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        }\r
-\r
-        break;\r
-    case 116:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT wr_id FROM worlds WHERE wr_group = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 125:\r
-        // Return position in Helpqueue. todo yet... for now its 255, we're always busy! =)\r
-        //if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT 255");\r
-\r
-        break;\r
-    case 126:\r
-        // Return position in Helpqueue. todo yet... for now its 255, we're always busy! =)\r
-        // This is with Datecheck, somehow..\r
-        //if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT 255");\r
-\r
-        break;\r
-    case 127:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name, apt_location FROM apartments INNER JOIN characters ON (apt_owner = c_id) WHERE (c_id = %d)", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 128:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT su_id FROM support WHERE su_supporterid = %d AND su_finished = 0", atoi(nOptions[0].c_str()));\r
-\r
-    case 131:\r
-        mResultFields = 6;\r
-        //snprintf(mSQLQuery, 500, "SELECT br_id, br_type, c_online, c_name, br_location, br_datetime FROM `bug report`, characters WHERE c_id = br_fromid AND br_status = %d LIMIT %d, %d",\r
-        // atoi(nOptions[0].c_str())+atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-        snprintf(mSQLQuery, 500, "SELECT su_id, su_type, 0, c_name, su_worldid, su_datetime FROM support INNER JOIN characters ON (su_player = c_id) WHERE su_inwork = %d AND su_finished = %d LIMIT %d, %d",\r
-         atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 132:\r
-    // reqid, runnerid, runnername, 0, date/time, type, 0, in work, finished, desc\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 10;\r
-        //snprintf(mSQLQuery, 500, "SELECT br_id, br_fromid, c_name, \"0\", br_datetime, br_type, \"0\", br_status, br_status, br_desc FROM `bug report` INNER JOIN characters ON (br_fromid = c_id) WHERE br_id = %d", atoi(nOptions[0].c_str()));\r
-        snprintf(mSQLQuery, 500, "SELECT su_id, su_player, c_name, 0, su_datetime, su_type, su_supporterid, su_inwork, su_finished, su_desc FROM support INNER JOIN characters ON (su_player = c_id) WHERE su_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 134:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf(mSQLQuery, 500, "SELECT br_id FROM bug_report WHERE br_fromid = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 136:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 137:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-    // runnerid, runnername, location, online\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_name = \"%s\"", nOptions[0].c_str());\r
-        break;\r
-    case 138:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-    // runnerid, runnername, location, online\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT br_type, br_location, br_datetime, br_supid, br_status, br_desc FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 143:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-    // runnerid, runnername, location, online\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT a.a_id, a.a_username, b.c_id, 0, b.c_location, b.c_online FROM `%s`.accounts AS a, `%s`.characters AS b WHERE b.c_name = \"%s\" AND a.a_id = b.a_id",\r
-                                  Config->GetOption("info_sql_database").c_str(), Config->GetOption("game_sql_database").c_str(), nOptions[0].c_str());\r
-        break;\r
-    case 144:\r
-        mResultFields = 2; // Replace "1" with Online/Offline!\r
-        snprintf (mSQLQuery, 500, "SELECT c_location, c_online FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 145:\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT a_email FROM `%s`.accounts WHERE a_id = %d", Config->GetOption("info_sql_database").c_str(), atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 146:\r
-        mResultFields = 4;\r
-        // Too bad we named the row different...\r
-        char tSortRow[10];\r
-        if(!strncmp(nOptions[1].c_str(), "world", 5))\r
-            strcpy(tSortRow, "location");\r
-        else\r
-            strcpy(tSortRow, "name");\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_name LIKE \"%s\" ORDER BY `c_%s` LIMIT %d, %d", nOptions[0].c_str(), tSortRow, atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 147:\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_online = %d ORDER BY `c_%s` LIMIT %d, %d", atoi(nOptions[0].c_str()), nOptions[1].c_str(), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 148:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, \"0\", \"0\", c_id FROM clans INNER JOIN characters ON (cl_leader = c_id) WHERE (cl_id = %d)", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 150:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 151:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 153:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 154:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 155:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 156:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 157:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 158:\r
-        // Mission stuff. Will be added later!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 175:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT br_id, br_type, br_title, br_datetime FROM bug_report LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 176:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 8;\r
-        snprintf (mSQLQuery, 500, "SELECT br_type, br_status, br_title, br_desc, 0, br_datetime, br_location, br_fromid FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 181:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 3;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name, apt_location, apt_password FROM apartments INNER JOIN characters ON (c_id = apt_owner) WHERE apt_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 183:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_name, (SELECT count(*) FROM characters WHERE c_clan = %d), c_name, apt_id, apt_location FROM clans INNER JOIN apartments ON (cl_appid = apt_id) INNER JOIN characters ON (c_clan = cl_id) AND (apt_owner = c_id) WHERE (cl_id = %d) GROUP BY c_id", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 186:\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id FROM characters WHERE c_name = \"%s\"", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 220:\r
-        mResultFields = 4; //Fieldnum\r
-        snprintf (mSQLQuery, 500, "SELECT v_id, v_type, v_status, v_condition FROM vehicles WHERE v_owner = %i LIMIT %i, %i", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 221:\r
-        //VehicleControl order. "VehicleControl", "Type", "Status", "Condition", "Repairprice?"\r
-        mResultFields = 4; //Fieldnum\r
-        snprintf (mSQLQuery, 500, "SELECT v_type, v_status, v_condition, \"0\" FROM vehicles WHERE v_id = %s", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 225:\r
-        // Statistics. Maybe later...\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 226:\r
-        // Statistics. Maybe later...\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 230:\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT st_id, st_factid, st_curval, st_curval-st_oldval FROM stockx");\r
-\r
-        break;\r
-    case 231:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT st_id, st_factid, st_curval, (st_curval - st_oldval) FROM stockx WHERE (st_id = %d)", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 232:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT sxd_id, st_factid, st_curval, sxd_amount, (sxd_amount * st_curval) FROM stockx_depots INNER JOIN stockx ON (sxd_st_id = st_id) WHERE (sxd_playerid = %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 233:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 7;\r
-        snprintf (mSQLQuery, 500, "SELECT st_factid, sxd_amount, (st_curval - st_oldval), st_curval, sxd_paid, (sxd_amount * st_curval), ((sxd_amount * st_curval) - sxd_paid) FROM stockx_depots INNER JOIN stockx ON (sxd_st_id = st_id) where sxd_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 234:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 3;\r
-        snprintf (mSQLQuery, 500, "SELECT sxd_id, sxd_amount, sxd_paid FROM stockx_depots INNER JOIN stockx ON (sxd_st_id = st_id) WHERE sxd_playerid = %d AND st_factid = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 250:\r
-        // Influence from CharID? Is stockx gm controlled??\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 251:\r
-        // What is this "influence" ? Check this on live servers!\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 260:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 2; //Fieldnum\r
-        snprintf (mSQLQuery, 500, "SELECT f_showname, f_name FROM forums WHERE f_area = %d+%d+%d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 261:\r
-        // Maybe even rewrite BB system.. its wrong written anyways....\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 262:\r
-        // This is wrong! 262 is the receiveDB request for FACTION threadlist. It should be limitet to that faction then\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND (fp_id = %s OR fp_replyid = %s)", nOptions[0].c_str(), nOptions[1].c_str());\r
-\r
-       //TODO Check this. Same (?) for ID 52,262,267,401 and 411\r
-        break;\r
-    case 266:\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND f_name = \'%s\' AND fp_replyid = 0 AND fp_clanid = %d LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 267:\r
-        mResultFields = 4;\r
-       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND (fp_id = %s OR fp_replyid = %s)", nOptions[0].c_str(), nOptions[1].c_str());\r
-\r
-        break;\r
-    case 270:\r
-        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d  Tablename/Name is: [%s] ThreadID is: [%d]", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID, atoi(nOptions[0].c_str()), nOptions[1].c_str());\r
-        break;\r
-    case 360:\r
-        // Gamemaster name (char), Accountname, Location, Online, CharID\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT a.a_id, c.c_id, a.a_username, c.c_name, c.c_online, c.c_location FROM %s.characters AS c, %s.accounts AS a WHERE a.a_priv >= 50 AND c.c_online = %d AND c.a_id = a.a_id ORDER BY c.c_name LIMIT %d, %d",\r
-                                    Config->GetOption("game_sql_database").c_str(), Config->GetOption("info_sql_database").c_str(), atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 365:\r
-        // ID, short, name faction\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction FROM clans LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 366:\r
-        // ID, short, name faction WHERE clanname = %s\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction FROM clans WHERE cl_name LIKE \"%s\" LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 367:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 8;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_leader, cl_faction, cl_appid, cl_money, (SELECT count(*) FROM characters WHERE c_clan = %d) FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 368:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cll_desc, cll_level FROM clanlevels WHERE cll_clanid = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 373:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT apt_id, apt_location, apt_type, apt_password FROM apartments WHERE apt_id = %d AND apt_owner = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 375:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 376:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_name LIKE \"%s\" LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 377:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT DISTINCT a_id FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 378:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT a_username, a_email, \"Since begin\", \"Never\", FROM_UNIXTIME(a_bandate) FROM `%s`.accounts WHERE a_id = %d", Config->GetOption("info_sql_database").c_str(), atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 379:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online, c_clan, cll_level FROM characters INNER JOIN clanlevels ON (cll_charid = c_id) WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 380: // clean\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_name, cll_desc FROM clans INNER JOIN clanlevels ON (cll_clanid = cl_id) WHERE cl_id = %d AND cll_level = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 381:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, c_online FROM characters WHERE a_id = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 384: // clean\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT apt_id, apt_location, 0, apt_password FROM apartments WHERE apt_owner = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 400:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 4;\r
-       snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 401:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") AND (fp_id = %d OR fp_replyid = %d)", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 406:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1;\r
-       snprintf (mSQLQuery, 500, "SELECT count(fp_id) FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) WHERE f_name = \"%s\"", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 410:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 4;\r
-       snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM forum_posts INNER JOIN forums ON (fp_forumid = f_area) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\" AND fp_factionid = %d) LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 411:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 4;\r
-       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM forum_posts INNER JOIN forums ON (fp_forumid = f_area) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") AND (fp_id = %d OR fp_replyid = %d) AND (fp_factionid = %d)", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-\r
-    case 420:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT e_id, e_subject, c_name, e_new, e_replied, e_datetime FROM emails, characters WHERE e_fromid = c_id AND e_toid = %i LIMIT %i, %i", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 421:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        //MailControl order. "MailControl", "Mail ID", "Subject", "From", boolean Replied, "Date/Time", "FromID", "Content"\r
-        mResultFields = 7;\r
-        snprintf (mSQLQuery, 500, "SELECT e_id, e_subject, c_name, e_replied, e_datetime, e_fromid, e_body FROM emails, characters WHERE e_fromid = c_id AND e_id = %s", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 425:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        //Send mail order. "SendMail", "id"\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id FROM characters WHERE c_name = \'%s\'", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 430:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT a.c_id, a.c_conid, b.c_name, a.c_desc FROM contacts as a, characters as b WHERE a.c_conid = b.c_id AND a.c_listid = %s AND c_type = %s", nOptions[0].c_str(), nOptions[1].c_str());\r
-\r
-        break;\r
-    case 431:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT a.c_id, a.c_conid, b.c_name, a.c_desc FROM contacts as a, characters as b WHERE a.c_conid = b.c_id AND a.c_id = %s", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 435:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM contacts WHERE c_listid = %s AND c_type = %s", nOptions[0].c_str(), nOptions[1].c_str());\r
-\r
-        break;\r
-    case 436:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name FROM characters WHERE c_name LIKE \'%%%s%%\' LIMIT %s, %s", nOptions[0].c_str(), nOptions[1].c_str(), nOptions[2].c_str());\r
-\r
-        break;\r
-    case 437:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 1; //Fieldnum\r
-        snprintf (mSQLQuery, 500, "SELECT c_name FROM characters WHERE c_id = %s", nOptions[0].c_str());\r
-\r
-        break;\r
-    case 445:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT nc_id, nc_name FROM neochronicle WHERE nc_lang = %d ORDER BY nc_id DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 446:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT nc_id, nc_lang, nc_datetime, nc_name, nc_content FROM neochronicle WHERE nc_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 453:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT g_id, 0, g_part, g_title, g_language FROM guides WHERE g_chapter = %d AND g_language = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 455:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 3;\r
-        // Opt 2 is Language\r
-        snprintf (mSQLQuery, 500, "SELECT g_id, g_part, g_title FROM guides WHERE g_chapter = %d AND g_language = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 456:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT g_id, g_language, g_title, g_content FROM guides WHERE g_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 458: // Statisics\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 459: // Statisics\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 510: // ClanWars: Overview\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT cw_id, cl_name, cw_starttime, cw_status FROM clanwars INNER JOIN clans ON (cw_initclan = cl_id) or (cw_enemyclan = cl_id) WHERE (cw_enemyclan = %d OR cw_initclan = %d) AND (cl_id != %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-        break;\r
-    case 511: // ClanWars: Selfdeclared wars\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT cw_id, cl_name, cw_starttime, cw_status FROM clanwars INNER JOIN clans ON (cw_enemyclan = cl_id) WHERE cw_initclan = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 512: // ClanWars: Foreigndeclared wars\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 4;\r
-        snprintf (mSQLQuery, 500, "SELECT cw_id, cl_name, cw_starttime, cw_status FROM clanwars INNER JOIN clans ON (cw_initclan = cl_id) WHERE cw_enemyclan = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 513:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_name FROM clans WHERE cl_faction = %d AND cl_id != %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-        break;\r
-    case 514:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_name FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 520:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 10;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_faction, cl_shortdesc, cl_name, cl_description, 0, cl_appid, 80, cl_money, (SELECT count(*) FROM outposts WHERE o_clan = %d), (SELECT count(*) FROM characters WHERE c_clan = %d) FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 521:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, cll_desc, 0, c_online FROM characters INNER JOIN clanlevels ON (c_id = cll_charid) WHERE c_clan = %d AND cll_level >= %d AND cll_level < 15 LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 522:\r
-        if(!ChkOpt(nNumOptions, 5)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, cll_desc, 0, c_online FROM characters INNER JOIN clanlevels ON (c_id = cll_charid) WHERE cll_level >= %d AND cll_level <= %d AND c_clan = %d ORDER BY cll_level DESC LIMIT %d, %d", atoi(nOptions[2].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));\r
-\r
-        break;\r
-    case 523:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT cl_shortdesc, cl_name, cl_leader, cl_description, cl_minsympathy FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 540:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT apt_id, apt_location FROM apartments WHERE apt_owner = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 541:\r
-        if(!ChkOpt(nNumOptions, 3)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT v_id, v_type FROM vehicles WHERE v_owner = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 542:\r
-        if(!ChkOpt(nNumOptions, 2)) break;\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT v_id, v_type, v_world, v_status, v_condition FROM vehicles WHERE v_owner = %d and v_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-\r
-        break;\r
-    case 544:\r
-        if(!ChkOpt(nNumOptions, 4)) break;\r
-        mResultFields = 1;\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM clanwars WHERE (cw_initclan = %d AND cw_enemyclan = %d) OR (cw_enemyclan = %d AND cw_initclan = %d)", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));\r
-\r
-        break;\r
-    case 546:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 2;\r
-        snprintf (mSQLQuery, 500, "SELECT cw_starttime, (TO_DAYS(NOW()) - TO_DAYS(cw_starttime)) FROM clanwars WHERE cw_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 547:\r
-        if(!ChkOpt(nNumOptions, 1)) break;\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT cw_initclan, cw_enemyclan, cw_starttime, cw_status, cw_statement_initiator, cw_statement_enemy FROM clanwars WHERE cw_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 557:\r
-        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d means that you want to edit an DialogScript from the server. This is not supportet yet!", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 558:\r
-        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d means that you want to edit an DialogScript from the server. This is not supportet yet!", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 562:\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT cb_inscription FROM datacubes WHERE cb_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 569:\r
-        // Faction representatives. Not stored yet... is it?\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 570:\r
-        // Clan representatives. Stored but this query wants votes too... Maybe later\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 571:\r
-        // Clan representatives. Stored but this query wants votes too... Maybe later\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 572:\r
-        // Runner voting. Not stored yet\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 573:\r
-        // Next election date\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 574:\r
-        mResultFields = 6;\r
-        snprintf (mSQLQuery, 500, "SELECT count(c_id) FROM characters WHERE c_faction = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 575:\r
-        // Runner satisfaction with faction\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 576:\r
-        // Check if vote from runner is already stored\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 582:\r
-        // Clan representative details. Faction rank etc... not stored yet\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 583:\r
-        // Clan representative details. Faction rank etc... not stored yet\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 584:\r
-        // Clan representative details. Faction rank etc... not stored yet\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 587:\r
-        // Clan representative stuff again...\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 603:\r
-        mResultFields = 1;\r
-        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_status = 0");\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_inwork = 0 AND su_finished = 0");\r
-\r
-        break;\r
-    case 604:\r
-        mResultFields = 1;\r
-        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_status = 1");\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_inwork = 1 AND su_finished = 0");\r
-\r
-        break;\r
-    case 605:\r
-        mResultFields = 1;\r
-        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_status = 2");\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_finished = 1");\r
-\r
-        break;\r
-    case 606:\r
-        mResultFields = 1;\r
-        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report`");\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support");\r
-\r
-        break;\r
-    case 607: // Dont know how to select data from sql where no data to JOIN is there anymore :/\r
-    // This should query ID, RunnerID and Date from bug reports where runnerID is unknown\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 608:\r
-        mResultFields = 5;\r
-        snprintf (mSQLQuery, 500, "SELECT br_id, br_fromid, br_location, br_status, br_datetime FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 609:\r
-        mResultFields = 1;\r
-        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_supid = %s", nOptions[0].c_str());\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_supporterid = %d", atoi(nOptions[0].c_str()));\r
-\r
-        break;\r
-    case 610:\r
-        mResultFields = 6;\r
-        //snprintf (mSQLQuery, 500, "SELECT br_id, \"0\", c_name, br_location, br_status = 2, br_datetime FROM `bug report`, characters WHERE c_id = br_fromid AND br_supid = %s AND br_status > 0 LIMIT %s, %s", nOptions[0].c_str(), nOptions[1].c_str(), nOptions[2].c_str());\r
-        snprintf (mSQLQuery, 500, "SELECT su_id, su_supporterid, c_name, su_worldid, su_finished, su_datetime FROM support INNER JOIN characters ON (su_supporterid = c_id) WHERE su_supporterid = %d AND su_finished = 1 LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-\r
-        break;\r
-    case 611:// Well, its meant to show date specific stuff. I will rewrite this soon...\r
-        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_supporterid = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 612:// Well, its meant to show date specific stuff. I will rewrite this soon...\r
-        snprintf (mSQLQuery, 500, "SELECT su_id, su_supporterid, c_name, su_worldid, su_finished, su_datetime FROM support INNER JOIN characters ON (su_supporterid = c_id) WHERE su_supporterid = %d AND su_finished = 1 LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));\r
-        break;\r
-    case 625: // Faction council stuff\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 626: // Faction council stuff\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 627: // Faction council stuff\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 628: // Faction council stuff\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 629: // Faction council stuff\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    default:\r
-        Console->Print("%s [Pterminal::HandleReceiveDB]  Unknown QueryID %d", Console->ColorText(RED,BLACK,"Warning"), nDBID);\r
-        return false;\r
-    }\r
-\r
-    if(strlen(mSQLQuery) == 0)\r
-        return false;\r
-// ---------------\r
-    MYSQL_RES *result = NULL;\r
-    MYSQL_ROW row;\r
-    int tNumRows = 0;\r
-\r
-    result = MySQL->GameResQuery(mSQLQuery);\r
-    if (!result)\r
-    {\r
-        Console->Print("Cannot query DB. DBID: %d query was: %s", nDBID, mSQLQuery);\r
-        MySQL->ShowGameSQLError();\r
-        return false;\r
-    }\r
-\r
-    PMessage* tDBResult = new PMessage();\r
-    tNumRows = mysql_num_rows(result);\r
-\r
-    // Loop all result rows\r
-    for (int i = 0; i < tNumRows ; i++)\r
-    {\r
-        row = mysql_fetch_row( result ) ;\r
-        // Loop all result fields and push answers into Message\r
-        for (int t = 0; t < mResultFields; t++)\r
-        {\r
-            *tDBResult << ( uint16_t )(strlen(row[t]) + 1);\r
-            *tDBResult << row[t];\r
-        }\r
-    }\r
-\r
-    // Build result messages\r
-    char tCmd[100];\r
-    memset(tCmd, '\0', 100);\r
-    strncpy(tCmd, nCommandName->c_str(), 100);\r
-\r
-    PMessage* tmpMsg_allowed = MsgBuilder->BuildTryAccessAnswerMsg( nClient, tCmd, true );\r
-    PMessage* tmpMsg_result = MsgBuilder->BuildReceiveDBAnswerMsg( nClient, tDBResult, nCommandName, tNumRows, mResultFields);\r
-\r
-    nClient->SendUDPMessage(tmpMsg_allowed);\r
-    nClient->FragmentAndSendUDPMessage(tmpMsg_result, 0x68);\r
-\r
-    return true;\r
-}\r
+#include <cstring>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+bool PTerminal::HandleReceiveDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown)
+{
+    EraseVars();
+    int nAccessLevel = nClient->GetAccountLevel();
+    //Console->Print("DBID: %d", nDBID);
+
+    switch (nDBID)
+    {
+    case 8:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 6;
+        if(!strncmp(nOptions[0].c_str(), "date", 4))
+            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        else
+            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 9:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 6;
+        if(!strncmp(nOptions[0].c_str(), "date", 4))
+            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        else
+            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 1 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 10:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 6;
+        if(!strncmp(nOptions[0].c_str(), "date", 4))
+            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        else
+            //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_approved FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+            snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_approved FROM `neochronicle` WHERE nc_approved = 0 ORDER BY nc_datetime DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 11:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 6;
+        //snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, c_name, nc_name, nc_content FROM `neochronicle` INNER JOIN characters ON (nc_author = c_id) WHERE nc_id = %d", atoi(nOptions[0].c_str()));
+        snprintf (mSQLQuery, 500, "SELECT nc_id, nc_icon, nc_datetime, nc_author, nc_name, nc_content FROM `neochronicle` WHERE nc_id = %d", atoi(nOptions[0].c_str()));
+        //snprintf (mSQLQuery, 500, "SELECT na_id, \'\', na_datetime, na_author, na_name, na_content FROM `neocron articles` WHERE na_approval = 1 AND na_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 14:
+        // 0: ID 1: Short 2: Clanname 3: FactionID 4: Faction Symp
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 6; // TODO: replace 0 with average faction sympathy
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction, \"0\", \"0\" FROM `clans` WHERE cl_name LIKE \"%%%s%%\" LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 16:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        if (!strcmp (nOptions[0].c_str(), "Neocronicle"))
+        {
+            mResultFields = 5;
+            snprintf (mSQLQuery, 500, "SELECT na_id, \'0\', na_datetime, na_author, na_name FROM `neocron articles` WHERE na_approval = 1 LIMIT %s, %s", nOptions[1].c_str(), nOptions[2].c_str());
+        }
+        else
+        {
+            mResultFields = 7;
+            snprintf (mSQLQuery, 500, "SELECT na_id, \'0\', na_datetime, na_author, na_name, na_approval, \"0\" FROM `neocron articles` LIMIT %s, %s", nOptions[1].c_str(), nOptions[2].c_str());
+        }
+
+        break;
+    case 18:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT c_name FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 20:
+    case 21:
+        // Select either c_"name" or c_"minsympathy". Names taken from option, saves if/else
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT `cl_%s` FROM `clans` WHERE `cl_id` = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()));
+
+        break;
+    case 25:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 6; // TODO: replace 0 with average faction sympathy
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction, \"0\", \"0\" FROM clans WHERE cl_name > \"%s\" AND cl_name <=\"%s\" LIMIT %d, %d", nOptions[0].c_str(), nOptions[1].c_str(), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 26:
+        // 0: short 1: name 2: money 3: faction 4: fac symp 5: symp_to_join 6: cappid
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT cl_shortdesc, cl_name, cl_money, cl_faction, \"0\", cl_minsympathy, cl_appid FROM `clans` WHERE `cl_id` = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 27:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_description, count(DISTINCT o_outnum), count(DISTINCT c_id) FROM outposts INNER JOIN clans ON (o_clan = cl_id) INNER JOIN characters ON (c_clan = clans.cl_id) WHERE (cl_id = %d) GROUP BY cl_id", atoi(nOptions[0].c_str()));
+
+        break;
+    case 28:
+        // Faction missions? Never seen them even in NC2...
+        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d has not been written yet; Factionmissions..? Never seen them", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 29:
+        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d Ordercol was missing. Its: [%s]", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID, nOptions[0].c_str());
+        break;
+    case 34:
+        // Name, Add. Info, Profession, Description, Overal Ranking, Soullight, Money, Runner Kills, Creature Kills
+        // Note: Add. Info is autogenerated clientside!
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 8;
+        snprintf (mSQLQuery, 500, "SELECT c_name, c_profession, \"0\", \"1\", \"127\", c_cash, \"0\", \"0\" FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 38:
+        // Faction missions? Never seen them even in NC2...
+        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d has not been written yet; Factionmissions..? Never seen them", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 39:
+    // 0:id 1:name 2:clan 3:fac.symp
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_clan, \"75\" FROM characters WHERE c_name LIKE \"%s\"", nOptions[0].c_str());
+
+        break;
+    case 41:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT o_outnum, o_outnum, \"0\", \"0\", \"0\" FROM outposts WHERE o_clan = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 46:
+        // charid, charname, charclanlevel, clanlevelname, charfactionsymp, char online
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, cll_level, cll_desc, \"0\", c_online FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (cll_clanid = %d) AND (cll_level >= %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 47:
+        if(!ChkOpt(nNumOptions, 5)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, cll_desc, 0, c_online FROM characters INNER JOIN clanlevels ON (c_id = cll_charid) WHERE cll_level >= %d AND cll_level <= %d AND c_clan = %d ORDER BY cll_level DESC LIMIT %d, %d", atoi(nOptions[2].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));
+
+        break;
+    case 48:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cll_desc, cll_level FROM clanlevels WHERE cll_clanid = %d AND cll_level = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 49:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 50:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 2; //Fieldnum
+        snprintf (mSQLQuery, 500, "SELECT f_showname, f_name FROM forums WHERE f_area = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 51:
+        if(!ChkOpt(nNumOptions, 9)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND f_name = \'%s\' AND fp_replyid = 0 LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[7].c_str()), atoi(nOptions[8].c_str()));
+
+        break;
+    case 52:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") AND (fp_id = %d OR fp_replyid = %d)", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 54:
+    // id, name, rank, rankname, f.symp
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, cll_level, cll_desc, 0 FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (c_id = %d)", atoi(nOptions[0].c_str()));
+
+        break;
+    case 60: // Query for OutPost state. Result is <outpost ID> <clan ID>
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT o_outnum, o_clan FROM outposts LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 61: // It should display the clanname, but it doesnt. seems to be clientside bug
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT o_outnum, o_clan, o_clan, o_security FROM outposts WHERE o_outnum = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 75:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cll_desc, cll_level FROM clanlevels WHERE cll_clanid = %d ORDER BY cll_level DESC LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 76:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT count(c_id) FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (cll_clanid = %d AND cll_desc = \"%s\")", atoi(nOptions[0].c_str()),nOptions[1].c_str());
+
+        break;
+    case 85:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 6; // No idea why this Fac.Symp is that high... 1000000 is 100 ingame. But only for this query
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, cll_level, cll_desc, 1000000, c_online FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (c_online = %d OR c_online = 1) AND c_clan = %d LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 86:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        if(!strncmp(nOptions[1].c_str(), "date", 4))
+            snprintf (mSQLQuery, 500, "SELECT mt_id, mt_amount, mt_date, c_name FROM moneytransactions INNER JOIN characters ON (mt_player = c_id) WHERE mt_clanid = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+        else
+            snprintf (mSQLQuery, 500, "SELECT mt_id, mt_amount, mt_date, c_name FROM moneytransactions INNER JOIN characters ON (mt_player = c_id) WHERE mt_clanid = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 87:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_name, mt_date, mt_amount, mt_comment FROM moneytransactions INNER JOIN characters ON (mt_player = c_id) WHERE mt_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 92:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        // Location of player
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT c_location FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 93:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        // Name, Add. Info, Profession, Description
+        // Note: Add. Info is autogenerated clientside!
+        mResultFields = 3;
+        snprintf (mSQLQuery, 500, "SELECT c_name, c_profession, \"0\" FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 96:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT f_showname FROM forums WHERE f_name = \"%s\"", nOptions[0].c_str());
+
+        break;
+    case 98:
+        // ID, Name, Online, 0, Soullight
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_online, \"0\", c_soullight FROM characters WHERE c_online = %d AND c_soullight <= -%d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+        break;
+    case 99:
+        // Terrorist info
+        // id, name, faction, clan, clanlevel, location
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_faction, c_clan, cll_level, c_location FROM clanlevels INNER JOIN characters ON (cll_charid = c_id) WHERE (c_id = %d AND c_soullight <= -%d)", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 108:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT cl_name FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 109:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        // The only case where KK used an DBId twice for completely different things...
+        if(nNumOptions < 3)
+        {
+            mResultFields = 5;
+            snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_clan, cll_level, cll_desc FROM characters INNER JOIN clanlevels ON (cll_charid = c_id AND cll_clanid = c_clan) WHERE c_id = %d", atoi(nOptions[0].c_str()));
+        }
+        else if(nNumOptions == 3)
+        {
+            mResultFields = 2;
+            snprintf (mSQLQuery, 500, "SELECT c_id, apt_location FROM apartments INNER JOIN characters ON (apt_owner = c_id) WHERE (c_id = %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        }
+
+        break;
+    case 116:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT wr_id FROM worlds WHERE wr_group = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 125:
+        // Return position in Helpqueue. todo yet... for now its 255, we're always busy! =)
+        //if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT 255");
+
+        break;
+    case 126:
+        // Return position in Helpqueue. todo yet... for now its 255, we're always busy! =)
+        // This is with Datecheck, somehow..
+        //if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT 255");
+
+        break;
+    case 127:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT c_name, apt_location FROM apartments INNER JOIN characters ON (apt_owner = c_id) WHERE (c_id = %d)", atoi(nOptions[0].c_str()));
+
+        break;
+    case 128:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT su_id FROM support WHERE su_supporterid = %d AND su_finished = 0", atoi(nOptions[0].c_str()));
+
+    case 131:
+        mResultFields = 6;
+        //snprintf(mSQLQuery, 500, "SELECT br_id, br_type, c_online, c_name, br_location, br_datetime FROM `bug report`, characters WHERE c_id = br_fromid AND br_status = %d LIMIT %d, %d",
+        // atoi(nOptions[0].c_str())+atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+        snprintf(mSQLQuery, 500, "SELECT su_id, su_type, 0, c_name, su_worldid, su_datetime FROM support INNER JOIN characters ON (su_player = c_id) WHERE su_inwork = %d AND su_finished = %d LIMIT %d, %d",
+         atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 132:
+    // reqid, runnerid, runnername, 0, date/time, type, 0, in work, finished, desc
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 10;
+        //snprintf(mSQLQuery, 500, "SELECT br_id, br_fromid, c_name, \"0\", br_datetime, br_type, \"0\", br_status, br_status, br_desc FROM `bug report` INNER JOIN characters ON (br_fromid = c_id) WHERE br_id = %d", atoi(nOptions[0].c_str()));
+        snprintf(mSQLQuery, 500, "SELECT su_id, su_player, c_name, 0, su_datetime, su_type, su_supporterid, su_inwork, su_finished, su_desc FROM support INNER JOIN characters ON (su_player = c_id) WHERE su_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 134:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf(mSQLQuery, 500, "SELECT br_id FROM bug_report WHERE br_fromid = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 136:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT c_name FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 137:
+        if(!ChkOpt(nNumOptions, 1)) break;
+    // runnerid, runnername, location, online
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_name = \"%s\"", nOptions[0].c_str());
+        break;
+    case 138:
+        if(!ChkOpt(nNumOptions, 1)) break;
+    // runnerid, runnername, location, online
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT br_type, br_location, br_datetime, br_supid, br_status, br_desc FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 143:
+        if(!ChkOpt(nNumOptions, 1)) break;
+    // runnerid, runnername, location, online
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT a.a_id, a.a_username, b.c_id, 0, b.c_location, b.c_online FROM `%s`.accounts AS a, `%s`.characters AS b WHERE b.c_name = \"%s\" AND a.a_id = b.a_id",
+                                  Config->GetOption("info_sql_database").c_str(), Config->GetOption("game_sql_database").c_str(), nOptions[0].c_str());
+        break;
+    case 144:
+        mResultFields = 2; // Replace "1" with Online/Offline!
+        snprintf (mSQLQuery, 500, "SELECT c_location, c_online FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 145:
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT a_email FROM `%s`.accounts WHERE a_id = %d", Config->GetOption("info_sql_database").c_str(), atoi(nOptions[0].c_str()));
+
+        break;
+    case 146:
+        mResultFields = 4;
+        // Too bad we named the row different...
+        char tSortRow[10];
+        if(!strncmp(nOptions[1].c_str(), "world", 5))
+            strcpy(tSortRow, "location");
+        else
+            strcpy(tSortRow, "name");
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_name LIKE \"%s\" ORDER BY `c_%s` LIMIT %d, %d", nOptions[0].c_str(), tSortRow, atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 147:
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_online = %d ORDER BY `c_%s` LIMIT %d, %d", atoi(nOptions[0].c_str()), nOptions[1].c_str(), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 148:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, \"0\", \"0\", c_id FROM clans INNER JOIN characters ON (cl_leader = c_id) WHERE (cl_id = %d)", atoi(nOptions[0].c_str()));
+
+        break;
+    case 150:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 151:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 153:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 154:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 155:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 156:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 157:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 158:
+        // Mission stuff. Will be added later!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 175:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT br_id, br_type, br_title, br_datetime FROM bug_report LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 176:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 8;
+        snprintf (mSQLQuery, 500, "SELECT br_type, br_status, br_title, br_desc, 0, br_datetime, br_location, br_fromid FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 181:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 3;
+        snprintf (mSQLQuery, 500, "SELECT c_name, apt_location, apt_password FROM apartments INNER JOIN characters ON (c_id = apt_owner) WHERE apt_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 183:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_name, (SELECT count(*) FROM characters WHERE c_clan = %d), c_name, apt_id, apt_location FROM clans INNER JOIN apartments ON (cl_appid = apt_id) INNER JOIN characters ON (c_clan = cl_id) AND (apt_owner = c_id) WHERE (cl_id = %d) GROUP BY c_id", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()));
+
+        break;
+    case 186:
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT c_id FROM characters WHERE c_name = \"%s\"", nOptions[0].c_str());
+
+        break;
+    case 220:
+        mResultFields = 4; //Fieldnum
+        snprintf (mSQLQuery, 500, "SELECT v_id, v_type, v_status, v_condition FROM vehicles WHERE v_owner = %i LIMIT %i, %i", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 221:
+        //VehicleControl order. "VehicleControl", "Type", "Status", "Condition", "Repairprice?"
+        mResultFields = 4; //Fieldnum
+        snprintf (mSQLQuery, 500, "SELECT v_type, v_status, v_condition, \"0\" FROM vehicles WHERE v_id = %s", nOptions[0].c_str());
+
+        break;
+    case 225:
+        // Statistics. Maybe later...
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 226:
+        // Statistics. Maybe later...
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 230:
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT st_id, st_factid, st_curval, st_curval-st_oldval FROM stockx");
+
+        break;
+    case 231:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT st_id, st_factid, st_curval, (st_curval - st_oldval) FROM stockx WHERE (st_id = %d)", atoi(nOptions[0].c_str()));
+
+        break;
+    case 232:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT sxd_id, st_factid, st_curval, sxd_amount, (sxd_amount * st_curval) FROM stockx_depots INNER JOIN stockx ON (sxd_st_id = st_id) WHERE (sxd_playerid = %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 233:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 7;
+        snprintf (mSQLQuery, 500, "SELECT st_factid, sxd_amount, (st_curval - st_oldval), st_curval, sxd_paid, (sxd_amount * st_curval), ((sxd_amount * st_curval) - sxd_paid) FROM stockx_depots INNER JOIN stockx ON (sxd_st_id = st_id) where sxd_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 234:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 3;
+        snprintf (mSQLQuery, 500, "SELECT sxd_id, sxd_amount, sxd_paid FROM stockx_depots INNER JOIN stockx ON (sxd_st_id = st_id) WHERE sxd_playerid = %d AND st_factid = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 250:
+        // Influence from CharID? Is stockx gm controlled??
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 251:
+        // What is this "influence" ? Check this on live servers!
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 260:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 2; //Fieldnum
+        snprintf (mSQLQuery, 500, "SELECT f_showname, f_name FROM forums WHERE f_area = %d+%d+%d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 261:
+        // Maybe even rewrite BB system.. its wrong written anyways....
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 262:
+        // This is wrong! 262 is the receiveDB request for FACTION threadlist. It should be limitet to that faction then
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND (fp_id = %s OR fp_replyid = %s)", nOptions[0].c_str(), nOptions[1].c_str());
+
+       //TODO Check this. Same (?) for ID 52,262,267,401 and 411
+        break;
+    case 266:
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND f_name = \'%s\' AND fp_replyid = 0 AND fp_clanid = %d LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 267:
+        mResultFields = 4;
+       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM `forum_posts`, forums, characters WHERE fp_forumid = f_id AND c_id = fp_fromid AND (fp_id = %s OR fp_replyid = %s)", nOptions[0].c_str(), nOptions[1].c_str());
+
+        break;
+    case 270:
+        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d  Tablename/Name is: [%s] ThreadID is: [%d]", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID, atoi(nOptions[0].c_str()), nOptions[1].c_str());
+        break;
+    case 360:
+        // Gamemaster name (char), Accountname, Location, Online, CharID
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT a.a_id, c.c_id, a.a_username, c.c_name, c.c_online, c.c_location FROM %s.characters AS c, %s.accounts AS a WHERE a.a_priv >= 50 AND c.c_online = %d AND c.a_id = a.a_id ORDER BY c.c_name LIMIT %d, %d",
+                                    Config->GetOption("game_sql_database").c_str(), Config->GetOption("info_sql_database").c_str(), atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 365:
+        // ID, short, name faction
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction FROM clans LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 366:
+        // ID, short, name faction WHERE clanname = %s
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_faction FROM clans WHERE cl_name LIKE \"%s\" LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 367:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 8;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_shortdesc, cl_name, cl_leader, cl_faction, cl_appid, cl_money, (SELECT count(*) FROM characters WHERE c_clan = %d) FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()));
+
+        break;
+    case 368:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cll_desc, cll_level FROM clanlevels WHERE cll_clanid = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 373:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT apt_id, apt_location, apt_type, apt_password FROM apartments WHERE apt_id = %d AND apt_owner = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 375:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 376:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online FROM characters WHERE c_name LIKE \"%s\" LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 377:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT DISTINCT a_id FROM characters WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 378:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT a_username, a_email, \"Since begin\", \"Never\", FROM_UNIXTIME(a_bandate) FROM `%s`.accounts WHERE a_id = %d", Config->GetOption("info_sql_database").c_str(), atoi(nOptions[0].c_str()));
+
+        break;
+    case 379:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, c_location, c_online, c_clan, cll_level FROM characters INNER JOIN clanlevels ON (cll_charid = c_id) WHERE c_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 380: // clean
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cl_name, cll_desc FROM clans INNER JOIN clanlevels ON (cll_clanid = cl_id) WHERE cl_id = %d AND cll_level = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 381:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, c_online FROM characters WHERE a_id = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 384: // clean
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT apt_id, apt_location, 0, apt_password FROM apartments WHERE apt_owner = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 400:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 4;
+       snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 401:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") AND (fp_id = %d OR fp_replyid = %d)", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 406:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1;
+       snprintf (mSQLQuery, 500, "SELECT count(fp_id) FROM forum_posts INNER JOIN forums ON (fp_forumid = f_id) WHERE f_name = \"%s\"", nOptions[0].c_str());
+
+        break;
+    case 410:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 4;
+       snprintf (mSQLQuery, 500, "SELECT fp_id, fp_name, c_name, fp_datetime FROM forum_posts INNER JOIN forums ON (fp_forumid = f_area) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\" AND fp_factionid = %d) LIMIT %d, %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 411:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 4;
+       snprintf (mSQLQuery, 500, "SELECT c_name, fp_name, fp_datetime, fp_content FROM forum_posts INNER JOIN forums ON (fp_forumid = f_area) INNER JOIN characters ON (fp_fromid = c_id) WHERE (f_name = \"%s\") AND (fp_id = %d OR fp_replyid = %d) AND (fp_factionid = %d)", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+
+    case 420:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT e_id, e_subject, c_name, e_new, e_replied, e_datetime FROM emails, characters WHERE e_fromid = c_id AND e_toid = %i LIMIT %i, %i", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 421:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        //MailControl order. "MailControl", "Mail ID", "Subject", "From", boolean Replied, "Date/Time", "FromID", "Content"
+        mResultFields = 7;
+        snprintf (mSQLQuery, 500, "SELECT e_id, e_subject, c_name, e_replied, e_datetime, e_fromid, e_body FROM emails, characters WHERE e_fromid = c_id AND e_id = %s", nOptions[0].c_str());
+
+        break;
+    case 425:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        //Send mail order. "SendMail", "id"
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT c_id FROM characters WHERE c_name = \'%s\'", nOptions[0].c_str());
+
+        break;
+    case 430:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT a.c_id, a.c_conid, b.c_name, a.c_desc FROM contacts as a, characters as b WHERE a.c_conid = b.c_id AND a.c_listid = %s AND c_type = %s", nOptions[0].c_str(), nOptions[1].c_str());
+
+        break;
+    case 431:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT a.c_id, a.c_conid, b.c_name, a.c_desc FROM contacts as a, characters as b WHERE a.c_conid = b.c_id AND a.c_id = %s", nOptions[0].c_str());
+
+        break;
+    case 435:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM contacts WHERE c_listid = %s AND c_type = %s", nOptions[0].c_str(), nOptions[1].c_str());
+
+        break;
+    case 436:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name FROM characters WHERE c_name LIKE \'%%%s%%\' LIMIT %s, %s", nOptions[0].c_str(), nOptions[1].c_str(), nOptions[2].c_str());
+
+        break;
+    case 437:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 1; //Fieldnum
+        snprintf (mSQLQuery, 500, "SELECT c_name FROM characters WHERE c_id = %s", nOptions[0].c_str());
+
+        break;
+    case 445:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT nc_id, nc_name FROM neochronicle WHERE nc_lang = %d ORDER BY nc_id DESC LIMIT %d, %d", atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 446:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT nc_id, nc_lang, nc_datetime, nc_name, nc_content FROM neochronicle WHERE nc_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 453:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT g_id, 0, g_part, g_title, g_language FROM guides WHERE g_chapter = %d AND g_language = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 455:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 3;
+        // Opt 2 is Language
+        snprintf (mSQLQuery, 500, "SELECT g_id, g_part, g_title FROM guides WHERE g_chapter = %d AND g_language = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 456:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT g_id, g_language, g_title, g_content FROM guides WHERE g_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 458: // Statisics
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 459: // Statisics
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 510: // ClanWars: Overview
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT cw_id, cl_name, cw_starttime, cw_status FROM clanwars INNER JOIN clans ON (cw_initclan = cl_id) or (cw_enemyclan = cl_id) WHERE (cw_enemyclan = %d OR cw_initclan = %d) AND (cl_id != %d) LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+        break;
+    case 511: // ClanWars: Selfdeclared wars
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT cw_id, cl_name, cw_starttime, cw_status FROM clanwars INNER JOIN clans ON (cw_enemyclan = cl_id) WHERE cw_initclan = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        break;
+    case 512: // ClanWars: Foreigndeclared wars
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 4;
+        snprintf (mSQLQuery, 500, "SELECT cw_id, cl_name, cw_starttime, cw_status FROM clanwars INNER JOIN clans ON (cw_initclan = cl_id) WHERE cw_enemyclan = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        break;
+    case 513:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_name FROM clans WHERE cl_faction = %d AND cl_id != %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+        break;
+    case 514:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cl_id, cl_name FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 520:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 10;
+        snprintf (mSQLQuery, 500, "SELECT cl_faction, cl_shortdesc, cl_name, cl_description, 0, cl_appid, 80, cl_money, (SELECT count(*) FROM outposts WHERE o_clan = %d), (SELECT count(*) FROM characters WHERE c_clan = %d) FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[0].c_str()));
+
+        break;
+    case 521:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, cll_desc, 0, c_online FROM characters INNER JOIN clanlevels ON (c_id = cll_charid) WHERE c_clan = %d AND cll_level >= %d AND cll_level < 15 LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 522:
+        if(!ChkOpt(nNumOptions, 5)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT c_id, c_name, 0, cll_desc, 0, c_online FROM characters INNER JOIN clanlevels ON (c_id = cll_charid) WHERE cll_level >= %d AND cll_level <= %d AND c_clan = %d ORDER BY cll_level DESC LIMIT %d, %d", atoi(nOptions[2].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[0].c_str()), atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));
+
+        break;
+    case 523:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT cl_shortdesc, cl_name, cl_leader, cl_description, cl_minsympathy FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 540:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT apt_id, apt_location FROM apartments WHERE apt_owner = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 541:
+        if(!ChkOpt(nNumOptions, 3)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT v_id, v_type FROM vehicles WHERE v_owner = %d LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 542:
+        if(!ChkOpt(nNumOptions, 2)) break;
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT v_id, v_type, v_world, v_status, v_condition FROM vehicles WHERE v_owner = %d and v_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+
+        break;
+    case 544:
+        if(!ChkOpt(nNumOptions, 4)) break;
+        mResultFields = 1;
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM clanwars WHERE (cw_initclan = %d AND cw_enemyclan = %d) OR (cw_enemyclan = %d AND cw_initclan = %d)", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()));
+
+        break;
+    case 546:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 2;
+        snprintf (mSQLQuery, 500, "SELECT cw_starttime, (TO_DAYS(NOW()) - TO_DAYS(cw_starttime)) FROM clanwars WHERE cw_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 547:
+        if(!ChkOpt(nNumOptions, 1)) break;
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT cw_initclan, cw_enemyclan, cw_starttime, cw_status, cw_statement_initiator, cw_statement_enemy FROM clanwars WHERE cw_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 557:
+        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d means that you want to edit an DialogScript from the server. This is not supportet yet!", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 558:
+        Console->Print("%s [Pterminal::HandleReceiveDB] QueryID %d means that you want to edit an DialogScript from the server. This is not supportet yet!", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 562:
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT cb_inscription FROM datacubes WHERE cb_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 569:
+        // Faction representatives. Not stored yet... is it?
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 570:
+        // Clan representatives. Stored but this query wants votes too... Maybe later
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 571:
+        // Clan representatives. Stored but this query wants votes too... Maybe later
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 572:
+        // Runner voting. Not stored yet
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 573:
+        // Next election date
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 574:
+        mResultFields = 6;
+        snprintf (mSQLQuery, 500, "SELECT count(c_id) FROM characters WHERE c_faction = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 575:
+        // Runner satisfaction with faction
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 576:
+        // Check if vote from runner is already stored
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 582:
+        // Clan representative details. Faction rank etc... not stored yet
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 583:
+        // Clan representative details. Faction rank etc... not stored yet
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 584:
+        // Clan representative details. Faction rank etc... not stored yet
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 587:
+        // Clan representative stuff again...
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 603:
+        mResultFields = 1;
+        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_status = 0");
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_inwork = 0 AND su_finished = 0");
+
+        break;
+    case 604:
+        mResultFields = 1;
+        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_status = 1");
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_inwork = 1 AND su_finished = 0");
+
+        break;
+    case 605:
+        mResultFields = 1;
+        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_status = 2");
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_finished = 1");
+
+        break;
+    case 606:
+        mResultFields = 1;
+        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report`");
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support");
+
+        break;
+    case 607: // Dont know how to select data from sql where no data to JOIN is there anymore :/
+    // This should query ID, RunnerID and Date from bug reports where runnerID is unknown
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 608:
+        mResultFields = 5;
+        snprintf (mSQLQuery, 500, "SELECT br_id, br_fromid, br_location, br_status, br_datetime FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 609:
+        mResultFields = 1;
+        //snprintf (mSQLQuery, 500, "SELECT count(*) FROM `bug report` WHERE br_supid = %s", nOptions[0].c_str());
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_supporterid = %d", atoi(nOptions[0].c_str()));
+
+        break;
+    case 610:
+        mResultFields = 6;
+        //snprintf (mSQLQuery, 500, "SELECT br_id, \"0\", c_name, br_location, br_status = 2, br_datetime FROM `bug report`, characters WHERE c_id = br_fromid AND br_supid = %s AND br_status > 0 LIMIT %s, %s", nOptions[0].c_str(), nOptions[1].c_str(), nOptions[2].c_str());
+        snprintf (mSQLQuery, 500, "SELECT su_id, su_supporterid, c_name, su_worldid, su_finished, su_datetime FROM support INNER JOIN characters ON (su_supporterid = c_id) WHERE su_supporterid = %d AND su_finished = 1 LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+
+        break;
+    case 611:// Well, its meant to show date specific stuff. I will rewrite this soon...
+        snprintf (mSQLQuery, 500, "SELECT count(*) FROM support WHERE su_supporterid = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 612:// Well, its meant to show date specific stuff. I will rewrite this soon...
+        snprintf (mSQLQuery, 500, "SELECT su_id, su_supporterid, c_name, su_worldid, su_finished, su_datetime FROM support INNER JOIN characters ON (su_supporterid = c_id) WHERE su_supporterid = %d AND su_finished = 1 LIMIT %d, %d", atoi(nOptions[0].c_str()), atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));
+        break;
+    case 625: // Faction council stuff
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 626: // Faction council stuff
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 627: // Faction council stuff
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 628: // Faction council stuff
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 629: // Faction council stuff
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    default:
+        Console->Print("%s [Pterminal::HandleReceiveDB]  Unknown QueryID %d", Console->ColorText(RED,BLACK,"Warning"), nDBID);
+        return false;
+    }
+
+    if(strlen(mSQLQuery) == 0)
+        return false;
+// ---------------
+    MYSQL_RES *result = NULL;
+    MYSQL_ROW row;
+    int tNumRows = 0;
+
+    result = MySQL->GameResQuery(mSQLQuery);
+    if (!result)
+    {
+        Console->Print("Cannot query DB. DBID: %d query was: %s", nDBID, mSQLQuery);
+        MySQL->ShowGameSQLError();
+        return false;
+    }
+
+    PMessage* tDBResult = new PMessage();
+    tNumRows = mysql_num_rows(result);
+
+    // Loop all result rows
+    for (int i = 0; i < tNumRows ; i++)
+    {
+        row = mysql_fetch_row( result ) ;
+        // Loop all result fields and push answers into Message
+        for (int t = 0; t < mResultFields; t++)
+        {
+            *tDBResult << ( uint16_t )(strlen(row[t]) + 1);
+            *tDBResult << row[t];
+        }
+    }
+
+    // Build result messages
+    char tCmd[100];
+    memset(tCmd, '\0', 100);
+    strncpy(tCmd, nCommandName->c_str(), 100);
+
+    PMessage* tmpMsg_allowed = MsgBuilder->BuildTryAccessAnswerMsg( nClient, tCmd, true );
+    PMessage* tmpMsg_result = MsgBuilder->BuildReceiveDBAnswerMsg( nClient, tDBResult, nCommandName, tNumRows, mResultFields);
+
+    nClient->SendUDPMessage(tmpMsg_allowed);
+    nClient->FragmentAndSendUDPMessage(tmpMsg_result, 0x68);
+
+    return true;
+}
index 96a57b1..3490aef 100644 (file)
-#include <cstring>\r
-#include <sstream>\r
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-bool PTerminal::HandleUpdateDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown)\r
-{\r
-    std::ostringstream tLongSQL; // omg my eyes... Stringstream is one of the worst inventions ever! Stick with printf syntax!!111\r
-    char tShortSQL[1024]; // Use this for small updates that will not exceed 1kb\r
-    memset(tShortSQL, '\0', 1024);\r
-    bool tSuccess = false;\r
-\r
-    //Console->Print("UpdateDB ID: %d", nDBID);\r
-    switch (nDBID)\r
-    {\r
-    case 5:\r
-        tLongSQL << "INSERT INTO neochronicle (nc_icon, nc_author, nc_datetime, nc_name, nc_content)";\r
-        tLongSQL << " VALUES (" << atoi(nOptions[0].c_str()) << ", \"" << nOptions[1] << "\", \"" << nOptions[2] << "\", \"" << nOptions[3] << "\", \"" << nOptions[4] << "\")";\r
-\r
-        break;\r
-    case 6:\r
-        // UPDATE when Neocronicle DB is changed! author must be CHAR not INT\r
-        break;\r
-    case 7: // Delete neocronicle\r
-        snprintf(tShortSQL, 1024, "DELETE FROM neochronicle WHERE nc_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 12:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 53: // Runner writing to public board\r
-        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str(), nOptions[4].c_str(), nOptions[5].c_str());\r
-        break;\r
-    case 58:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 62: // Set new outpost security\r
-        snprintf(tShortSQL, 1024, "UPDATE outposts SET o_security = %d WHERE o_outnum = %d AND o_clan = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        break;\r
-\r
-    case 66: // Claninfo stuff that is somehow never used... Print error if it is\r
-    case 67:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB] QueryID %d should never happen. Please contact Linux Addited forums!", Console->ColorText(RED,BLACK,"Notice"), nDBID);\r
-        break;\r
-\r
-    case 77: // Delete old clanlevel\r
-        snprintf(tShortSQL, 1024, "DELETE FROM clanlevels WHERE cll_clanid = %d AND cll_level = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-        break;\r
-    case 78: // Add new clanlevel\r
-        snprintf(tShortSQL, 1024, "INSERT INTO clanlevels (cll_clanid, cll_desc, cll_level) VALUES (%d, \"%s\", %d)", atoi(nOptions[0].c_str()), nOptions[1].c_str(), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 84: // Take/Give money to/from clan\r
-        tLongSQL << "INSERT INTO moneytransactions (mt_clanid, mt_player, mt_amount, mt_date, mt_comment) ";\r
-        tLongSQL << "VALUES (" << atoi(nOptions[0].c_str()) << ", " << atoi(nOptions[1].c_str()) << ", " << atoi(nOptions[2].c_str()) << ", \"" << nOptions[3] << "\", \"" << nOptions[4] << "\")";\r
-        break;\r
-    case 94: // Update runner description\r
-        snprintf(tShortSQL, 1024, "UPDATE characters SET c_desc = \"%s\" WHERE c_id = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()));\r
-        break;\r
-    case 97:\r
-        // Just ignore that... KK required some extra updates here\r
-        tSuccess = true;\r
-        //Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 120: // Create support call\r
-        snprintf(tShortSQL, 1024, "INSERT INTO support (su_player, su_worldid, su_type, su_desc) VALUES (%d, %d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str());\r
-        break;\r
-    case 121:\r
-        snprintf(tShortSQL, 1024, "UPDATE support SET su_inwork = 1, su_supporterid = %d WHERE su_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-        break;\r
-    case 122:\r
-        snprintf(tShortSQL, 1024, "UPDATE support SET su_inwork = 0, su_supporterid = 0 WHERE su_id = %d AND su_supporterid = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-        break;\r
-    case 123:\r
-        snprintf(tShortSQL, 1024, "UPDATE support SET su_inwork = 1, su_finished = 1, su_supporterid = %d WHERE su_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-        break;\r
-    case 124:\r
-        snprintf(tShortSQL, 1024, "DELETE FROM support WHERE su_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 133:\r
-        tSuccess = true;\r
-        //Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 139:\r
-        snprintf(tShortSQL, 1024, "UPDATE characters SET c_location = %d WHERE c_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));\r
-        break;\r
-    case 142:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 149: // Changeleader 2nd step. Update clanappartment owner\r
-        snprintf(tShortSQL, 1024, "UPDATE apartments SET apt_owner = %d WHERE apt_id = %d AND apt_owner = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 160: // Missions, not yet\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 161: // Missions, not yet\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 162: // Missions, not yet\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 163: // Missions, not yet\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 164: // Missions, not yet\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 165: // Missions, not yet\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 170: // Enter new bug\r
-        snprintf(tShortSQL, 1024, "INSERT INTO bug_report (br_type, br_status, br_title, br_desc, br_location, br_fromid, br_datetime) VALUES (%d, %d, \"%s\", \"%s\", %d, %d, NOW())", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str(), nOptions[3].c_str(), atoi(nOptions[4].c_str()), atoi(nOptions[5].c_str()));\r
-        break;\r
-    case 172: // Delete bug id %d\r
-        snprintf(tShortSQL, 1024, "DELETE FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 180:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 182:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 235:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 252:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 263: // Runner writing to Faction Board\r
-        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_factionid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()), nOptions[4].c_str(), nOptions[5].c_str(), nOptions[6].c_str());\r
-        break;\r
-    case 268: // Runner writing to ClanBoard\r
-        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_clanid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()), nOptions[4].c_str(), nOptions[5].c_str(), nOptions[6].c_str());\r
-        break;\r
-    case 370: // GM ClanRepair\r
-        snprintf(tShortSQL, 1024, "INSERT INTO clanlevels (cll_clanid, cll_level, cll_desc) VALUES (%d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str());\r
-        break;\r
-    case 385: // Clandelete 1/7 Clanlevels\r
-        snprintf(tShortSQL, 1024, "DELETE FROM clanlevels WHERE cl_clanid = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 386: // Clandelete 2/7 Outposts\r
-        snprintf(tShortSQL, 1024, "UPDATE outposts SET o_clan = 0 WHERE o_clan = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 387: // Clandelete 3/7 Free users from clans\r
-        snprintf(tShortSQL, 1024, "UPDATE characters SET c_clan = 0 WHERE c_clan = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 388: // Clandelete 4/7 The clan itself\r
-        snprintf(tShortSQL, 1024, "DELETE FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 389: // Clandelete 5/7 ?\r
-        tSuccess = true;\r
-        break;\r
-    case 390: // Clandelete 6/7 Clanappartment\r
-        snprintf(tShortSQL, 1024, "DELETE FROM apartments WHERE apt_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 391: // Clandelete 7/7 ?\r
-        tSuccess = true;\r
-        break;\r
-    case 402: // GM writing to publicforum\r
-        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str(), nOptions[4].c_str(), nOptions[5].c_str());\r
-        break;\r
-    case 404: // GM deleting forum entry step 1\r
-        snprintf(tShortSQL, 1024, "DELETE FROM forum_posts WHERE fp_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 405: // GM deleting forum entry step 2\r
-        snprintf(tShortSQL, 1024, "DELETE FROM forum_posts WHERE fp_replyid = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 412: // GM writing to faction forum\r
-        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_factionid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()), nOptions[4].c_str(), nOptions[5].c_str(), nOptions[6].c_str());\r
-        break;\r
-    case 422: // Mark email as replied\r
-        snprintf(tShortSQL, 1024, "UPDATE emails SET e_replied = 1 WHERE e_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 423: // Write new email\r
-        snprintf(tShortSQL, 1024, "INSERT INTO emails (e_fromid,e_toid,e_datetime,e_subject,e_body) VALUES (%d, %d, \"%s\", \"%s\", \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str(), nOptions[3].c_str(), nOptions[4].c_str());\r
-        break;\r
-    case 424: // Delete email\r
-        snprintf(tShortSQL, 1024, "DELETE FROM emails WHERE e_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 426: // Mark email as read\r
-        snprintf(tShortSQL, 1024, "UPDATE emails SET e_new = 0 WHERE e_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 432: // Add new contact\r
-        snprintf(tShortSQL, 1024, "INSERT INTO contacts (c_listid,c_conid,c_type,c_desc) VALUES (%d, %d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str());\r
-        break;\r
-    case 433: // Edit contact\r
-        snprintf(tShortSQL, 1024, "UPDATE contacts SET c_type = %d, c_desc = \"%s\" WHERE c_id = %d", atoi(nOptions[0].c_str()), nOptions[1].c_str(), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 434: // Delete contact\r
-        snprintf(tShortSQL, 1024, "DELETE FROM contacts WHERE c_id = %d", atoi(nOptions[0].c_str()));\r
-        break;\r
-    case 447:\r
-        snprintf(tShortSQL, 1024, "INSERT INTO neochronicle (nc_icon, nc_author, nc_datetime, nc_name, nc_content, nc_lang) VALUES (%d, \"%s\", \"%s\", \"%s\", \"%s\", %d)", atoi(nOptions[0].c_str()), nOptions[1].c_str(), nOptions[2].c_str(), nOptions[3].c_str(), nOptions[4].c_str(), atoi(nOptions[5].c_str()));\r
-        break;\r
-    case 450:\r
-        snprintf(tShortSQL, 1024, "INSERT INTO guides (g_chapter, g_part, g_title, g_content, g_language) VALUES (%d, %d, \"%s\", \"%s\", %d)", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str(), nOptions[3].c_str(), atoi(nOptions[4].c_str()));\r
-        break;\r
-    case 515: // Create new clanwar\r
-        snprintf(tShortSQL, 1024, "INSERT INTO clanwars (cw_initclan, cw_enemyclan, cw_starttime) VALUES (%d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str());\r
-        break;\r
-    case 516:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 517:\r
-        // Special: Check if Clan of our char is = nOption2\r
-        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))\r
-            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_status = %d WHERE cw_id = %d AND cw_initclan = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        // else: SQL Query is empty = failed as result\r
-        break;\r
-    case 518:\r
-        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))\r
-            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_status = %d WHERE cw_id = %d AND cw_enemyclan = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        // else: SQL Query is empty = failed as result\r
-        break;\r
-    case 519:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 525: // Update clan short\r
-        tLongSQL << "UPDATE clans SET cl_shortdesc = \"" << nOptions[0] << "\" WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());\r
-\r
-        break;\r
-    case 526: // Update clan name\r
-        tLongSQL << "UPDATE clans SET cl_name = \"" << nOptions[0] << "\" WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());\r
-\r
-        break;\r
-    case 527: // Update clanapp password\r
-        //UPDATE apartments SET apt_password = x WHERE apt_owner = x AND apt_id = (SELECT clans.cl_appid WHERE clans.cl_id = x)\r
-        tLongSQL << "UPDATE apartments SET apt_password = \"" << nOptions[0] << "\" WHERE apt_owner = " << atoi(nOptions[2].c_str()) << " AND apt_id = (SELECT cl_appid FROM clans WHERE cl_id = " << atoi(nOptions[1].c_str()) << ")";\r
-        break;\r
-    case 528:\r
-        tLongSQL << "UPDATE clans SET cl_minsympathy = " << atoi(nOptions[0].c_str()) << " WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());\r
-        break;\r
-    case 529:\r
-        tLongSQL << "UPDATE clans SET cl_description = \"" << nOptions[0] << "\" WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());\r
-        break;\r
-    case 543:\r
-        // Only delete if: option 2 is >= 7 (days); option0 is 5 or 6; option 4 = our clanid\r
-        if(atoi(nOptions[2].c_str()) >= 7)\r
-            if(atoi(nOptions[0].c_str()) == 5 || atoi(nOptions[0].c_str()) == 6)\r
-                if(nClient->GetChar()->GetClan() == atoi(nOptions[4].c_str()))\r
-                    snprintf(tShortSQL, 1024, "DELETE FROM clanwars WHERE (cw_status = 5 OR cw_status = 6) AND cw_id = %d AND cw_initclan = %d", atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));\r
-\r
-        //Console->Print("%s", tShortSQL);\r
-        break;\r
-    case 548:\r
-        // Check clanmembership\r
-        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))\r
-            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_statement_initiator = \"%s\" WHERE cw_id = %d AND cw_initclan = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 549:\r
-        // Check clanmembership\r
-        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))\r
-            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_statement_enemy = \"%s\" WHERE cw_id = %d AND cw_enemyclan = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));\r
-        break;\r
-    case 555:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 556:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 561:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 577:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 578:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 579:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 580:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 581:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 585:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 590:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 591:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    case 600: // Just ok, skip it\r
-        tSuccess = true;\r
-        break;\r
-    case 601: // Just ok, skip it\r
-        tSuccess = true;\r
-        break;\r
-    case 630:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);\r
-        break;\r
-    default:\r
-        Console->Print("%s [Pterminal::HandleUpdateDB]  Unknown QueryID %d", Console->ColorText(RED,BLACK,"Warning"), nDBID);\r
-        return false;\r
-    }\r
-\r
-// -------\r
-    if(tLongSQL.str().length() > 0)\r
-    {\r
-        if(MySQL->GameQuery(tLongSQL.str().c_str()))\r
-        {\r
-            Console->Print("Cannot update DB. query was: %s", tLongSQL.str().c_str());\r
-            MySQL->ShowGameSQLError();\r
-            tSuccess = false;\r
-        }\r
-        else\r
-            tSuccess = true;\r
-    }\r
-    else if(strlen(tShortSQL) > 0)\r
-    {\r
-        if(MySQL->GameQuery(tShortSQL))\r
-        {\r
-            Console->Print("Cannot update DB. query was: %s", tShortSQL);\r
-            MySQL->ShowGameSQLError();\r
-            tSuccess = false;\r
-        }\r
-        else\r
-            tSuccess = true;\r
-    }\r
-\r
-    // Notice client about UpdateDB result\r
-    char tCmd[100];\r
-    memset(tCmd, '\0', 100);\r
-    strncpy(tCmd, nCommandName->c_str(), 100);\r
-\r
-    PMessage* tmpMsg = MsgBuilder->BuildTryAccessAnswerMsg(nClient, tCmd, tSuccess);\r
-    nClient->SendUDPMessage(tmpMsg);\r
-    return true;\r
-}\r
+#include <cstring>
+#include <sstream>
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+bool PTerminal::HandleUpdateDB(PClient* nClient, uint16_t mTerminalSessionId, std::string *nCommandName, std::string *nOptions, uint8_t nNumOptions, uint16_t nDBID, uint8_t nUnknown)
+{
+    std::ostringstream tLongSQL; // omg my eyes... Stringstream is one of the worst inventions ever! Stick with printf syntax!!111
+    char tShortSQL[1024]; // Use this for small updates that will not exceed 1kb
+    memset(tShortSQL, '\0', 1024);
+    bool tSuccess = false;
+
+    //Console->Print("UpdateDB ID: %d", nDBID);
+    switch (nDBID)
+    {
+    case 5:
+        tLongSQL << "INSERT INTO neochronicle (nc_icon, nc_author, nc_datetime, nc_name, nc_content)";
+        tLongSQL << " VALUES (" << atoi(nOptions[0].c_str()) << ", \"" << nOptions[1] << "\", \"" << nOptions[2] << "\", \"" << nOptions[3] << "\", \"" << nOptions[4] << "\")";
+
+        break;
+    case 6:
+        // UPDATE when Neocronicle DB is changed! author must be CHAR not INT
+        break;
+    case 7: // Delete neocronicle
+        snprintf(tShortSQL, 1024, "DELETE FROM neochronicle WHERE nc_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 12:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 53: // Runner writing to public board
+        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str(), nOptions[4].c_str(), nOptions[5].c_str());
+        break;
+    case 58:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 62: // Set new outpost security
+        snprintf(tShortSQL, 1024, "UPDATE outposts SET o_security = %d WHERE o_outnum = %d AND o_clan = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        break;
+
+    case 66: // Claninfo stuff that is somehow never used... Print error if it is
+    case 67:
+        Console->Print("%s [Pterminal::HandleUpdateDB] QueryID %d should never happen. Please contact Linux Addited forums!", Console->ColorText(RED,BLACK,"Notice"), nDBID);
+        break;
+
+    case 77: // Delete old clanlevel
+        snprintf(tShortSQL, 1024, "DELETE FROM clanlevels WHERE cll_clanid = %d AND cll_level = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+        break;
+    case 78: // Add new clanlevel
+        snprintf(tShortSQL, 1024, "INSERT INTO clanlevels (cll_clanid, cll_desc, cll_level) VALUES (%d, \"%s\", %d)", atoi(nOptions[0].c_str()), nOptions[1].c_str(), atoi(nOptions[2].c_str()));
+        break;
+    case 84: // Take/Give money to/from clan
+        tLongSQL << "INSERT INTO moneytransactions (mt_clanid, mt_player, mt_amount, mt_date, mt_comment) ";
+        tLongSQL << "VALUES (" << atoi(nOptions[0].c_str()) << ", " << atoi(nOptions[1].c_str()) << ", " << atoi(nOptions[2].c_str()) << ", \"" << nOptions[3] << "\", \"" << nOptions[4] << "\")";
+        break;
+    case 94: // Update runner description
+        snprintf(tShortSQL, 1024, "UPDATE characters SET c_desc = \"%s\" WHERE c_id = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()));
+        break;
+    case 97:
+        // Just ignore that... KK required some extra updates here
+        tSuccess = true;
+        //Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 120: // Create support call
+        snprintf(tShortSQL, 1024, "INSERT INTO support (su_player, su_worldid, su_type, su_desc) VALUES (%d, %d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str());
+        break;
+    case 121:
+        snprintf(tShortSQL, 1024, "UPDATE support SET su_inwork = 1, su_supporterid = %d WHERE su_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+        break;
+    case 122:
+        snprintf(tShortSQL, 1024, "UPDATE support SET su_inwork = 0, su_supporterid = 0 WHERE su_id = %d AND su_supporterid = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+        break;
+    case 123:
+        snprintf(tShortSQL, 1024, "UPDATE support SET su_inwork = 1, su_finished = 1, su_supporterid = %d WHERE su_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+        break;
+    case 124:
+        snprintf(tShortSQL, 1024, "DELETE FROM support WHERE su_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 133:
+        tSuccess = true;
+        //Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 139:
+        snprintf(tShortSQL, 1024, "UPDATE characters SET c_location = %d WHERE c_id = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()));
+        break;
+    case 142:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 149: // Changeleader 2nd step. Update clanappartment owner
+        snprintf(tShortSQL, 1024, "UPDATE apartments SET apt_owner = %d WHERE apt_id = %d AND apt_owner = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        break;
+    case 160: // Missions, not yet
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 161: // Missions, not yet
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 162: // Missions, not yet
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 163: // Missions, not yet
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 164: // Missions, not yet
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 165: // Missions, not yet
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 170: // Enter new bug
+        snprintf(tShortSQL, 1024, "INSERT INTO bug_report (br_type, br_status, br_title, br_desc, br_location, br_fromid, br_datetime) VALUES (%d, %d, \"%s\", \"%s\", %d, %d, NOW())", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str(), nOptions[3].c_str(), atoi(nOptions[4].c_str()), atoi(nOptions[5].c_str()));
+        break;
+    case 172: // Delete bug id %d
+        snprintf(tShortSQL, 1024, "DELETE FROM bug_report WHERE br_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 180:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 182:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 235:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 252:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 263: // Runner writing to Faction Board
+        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_factionid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()), nOptions[4].c_str(), nOptions[5].c_str(), nOptions[6].c_str());
+        break;
+    case 268: // Runner writing to ClanBoard
+        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_clanid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()), nOptions[4].c_str(), nOptions[5].c_str(), nOptions[6].c_str());
+        break;
+    case 370: // GM ClanRepair
+        snprintf(tShortSQL, 1024, "INSERT INTO clanlevels (cll_clanid, cll_level, cll_desc) VALUES (%d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str());
+        break;
+    case 385: // Clandelete 1/7 Clanlevels
+        snprintf(tShortSQL, 1024, "DELETE FROM clanlevels WHERE cl_clanid = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 386: // Clandelete 2/7 Outposts
+        snprintf(tShortSQL, 1024, "UPDATE outposts SET o_clan = 0 WHERE o_clan = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 387: // Clandelete 3/7 Free users from clans
+        snprintf(tShortSQL, 1024, "UPDATE characters SET c_clan = 0 WHERE c_clan = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 388: // Clandelete 4/7 The clan itself
+        snprintf(tShortSQL, 1024, "DELETE FROM clans WHERE cl_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 389: // Clandelete 5/7 ?
+        tSuccess = true;
+        break;
+    case 390: // Clandelete 6/7 Clanappartment
+        snprintf(tShortSQL, 1024, "DELETE FROM apartments WHERE apt_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 391: // Clandelete 7/7 ?
+        tSuccess = true;
+        break;
+    case 402: // GM writing to publicforum
+        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str(), nOptions[4].c_str(), nOptions[5].c_str());
+        break;
+    case 404: // GM deleting forum entry step 1
+        snprintf(tShortSQL, 1024, "DELETE FROM forum_posts WHERE fp_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 405: // GM deleting forum entry step 2
+        snprintf(tShortSQL, 1024, "DELETE FROM forum_posts WHERE fp_replyid = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 412: // GM writing to faction forum
+        snprintf(tShortSQL, 1024, "INSERT INTO forum_posts (fp_forumid, fp_factionid, fp_replyid, fp_fromid, fp_datetime, fp_name, fp_content) VALUES ((SELECT f_area FROM forums WHERE f_name = \"%s\"), %d, %d, %d, \"%s\", \"%s\", \"%s\")", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), atoi(nOptions[3].c_str()), nOptions[4].c_str(), nOptions[5].c_str(), nOptions[6].c_str());
+        break;
+    case 422: // Mark email as replied
+        snprintf(tShortSQL, 1024, "UPDATE emails SET e_replied = 1 WHERE e_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 423: // Write new email
+        snprintf(tShortSQL, 1024, "INSERT INTO emails (e_fromid,e_toid,e_datetime,e_subject,e_body) VALUES (%d, %d, \"%s\", \"%s\", \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str(), nOptions[3].c_str(), nOptions[4].c_str());
+        break;
+    case 424: // Delete email
+        snprintf(tShortSQL, 1024, "DELETE FROM emails WHERE e_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 426: // Mark email as read
+        snprintf(tShortSQL, 1024, "UPDATE emails SET e_new = 0 WHERE e_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 432: // Add new contact
+        snprintf(tShortSQL, 1024, "INSERT INTO contacts (c_listid,c_conid,c_type,c_desc) VALUES (%d, %d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()), nOptions[3].c_str());
+        break;
+    case 433: // Edit contact
+        snprintf(tShortSQL, 1024, "UPDATE contacts SET c_type = %d, c_desc = \"%s\" WHERE c_id = %d", atoi(nOptions[0].c_str()), nOptions[1].c_str(), atoi(nOptions[2].c_str()));
+        break;
+    case 434: // Delete contact
+        snprintf(tShortSQL, 1024, "DELETE FROM contacts WHERE c_id = %d", atoi(nOptions[0].c_str()));
+        break;
+    case 447:
+        snprintf(tShortSQL, 1024, "INSERT INTO neochronicle (nc_icon, nc_author, nc_datetime, nc_name, nc_content, nc_lang) VALUES (%d, \"%s\", \"%s\", \"%s\", \"%s\", %d)", atoi(nOptions[0].c_str()), nOptions[1].c_str(), nOptions[2].c_str(), nOptions[3].c_str(), nOptions[4].c_str(), atoi(nOptions[5].c_str()));
+        break;
+    case 450:
+        snprintf(tShortSQL, 1024, "INSERT INTO guides (g_chapter, g_part, g_title, g_content, g_language) VALUES (%d, %d, \"%s\", \"%s\", %d)", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str(), nOptions[3].c_str(), atoi(nOptions[4].c_str()));
+        break;
+    case 515: // Create new clanwar
+        snprintf(tShortSQL, 1024, "INSERT INTO clanwars (cw_initclan, cw_enemyclan, cw_starttime) VALUES (%d, %d, \"%s\")", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), nOptions[2].c_str());
+        break;
+    case 516:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 517:
+        // Special: Check if Clan of our char is = nOption2
+        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))
+            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_status = %d WHERE cw_id = %d AND cw_initclan = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        // else: SQL Query is empty = failed as result
+        break;
+    case 518:
+        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))
+            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_status = %d WHERE cw_id = %d AND cw_enemyclan = %d", atoi(nOptions[0].c_str()), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        // else: SQL Query is empty = failed as result
+        break;
+    case 519:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 525: // Update clan short
+        tLongSQL << "UPDATE clans SET cl_shortdesc = \"" << nOptions[0] << "\" WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());
+
+        break;
+    case 526: // Update clan name
+        tLongSQL << "UPDATE clans SET cl_name = \"" << nOptions[0] << "\" WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());
+
+        break;
+    case 527: // Update clanapp password
+        //UPDATE apartments SET apt_password = x WHERE apt_owner = x AND apt_id = (SELECT clans.cl_appid WHERE clans.cl_id = x)
+        tLongSQL << "UPDATE apartments SET apt_password = \"" << nOptions[0] << "\" WHERE apt_owner = " << atoi(nOptions[2].c_str()) << " AND apt_id = (SELECT cl_appid FROM clans WHERE cl_id = " << atoi(nOptions[1].c_str()) << ")";
+        break;
+    case 528:
+        tLongSQL << "UPDATE clans SET cl_minsympathy = " << atoi(nOptions[0].c_str()) << " WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());
+        break;
+    case 529:
+        tLongSQL << "UPDATE clans SET cl_description = \"" << nOptions[0] << "\" WHERE cl_id = " << atoi(nOptions[1].c_str()) << " AND cl_leader = " << atoi(nOptions[2].c_str());
+        break;
+    case 543:
+        // Only delete if: option 2 is >= 7 (days); option0 is 5 or 6; option 4 = our clanid
+        if(atoi(nOptions[2].c_str()) >= 7)
+            if(atoi(nOptions[0].c_str()) == 5 || atoi(nOptions[0].c_str()) == 6)
+                if(nClient->GetChar()->GetClan() == atoi(nOptions[4].c_str()))
+                    snprintf(tShortSQL, 1024, "DELETE FROM clanwars WHERE (cw_status = 5 OR cw_status = 6) AND cw_id = %d AND cw_initclan = %d", atoi(nOptions[3].c_str()), atoi(nOptions[4].c_str()));
+
+        //Console->Print("%s", tShortSQL);
+        break;
+    case 548:
+        // Check clanmembership
+        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))
+            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_statement_initiator = \"%s\" WHERE cw_id = %d AND cw_initclan = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        break;
+    case 549:
+        // Check clanmembership
+        if(nClient->GetChar()->GetClan() == atoi(nOptions[2].c_str()))
+            snprintf(tShortSQL, 1024, "UPDATE clanwars SET cw_statement_enemy = \"%s\" WHERE cw_id = %d AND cw_enemyclan = %d", nOptions[0].c_str(), atoi(nOptions[1].c_str()), atoi(nOptions[2].c_str()));
+        break;
+    case 555:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 556:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 561:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 577:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 578:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 579:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 580:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 581:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 585:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 590:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 591:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    case 600: // Just ok, skip it
+        tSuccess = true;
+        break;
+    case 601: // Just ok, skip it
+        tSuccess = true;
+        break;
+    case 630:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Nothing to do; Function not written yet for QueryID %d", Console->ColorText(YELLOW,BLACK,"Notice"), nDBID);
+        break;
+    default:
+        Console->Print("%s [Pterminal::HandleUpdateDB]  Unknown QueryID %d", Console->ColorText(RED,BLACK,"Warning"), nDBID);
+        return false;
+    }
+
+// -------
+    if(tLongSQL.str().length() > 0)
+    {
+        if(MySQL->GameQuery(tLongSQL.str().c_str()))
+        {
+            Console->Print("Cannot update DB. query was: %s", tLongSQL.str().c_str());
+            MySQL->ShowGameSQLError();
+            tSuccess = false;
+        }
+        else
+            tSuccess = true;
+    }
+    else if(strlen(tShortSQL) > 0)
+    {
+        if(MySQL->GameQuery(tShortSQL))
+        {
+            Console->Print("Cannot update DB. query was: %s", tShortSQL);
+            MySQL->ShowGameSQLError();
+            tSuccess = false;
+        }
+        else
+            tSuccess = true;
+    }
+
+    // Notice client about UpdateDB result
+    char tCmd[100];
+    memset(tCmd, '\0', 100);
+    strncpy(tCmd, nCommandName->c_str(), 100);
+
+    PMessage* tmpMsg = MsgBuilder->BuildTryAccessAnswerMsg(nClient, tCmd, tSuccess);
+    nClient->SendUDPMessage(tmpMsg);
+    return true;
+}
index 33276b4..48d30b4 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// PVhcCoordinates\r
-void PVhcCoordinates::SetInterpolate( const PVhcCoordinates& Pos1, const PVhcCoordinates& Pos2, float nCoef )\r
-{\r
-  if (( nCoef < 0 ) || ( nCoef > 1 ) )\r
-  {\r
-    Console->Print( RED, BLACK, "[Error] PVhcCoordinates::Interpolate : Invalid nCoef value: %f", nCoef );\r
-    nCoef = 0;\r
-  }\r
-  float rCoef = 1 - nCoef;\r
-\r
-  mY = ( uint16_t )( rCoef * Pos1.mY + nCoef * Pos2.mY );\r
-  mZ = ( uint16_t )( rCoef * Pos1.mZ + nCoef * Pos2.mZ );\r
-  mX = ( uint16_t )( rCoef * Pos1.mX + nCoef * Pos2.mX );\r
-  mUD = ( uint8_t )( rCoef * Pos1.mUD + nCoef * Pos2.mUD );\r
-  mLR = ( uint16_t )( rCoef * Pos1.mLR + nCoef * Pos2.mLR );\r
-  mRoll = ( uint16_t )( rCoef * Pos1.mRoll + nCoef * Pos2.mRoll );\r
-}\r
-\r
-void PVhcCoordinates::SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD, uint16_t nLR, uint16_t nRoll, uint8_t nAct, uint16_t nUnknown, uint8_t nFF )\r
-{\r
-  mY = nY;\r
-  mZ = nZ;\r
-  mX = nX;\r
-  mUD = nUD;\r
-  mLR = nLR;\r
-  mRoll = nRoll;\r
-  mAct = nAct;\r
-  mUnknown = nUnknown;\r
-  mFF = nFF;\r
-}\r
-\r
-// PVehicleInformation\r
-//Tmp\r
-const uint8_t VhcTypes[] = {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,\r
-                         11, 12, 13, 50, 60, 62, 64, 65, 70\r
-                      }; // (adv.) assault gliders discarded because not ok\r
-#define VHC_DISABLE_NOVULARI\r
-#ifndef VHC_DISABLE_NOVULARI\r
-const uint8_t VhcTypesNum = 19;\r
-#else\r
-const uint8_t VhcTypesNum = 18;\r
-#endif\r
-\r
-bool PVehicleInformation::Load( uint32_t nVehicleId )\r
-{\r
-  uint8_t i;\r
-  uint8_t nVId = nVehicleId % 100; //Tmp\r
-  for ( i = 0; ( i < VhcTypesNum ) && ( VhcTypes[i] < nVId ); i++ ) ; //Tmp\r
-  if (( i < VhcTypesNum ) && ( VhcTypes[i] == nVId ) ) //Tmp\r
-  {\r
-    mVehicleId = nVehicleId;\r
-    mOwnerCharId = nVehicleId / 100; // tmp\r
-    mHealth = 200; // Tmp\r
-    mVehicleType = nVId; // tmp\r
-    mStatus = 0;\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-bool PVehicleInformation::Save()\r
-{\r
-  // Shall we Destroy() when mStatus == 2, or keep destroyed vhc in DB ?\r
-  return true;\r
-}\r
-\r
-bool PVehicleInformation::Destroy()\r
-{\r
-  if ( mStatus == 2 )\r
-  {\r
-    // Delete from DB\r
-    mVehicleId = 0;\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-bool PVehicleInformation::SetStatus( uint8_t nStatus )\r
-{\r
-  if (( mStatus != 2 ) && ( nStatus <= 2 ) )\r
-  {\r
-    mStatus = nStatus;\r
-    return true;\r
-  }\r
-  else\r
-    return false;\r
-}\r
-\r
-// PSpawnedVehicule\r
-const uint8_t PSpawnedVehicle::mSeatsFlags[] = { 1, 2, 4, 8, 16, 32, 64, 128 };\r
-\r
-PSpawnedVehicle::PSpawnedVehicle( uint32_t nLocalId, PVehicleInformation const* nVhcInfo, uint32_t nLocation, PVhcCoordinates const* nVhcPos )\r
-{\r
-  mLocalId = nLocalId;\r
-  mInfo = *nVhcInfo;\r
-  mLocation = nLocation;\r
-  mCoords = *nVhcPos;\r
-  for ( int i = 0; i < 8; ++i )\r
-    mSeatUserId[i] = 0;\r
-\r
-  mVhcDef = GameDefs->Vhcs()->GetDef( mInfo.mVehicleType );\r
-  if ( ! mVhcDef )\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Invalid vhc type %d for vhc id %d (local %d) owner char id %d", mInfo.mVehicleType, mInfo.mVehicleId, mLocalId, mInfo.mOwnerCharId );\r
-    Console->Print( RED, BLACK, "[NOTICE] Setting vhc type to %d for vhc id %d (local %d) owner char id %d", VhcTypes[0], mInfo.mVehicleId, mLocalId, mInfo.mOwnerCharId );\r
-    mInfo.mVehicleType = VhcTypes[0];\r
-    mVhcDef = GameDefs->Vhcs()->GetDef( mInfo.mVehicleType );\r
-  }\r
-\r
-  mNbFreeSeats = GetNumSeats();\r
-  if ( mNbFreeSeats > 8 )\r
-  {\r
-    Console->Print( RED, BLACK, "[ERROR] Vhc type %d has more than 8 seats (%d)", mInfo.mVehicleType, mNbFreeSeats );\r
-    mNbFreeSeats = 8;\r
-  }\r
-  for ( int i = 0; i < mNbFreeSeats; ++i )\r
-    mFreeSeatsFlags |= mSeatsFlags[i];\r
-\r
-  //Temp\r
-  for ( int i = 0; i < 4; ++i )\r
-  {\r
-    minmax[i][0] = 0xffff;\r
-    minmax[i][1] = 0;\r
-  }\r
-}\r
-\r
-void PSpawnedVehicle::SetLocation( uint32_t nLocation )\r
-{\r
-  mLocation = nLocation;\r
-}\r
-\r
-void PSpawnedVehicle::SetPosition( PVhcCoordinates const* nVhcPos )\r
-{\r
-  mCoords = *nVhcPos;\r
-  // Temp\r
-  if(gDevDebug)\r
-  {\r
-    if ( mCoords.mUD < minmax[0][0] ) minmax[0][0] = mCoords.mUD;\r
-    if ( mCoords.mUD > minmax[0][1] ) minmax[0][1] = mCoords.mUD;\r
-    if ( mCoords.mLR < minmax[1][0] ) minmax[1][0] = mCoords.mLR;\r
-    if ( mCoords.mLR > minmax[1][1] ) minmax[1][1] = mCoords.mLR;\r
-    if ( mCoords.mRoll < minmax[2][0] ) minmax[2][0] = mCoords.mRoll;\r
-    if ( mCoords.mRoll > minmax[2][1] ) minmax[2][1] = mCoords.mRoll;\r
-    Console->Print( "%s Min/Max: UD:%d/%d(%d) LR:%d/%d(%d) Roll:%d/%d(%d)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), minmax[0][0], minmax[0][1], mCoords.mUD, minmax[1][0], minmax[1][1], mCoords.mLR, minmax[2][0], minmax[2][1], mCoords.mRoll );\r
-  }\r
-}\r
-\r
-int PSpawnedVehicle::GetNumSeats() const\r
-{\r
-  return mVhcDef->GetNumSeats();\r
-}\r
-\r
-bool PSpawnedVehicle::SetSeatUser( uint8_t nSeatId, uint32_t nCharId )\r
-{\r
-  if ( nSeatId < mVhcDef->GetNumSeats() )\r
-  {\r
-    if ( ! mSeatUserId[nSeatId] )\r
-    {\r
-      mSeatUserId[nSeatId] = nCharId;\r
-      mFreeSeatsFlags &= ~mSeatsFlags[nSeatId];\r
-      --mNbFreeSeats;\r
-      return true;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-bool PSpawnedVehicle::UnsetSeatUser( uint8_t nSeatId, uint32_t nCharId )\r
-{\r
-  if ( nSeatId < mVhcDef->GetNumSeats() )\r
-  {\r
-    if ( mSeatUserId[nSeatId] == nCharId )\r
-    {\r
-      mSeatUserId[nSeatId] = 0;\r
-      mFreeSeatsFlags |= mSeatsFlags[nSeatId];\r
-      ++mNbFreeSeats;\r
-      return true;\r
-    }\r
-  }\r
-  return false;\r
-}\r
-\r
-bool PSpawnedVehicle::IsCharInside( uint32_t nCharId ) const\r
-{\r
-  for ( int i = 0; i < mVhcDef->GetNumSeats(); ++i )\r
-  {\r
-    if ( mSeatUserId[i] == nCharId )\r
-      return true;\r
-  }\r
-  return false;\r
-}\r
-\r
-uint8_t PSpawnedVehicle::GetFirstFreeSeat() const\r
-{\r
-  for ( int i = 0; i < mVhcDef->GetNumSeats(); ++i )\r
-  {\r
-    if ( ! mSeatUserId[i] )\r
-      return i;\r
-  }\r
-\r
-  return 255;\r
-}\r
-/*uint8_t PSpawnedVehicle::GetFreeSeats() const\r
-{\r
-  uint8_t bitField = 0;\r
-\r
-  for(int i = mVhcDef->GetNumSeats() - 1; i >= 0 ; --i)\r
-  {\r
-    bitField <<= 1;\r
-    if ( ! mSeatUserId[i] )\r
-      bitField |= 1;\r
-  }\r
-\r
-  return bitField;\r
-}*/\r
-\r
-// PVehicles\r
-PVehicles::PVehicles()\r
-{\r
-\r
-}\r
-\r
-PVehicles::~PVehicles()\r
-{\r
-\r
-}\r
-\r
-bool PVehicles::RegisterSpawnedVehicle( PSpawnedVehicle* nSpawnedVehicle )\r
-{\r
-  std::pair<PSpawnedVhcMap::iterator, bool> Result = mSpawnedVehicles.insert( std::make_pair( nSpawnedVehicle->GetVehicleId(), nSpawnedVehicle ) );\r
-  return Result.second;\r
-}\r
-\r
-bool PVehicles::UnregisterSpawnedVehicle( uint32_t nVehicleId )\r
-{\r
-  PSpawnedVhcMap::iterator it = mSpawnedVehicles.find( nVehicleId );\r
-  if ( it != mSpawnedVehicles.end() )\r
-  {\r
-    mSpawnedVehicles.erase( it );\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-//uint32_t PVehicles::CreateVehicle(uint32_t nOwnerChar, uint8_t mVehicleType) {}\r
-//bool PVehicles::RegisterVehicleOwner(uint32_t nVehicleId, uint32_t nOwnerChar) {}\r
-//bool PVehicles::DestroyVehicle(uint32_t nVehicleId) {}\r
-\r
-bool PVehicles::IsValidVehicle( uint32_t nVehicleId, bool nCheckOwner, uint32_t nOwnerId ) const\r
-{\r
-  // Look in DB\r
-  // tmp\r
-  uint32_t tVehicleId = nVehicleId;\r
-  bool tCheckOwner = nCheckOwner;\r
-  uint32_t tOwnerId = nOwnerId;\r
-  return true; // tmp\r
-}\r
-\r
-PSpawnedVehicle* PVehicles::GetSpawnedVehicle( uint32_t nVehicleId ) const\r
-{\r
-  PSpawnedVhcMap::const_iterator it = mSpawnedVehicles.find( nVehicleId );\r
-  if ( it != mSpawnedVehicles.end() )\r
-  {\r
-    return ( it->second );\r
-  }\r
-  else\r
-  {\r
-    return NULL;\r
-  }\r
-}\r
-\r
-bool PVehicles::GetVehicleInfo( uint32_t nVehicleId, PVehicleInformation* nInfo ) const\r
-{\r
-  PSpawnedVehicle* tVhc = GetSpawnedVehicle( nVehicleId );\r
-  if ( tVhc )\r
-  {\r
-    *nInfo = tVhc->GetInformation();\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return nInfo->Load( nVehicleId );\r
-  }\r
-}\r
-\r
-PVhcInfoList* PVehicles::GetCharVehicles( uint32_t nCharId, uint16_t nMaxCount, uint16_t nStartIndex )\r
-{\r
-  PVhcInfoList* Entries = new PVhcInfoList();\r
-  PVehicleInformation* InfoEntry;\r
-  // Tmp implementation\r
-  uint16_t LimitIndex = nStartIndex + nMaxCount;\r
-  if ( !nMaxCount || ( VhcTypesNum < LimitIndex ) )\r
-  {\r
-    LimitIndex = VhcTypesNum;\r
-  }\r
-\r
-  for ( uint16_t i = nStartIndex; ( i < LimitIndex ) ; ++i )\r
-  {\r
-    InfoEntry = new PVehicleInformation();\r
-    if ( GetVehicleInfo( nCharId * 100 + VhcTypes[i], InfoEntry ) )\r
-    {\r
-      Entries->push( InfoEntry );\r
-    }\r
-    else\r
-    {\r
-      delete InfoEntry;\r
-    }\r
-  }\r
-\r
-  return Entries;\r
-}\r
-\r
-PSpawnedVehicle* PVehicles::SpawnVehicle( uint32_t nVehicleId, uint32_t nLocation, PVhcCoordinates const* nVhcPos )\r
-{\r
-  PSpawnedVehicle* newVhc = NULL;\r
-  PWorld* cWorld;\r
-  PVehicleInformation nVhcInfo;\r
-\r
-  if (( nLocation != PWorlds::mNcSubwayWorldId ) && IsValidVehicle( nVehicleId ) && !IsSpawned( nVehicleId ) )\r
-  {\r
-    cWorld = Worlds->LeaseWorld( nLocation );\r
-\r
-    if ( cWorld && GetVehicleInfo( nVehicleId, &nVhcInfo ) )\r
-    {\r
-      newVhc = cWorld->GetSpawnedVehicles()->SpawnVehicle( &nVhcInfo, nVhcPos );\r
-      if ( newVhc )\r
-      {\r
-        if ( !RegisterSpawnedVehicle( newVhc ) )\r
-        {\r
-          Console->Print( RED, BLACK, "[Error] PVehicles::SpawnVehicle : Could not register spawned vhc" );\r
-        }\r
-        if( gDevDebug )\r
-          Console->Print( "%d Spawned vhc %d (local 0x%04x) type %d (requested: %d)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), newVhc->GetVehicleId(), newVhc->GetLocalId(), newVhc->GetInformation().GetVehicleType(), nVhcInfo.GetVehicleType() );\r
-      }\r
-      else\r
-        Console->Print( RED, BLACK, "[Error] PVehicles::SpawnVehicle : Could not create vhc" );\r
-    }\r
-\r
-    Worlds->ReleaseWorld( nLocation );\r
-  }\r
-\r
-  return newVhc;\r
-}\r
-\r
-bool PVehicles::UnspawnVehicle( uint32_t nVehicleId )\r
-{\r
-  PWorld* cWorld;\r
-  bool Result = false;\r
-\r
-  PSpawnedVhcMap::iterator it = mSpawnedVehicles.find( nVehicleId );\r
-  if ( it != mSpawnedVehicles.end() )\r
-  {\r
-    cWorld = Worlds->LeaseWorld( it->second->GetLocation() );\r
-\r
-    if ( cWorld )\r
-    {\r
-      if ( !it->second->Save() )\r
-      {\r
-        Console->Print( RED, BLACK, "[Error] PVehicles::UnspawnVehicle : Could not save vhc %d", nVehicleId );\r
-      }\r
-\r
-      Result = cWorld->GetSpawnedVehicles()->UnspawnVehicle( it->second->GetLocalId() );\r
-      if ( Result )\r
-      {\r
-        if ( !UnregisterSpawnedVehicle( nVehicleId ) )\r
-        {\r
-          Console->Print( RED, BLACK, "[Error] PVehicles::UnspawnVehicle : Could not unregister vhc %d", nVehicleId );\r
-        }\r
-      }\r
-    }\r
-\r
-    Worlds->ReleaseWorld( it->second->GetLocation() );\r
-  }\r
-\r
-  return Result;\r
-}\r
-\r
-//PSpawnedVehicles\r
-PSpawnedVehicles::PSpawnedVehicles()\r
-{\r
-  mNextFreeHint = 0;\r
-  mLocation = 0;\r
-}\r
-\r
-PSpawnedVehicles::~PSpawnedVehicles()\r
-{\r
-\r
-}\r
-\r
-PSpawnedVehicle* PSpawnedVehicles::SpawnVehicle( PVehicleInformation const* nVhcInfo, PVhcCoordinates const* nVhcPos )\r
-{\r
-  PSpawnedVehicle* newVhc = NULL;\r
-  uint32_t nSize;\r
-\r
-  if ( nVhcInfo->GetStatus() == 0 ) // only if in garage\r
-  {\r
-    nSize = mSpawnedVehicles.size();\r
-    while (( mNextFreeHint < nSize ) && mSpawnedVehicles[mNextFreeHint] )\r
-    {\r
-      ++mNextFreeHint;\r
-    }\r
-    if ( mNextFreeHint > nSize )\r
-    {\r
-      mNextFreeHint = nSize;\r
-    }\r
-    if ( mNextFreeHint == nSize )\r
-    {\r
-      mSpawnedVehicles.push_back( static_cast<PSpawnedVehicle *>(NULL) );\r
-    }\r
-\r
-    if ( mNextFreeHint < mMaxLocalVhc )\r
-    {\r
-      newVhc = new PSpawnedVehicle( mVhcBaseLocalId - mNextFreeHint, nVhcInfo, mLocation, nVhcPos );\r
-      mSpawnedVehicles[mNextFreeHint++] = newVhc;\r
-      newVhc->SetStatus( 1 );\r
-    }\r
-  }\r
-\r
-  return newVhc;\r
-}\r
-\r
-PSpawnedVehicle* PSpawnedVehicles::GetVehicle( uint32_t nLocalId )\r
-{\r
-  if (( nLocalId <= mVhcBaseLocalId ) && ( nLocalId > ( mVhcBaseLocalId - mSpawnedVehicles.size() ) ) )\r
-  {\r
-    return mSpawnedVehicles[mVhcBaseLocalId - nLocalId];\r
-  }\r
-  else\r
-  {\r
-    return NULL;\r
-  }\r
-}\r
-\r
-PSpawnedVehicle* PSpawnedVehicles::GetVehicleByGlobalId( uint32_t nVehicleId ) const\r
-{\r
-  for ( PSpawnedVhcVector::const_iterator it = mSpawnedVehicles.begin(); it != mSpawnedVehicles.end(); it++ )\r
-  {\r
-    if (( *it )->GetVehicleId() == nVehicleId )\r
-    {\r
-      return ( *it );\r
-    }\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-bool PSpawnedVehicles::UnspawnVehicle( uint32_t nLocalId )\r
-{\r
-  uint16_t Index;\r
-  PSpawnedVehicle* tVhc;\r
-\r
-  if (( nLocalId <= mVhcBaseLocalId ) && ( nLocalId > ( mVhcBaseLocalId - mSpawnedVehicles.size() ) ) )\r
-  {\r
-    Index = mVhcBaseLocalId - nLocalId;\r
-    tVhc = mSpawnedVehicles[Index];\r
-    if ( tVhc )\r
-    {\r
-      if ( tVhc->GetInformation().GetStatus() != 2 )\r
-      {\r
-        tVhc->SetStatus( 0 );\r
-      }\r
-      delete tVhc;\r
-      mSpawnedVehicles[Index] = NULL;\r
-      if ( mNextFreeHint > Index )\r
-      {\r
-        mNextFreeHint = Index;\r
-      }\r
-      return true;\r
-    }\r
-  }\r
-\r
-  return false;\r
-}\r
-\r
-PSpawnedVhcList* PSpawnedVehicles::GetSpawnedVehicles() const\r
-{\r
-  PSpawnedVhcList* Entries = new PSpawnedVhcList();\r
-\r
-  for ( PSpawnedVhcVector::const_iterator i = mSpawnedVehicles.begin(); i !=  mSpawnedVehicles.end(); ++i )\r
-  {\r
-    if ( *i )\r
-    {\r
-      Entries->push( *i );\r
-    }\r
-  }\r
-\r
-  return Entries;\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// PVhcCoordinates
+void PVhcCoordinates::SetInterpolate( const PVhcCoordinates& Pos1, const PVhcCoordinates& Pos2, float nCoef )
+{
+  if (( nCoef < 0 ) || ( nCoef > 1 ) )
+  {
+    Console->Print( RED, BLACK, "[Error] PVhcCoordinates::Interpolate : Invalid nCoef value: %f", nCoef );
+    nCoef = 0;
+  }
+  float rCoef = 1 - nCoef;
+
+  mY = ( uint16_t )( rCoef * Pos1.mY + nCoef * Pos2.mY );
+  mZ = ( uint16_t )( rCoef * Pos1.mZ + nCoef * Pos2.mZ );
+  mX = ( uint16_t )( rCoef * Pos1.mX + nCoef * Pos2.mX );
+  mUD = ( uint8_t )( rCoef * Pos1.mUD + nCoef * Pos2.mUD );
+  mLR = ( uint16_t )( rCoef * Pos1.mLR + nCoef * Pos2.mLR );
+  mRoll = ( uint16_t )( rCoef * Pos1.mRoll + nCoef * Pos2.mRoll );
+}
+
+void PVhcCoordinates::SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD, uint16_t nLR, uint16_t nRoll, uint8_t nAct, uint16_t nUnknown, uint8_t nFF )
+{
+  mY = nY;
+  mZ = nZ;
+  mX = nX;
+  mUD = nUD;
+  mLR = nLR;
+  mRoll = nRoll;
+  mAct = nAct;
+  mUnknown = nUnknown;
+  mFF = nFF;
+}
+
+// PVehicleInformation
+//Tmp
+const uint8_t VhcTypes[] = {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
+                         11, 12, 13, 50, 60, 62, 64, 65, 70
+                      }; // (adv.) assault gliders discarded because not ok
+#define VHC_DISABLE_NOVULARI
+#ifndef VHC_DISABLE_NOVULARI
+const uint8_t VhcTypesNum = 19;
+#else
+const uint8_t VhcTypesNum = 18;
+#endif
+
+bool PVehicleInformation::Load( uint32_t nVehicleId )
+{
+  uint8_t i;
+  uint8_t nVId = nVehicleId % 100; //Tmp
+  for ( i = 0; ( i < VhcTypesNum ) && ( VhcTypes[i] < nVId ); i++ ) ; //Tmp
+  if (( i < VhcTypesNum ) && ( VhcTypes[i] == nVId ) ) //Tmp
+  {
+    mVehicleId = nVehicleId;
+    mOwnerCharId = nVehicleId / 100; // tmp
+    mHealth = 200; // Tmp
+    mVehicleType = nVId; // tmp
+    mStatus = 0;
+    return true;
+  }
+  else
+    return false;
+}
+
+bool PVehicleInformation::Save()
+{
+  // Shall we Destroy() when mStatus == 2, or keep destroyed vhc in DB ?
+  return true;
+}
+
+bool PVehicleInformation::Destroy()
+{
+  if ( mStatus == 2 )
+  {
+    // Delete from DB
+    mVehicleId = 0;
+    return true;
+  }
+  else
+    return false;
+}
+
+bool PVehicleInformation::SetStatus( uint8_t nStatus )
+{
+  if (( mStatus != 2 ) && ( nStatus <= 2 ) )
+  {
+    mStatus = nStatus;
+    return true;
+  }
+  else
+    return false;
+}
+
+// PSpawnedVehicule
+const uint8_t PSpawnedVehicle::mSeatsFlags[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+PSpawnedVehicle::PSpawnedVehicle( uint32_t nLocalId, PVehicleInformation const* nVhcInfo, uint32_t nLocation, PVhcCoordinates const* nVhcPos )
+{
+  mLocalId = nLocalId;
+  mInfo = *nVhcInfo;
+  mLocation = nLocation;
+  mCoords = *nVhcPos;
+  for ( int i = 0; i < 8; ++i )
+    mSeatUserId[i] = 0;
+
+  mVhcDef = GameDefs->Vhcs()->GetDef( mInfo.mVehicleType );
+  if ( ! mVhcDef )
+  {
+    Console->Print( RED, BLACK, "[ERROR] Invalid vhc type %d for vhc id %d (local %d) owner char id %d", mInfo.mVehicleType, mInfo.mVehicleId, mLocalId, mInfo.mOwnerCharId );
+    Console->Print( RED, BLACK, "[NOTICE] Setting vhc type to %d for vhc id %d (local %d) owner char id %d", VhcTypes[0], mInfo.mVehicleId, mLocalId, mInfo.mOwnerCharId );
+    mInfo.mVehicleType = VhcTypes[0];
+    mVhcDef = GameDefs->Vhcs()->GetDef( mInfo.mVehicleType );
+  }
+
+  mNbFreeSeats = GetNumSeats();
+  if ( mNbFreeSeats > 8 )
+  {
+    Console->Print( RED, BLACK, "[ERROR] Vhc type %d has more than 8 seats (%d)", mInfo.mVehicleType, mNbFreeSeats );
+    mNbFreeSeats = 8;
+  }
+  for ( int i = 0; i < mNbFreeSeats; ++i )
+    mFreeSeatsFlags |= mSeatsFlags[i];
+
+  //Temp
+  for ( int i = 0; i < 4; ++i )
+  {
+    minmax[i][0] = 0xffff;
+    minmax[i][1] = 0;
+  }
+}
+
+void PSpawnedVehicle::SetLocation( uint32_t nLocation )
+{
+  mLocation = nLocation;
+}
+
+void PSpawnedVehicle::SetPosition( PVhcCoordinates const* nVhcPos )
+{
+  mCoords = *nVhcPos;
+  // Temp
+  if(gDevDebug)
+  {
+    if ( mCoords.mUD < minmax[0][0] ) minmax[0][0] = mCoords.mUD;
+    if ( mCoords.mUD > minmax[0][1] ) minmax[0][1] = mCoords.mUD;
+    if ( mCoords.mLR < minmax[1][0] ) minmax[1][0] = mCoords.mLR;
+    if ( mCoords.mLR > minmax[1][1] ) minmax[1][1] = mCoords.mLR;
+    if ( mCoords.mRoll < minmax[2][0] ) minmax[2][0] = mCoords.mRoll;
+    if ( mCoords.mRoll > minmax[2][1] ) minmax[2][1] = mCoords.mRoll;
+    Console->Print( "%s Min/Max: UD:%d/%d(%d) LR:%d/%d(%d) Roll:%d/%d(%d)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), minmax[0][0], minmax[0][1], mCoords.mUD, minmax[1][0], minmax[1][1], mCoords.mLR, minmax[2][0], minmax[2][1], mCoords.mRoll );
+  }
+}
+
+int PSpawnedVehicle::GetNumSeats() const
+{
+  return mVhcDef->GetNumSeats();
+}
+
+bool PSpawnedVehicle::SetSeatUser( uint8_t nSeatId, uint32_t nCharId )
+{
+  if ( nSeatId < mVhcDef->GetNumSeats() )
+  {
+    if ( ! mSeatUserId[nSeatId] )
+    {
+      mSeatUserId[nSeatId] = nCharId;
+      mFreeSeatsFlags &= ~mSeatsFlags[nSeatId];
+      --mNbFreeSeats;
+      return true;
+    }
+  }
+  return false;
+}
+
+bool PSpawnedVehicle::UnsetSeatUser( uint8_t nSeatId, uint32_t nCharId )
+{
+  if ( nSeatId < mVhcDef->GetNumSeats() )
+  {
+    if ( mSeatUserId[nSeatId] == nCharId )
+    {
+      mSeatUserId[nSeatId] = 0;
+      mFreeSeatsFlags |= mSeatsFlags[nSeatId];
+      ++mNbFreeSeats;
+      return true;
+    }
+  }
+  return false;
+}
+
+bool PSpawnedVehicle::IsCharInside( uint32_t nCharId ) const
+{
+  for ( int i = 0; i < mVhcDef->GetNumSeats(); ++i )
+  {
+    if ( mSeatUserId[i] == nCharId )
+      return true;
+  }
+  return false;
+}
+
+uint8_t PSpawnedVehicle::GetFirstFreeSeat() const
+{
+  for ( int i = 0; i < mVhcDef->GetNumSeats(); ++i )
+  {
+    if ( ! mSeatUserId[i] )
+      return i;
+  }
+
+  return 255;
+}
+/*uint8_t PSpawnedVehicle::GetFreeSeats() const
+{
+  uint8_t bitField = 0;
+
+  for(int i = mVhcDef->GetNumSeats() - 1; i >= 0 ; --i)
+  {
+    bitField <<= 1;
+    if ( ! mSeatUserId[i] )
+      bitField |= 1;
+  }
+
+  return bitField;
+}*/
+
+// PVehicles
+PVehicles::PVehicles()
+{
+
+}
+
+PVehicles::~PVehicles()
+{
+
+}
+
+bool PVehicles::RegisterSpawnedVehicle( PSpawnedVehicle* nSpawnedVehicle )
+{
+  std::pair<PSpawnedVhcMap::iterator, bool> Result = mSpawnedVehicles.insert( std::make_pair( nSpawnedVehicle->GetVehicleId(), nSpawnedVehicle ) );
+  return Result.second;
+}
+
+bool PVehicles::UnregisterSpawnedVehicle( uint32_t nVehicleId )
+{
+  PSpawnedVhcMap::iterator it = mSpawnedVehicles.find( nVehicleId );
+  if ( it != mSpawnedVehicles.end() )
+  {
+    mSpawnedVehicles.erase( it );
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+//uint32_t PVehicles::CreateVehicle(uint32_t nOwnerChar, uint8_t mVehicleType) {}
+//bool PVehicles::RegisterVehicleOwner(uint32_t nVehicleId, uint32_t nOwnerChar) {}
+//bool PVehicles::DestroyVehicle(uint32_t nVehicleId) {}
+
+bool PVehicles::IsValidVehicle( uint32_t nVehicleId, bool nCheckOwner, uint32_t nOwnerId ) const
+{
+  // Look in DB
+  // tmp
+  uint32_t tVehicleId = nVehicleId;
+  bool tCheckOwner = nCheckOwner;
+  uint32_t tOwnerId = nOwnerId;
+  return true; // tmp
+}
+
+PSpawnedVehicle* PVehicles::GetSpawnedVehicle( uint32_t nVehicleId ) const
+{
+  PSpawnedVhcMap::const_iterator it = mSpawnedVehicles.find( nVehicleId );
+  if ( it != mSpawnedVehicles.end() )
+  {
+    return ( it->second );
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+bool PVehicles::GetVehicleInfo( uint32_t nVehicleId, PVehicleInformation* nInfo ) const
+{
+  PSpawnedVehicle* tVhc = GetSpawnedVehicle( nVehicleId );
+  if ( tVhc )
+  {
+    *nInfo = tVhc->GetInformation();
+    return true;
+  }
+  else
+  {
+    return nInfo->Load( nVehicleId );
+  }
+}
+
+PVhcInfoList* PVehicles::GetCharVehicles( uint32_t nCharId, uint16_t nMaxCount, uint16_t nStartIndex )
+{
+  PVhcInfoList* Entries = new PVhcInfoList();
+  PVehicleInformation* InfoEntry;
+  // Tmp implementation
+  uint16_t LimitIndex = nStartIndex + nMaxCount;
+  if ( !nMaxCount || ( VhcTypesNum < LimitIndex ) )
+  {
+    LimitIndex = VhcTypesNum;
+  }
+
+  for ( uint16_t i = nStartIndex; ( i < LimitIndex ) ; ++i )
+  {
+    InfoEntry = new PVehicleInformation();
+    if ( GetVehicleInfo( nCharId * 100 + VhcTypes[i], InfoEntry ) )
+    {
+      Entries->push( InfoEntry );
+    }
+    else
+    {
+      delete InfoEntry;
+    }
+  }
+
+  return Entries;
+}
+
+PSpawnedVehicle* PVehicles::SpawnVehicle( uint32_t nVehicleId, uint32_t nLocation, PVhcCoordinates const* nVhcPos )
+{
+  PSpawnedVehicle* newVhc = NULL;
+  PWorld* cWorld;
+  PVehicleInformation nVhcInfo;
+
+  if (( nLocation != PWorlds::mNcSubwayWorldId ) && IsValidVehicle( nVehicleId ) && !IsSpawned( nVehicleId ) )
+  {
+    cWorld = Worlds->LeaseWorld( nLocation );
+
+    if ( cWorld && GetVehicleInfo( nVehicleId, &nVhcInfo ) )
+    {
+      newVhc = cWorld->GetSpawnedVehicles()->SpawnVehicle( &nVhcInfo, nVhcPos );
+      if ( newVhc )
+      {
+        if ( !RegisterSpawnedVehicle( newVhc ) )
+        {
+          Console->Print( RED, BLACK, "[Error] PVehicles::SpawnVehicle : Could not register spawned vhc" );
+        }
+        if( gDevDebug )
+          Console->Print( "%d Spawned vhc %d (local 0x%04x) type %d (requested: %d)", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), newVhc->GetVehicleId(), newVhc->GetLocalId(), newVhc->GetInformation().GetVehicleType(), nVhcInfo.GetVehicleType() );
+      }
+      else
+        Console->Print( RED, BLACK, "[Error] PVehicles::SpawnVehicle : Could not create vhc" );
+    }
+
+    Worlds->ReleaseWorld( nLocation );
+  }
+
+  return newVhc;
+}
+
+bool PVehicles::UnspawnVehicle( uint32_t nVehicleId )
+{
+  PWorld* cWorld;
+  bool Result = false;
+
+  PSpawnedVhcMap::iterator it = mSpawnedVehicles.find( nVehicleId );
+  if ( it != mSpawnedVehicles.end() )
+  {
+    cWorld = Worlds->LeaseWorld( it->second->GetLocation() );
+
+    if ( cWorld )
+    {
+      if ( !it->second->Save() )
+      {
+        Console->Print( RED, BLACK, "[Error] PVehicles::UnspawnVehicle : Could not save vhc %d", nVehicleId );
+      }
+
+      Result = cWorld->GetSpawnedVehicles()->UnspawnVehicle( it->second->GetLocalId() );
+      if ( Result )
+      {
+        if ( !UnregisterSpawnedVehicle( nVehicleId ) )
+        {
+          Console->Print( RED, BLACK, "[Error] PVehicles::UnspawnVehicle : Could not unregister vhc %d", nVehicleId );
+        }
+      }
+    }
+
+    Worlds->ReleaseWorld( it->second->GetLocation() );
+  }
+
+  return Result;
+}
+
+//PSpawnedVehicles
+PSpawnedVehicles::PSpawnedVehicles()
+{
+  mNextFreeHint = 0;
+  mLocation = 0;
+}
+
+PSpawnedVehicles::~PSpawnedVehicles()
+{
+
+}
+
+PSpawnedVehicle* PSpawnedVehicles::SpawnVehicle( PVehicleInformation const* nVhcInfo, PVhcCoordinates const* nVhcPos )
+{
+  PSpawnedVehicle* newVhc = NULL;
+  uint32_t nSize;
+
+  if ( nVhcInfo->GetStatus() == 0 ) // only if in garage
+  {
+    nSize = mSpawnedVehicles.size();
+    while (( mNextFreeHint < nSize ) && mSpawnedVehicles[mNextFreeHint] )
+    {
+      ++mNextFreeHint;
+    }
+    if ( mNextFreeHint > nSize )
+    {
+      mNextFreeHint = nSize;
+    }
+    if ( mNextFreeHint == nSize )
+    {
+      mSpawnedVehicles.push_back( static_cast<PSpawnedVehicle *>(NULL) );
+    }
+
+    if ( mNextFreeHint < mMaxLocalVhc )
+    {
+      newVhc = new PSpawnedVehicle( mVhcBaseLocalId - mNextFreeHint, nVhcInfo, mLocation, nVhcPos );
+      mSpawnedVehicles[mNextFreeHint++] = newVhc;
+      newVhc->SetStatus( 1 );
+    }
+  }
+
+  return newVhc;
+}
+
+PSpawnedVehicle* PSpawnedVehicles::GetVehicle( uint32_t nLocalId )
+{
+  if (( nLocalId <= mVhcBaseLocalId ) && ( nLocalId > ( mVhcBaseLocalId - mSpawnedVehicles.size() ) ) )
+  {
+    return mSpawnedVehicles[mVhcBaseLocalId - nLocalId];
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+PSpawnedVehicle* PSpawnedVehicles::GetVehicleByGlobalId( uint32_t nVehicleId ) const
+{
+  for ( PSpawnedVhcVector::const_iterator it = mSpawnedVehicles.begin(); it != mSpawnedVehicles.end(); it++ )
+  {
+    if (( *it )->GetVehicleId() == nVehicleId )
+    {
+      return ( *it );
+    }
+  }
+
+  return NULL;
+}
+
+bool PSpawnedVehicles::UnspawnVehicle( uint32_t nLocalId )
+{
+  uint16_t Index;
+  PSpawnedVehicle* tVhc;
+
+  if (( nLocalId <= mVhcBaseLocalId ) && ( nLocalId > ( mVhcBaseLocalId - mSpawnedVehicles.size() ) ) )
+  {
+    Index = mVhcBaseLocalId - nLocalId;
+    tVhc = mSpawnedVehicles[Index];
+    if ( tVhc )
+    {
+      if ( tVhc->GetInformation().GetStatus() != 2 )
+      {
+        tVhc->SetStatus( 0 );
+      }
+      delete tVhc;
+      mSpawnedVehicles[Index] = NULL;
+      if ( mNextFreeHint > Index )
+      {
+        mNextFreeHint = Index;
+      }
+      return true;
+    }
+  }
+
+  return false;
+}
+
+PSpawnedVhcList* PSpawnedVehicles::GetSpawnedVehicles() const
+{
+  PSpawnedVhcList* Entries = new PSpawnedVhcList();
+
+  for ( PSpawnedVhcVector::const_iterator i = mSpawnedVehicles.begin(); i !=  mSpawnedVehicles.end(); ++i )
+  {
+    if ( *i )
+    {
+      Entries->push( *i );
+    }
+  }
+
+  return Entries;
+}
index d7c407b..a1e901f 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-#include <queue>\r
-#include <vector>\r
-\r
-class PDefVhc;\r
-\r
-class PVhcCoordinates {\r
-    friend class PSpawnedVehicle;\r
-\r
-  private:\r
-    uint16_t mY;     // Y-Position in world\r
-    uint16_t mZ;     // Z-Position in world\r
-    uint16_t mX;     // X-Position in world\r
-    uint8_t mUD;     // Up - Mid - Down (d6 - 80 - 2a) // Pitch\r
-    uint16_t mLR;     // Yaw\r
-    uint16_t mRoll;\r
-    uint16_t mUnknown; // Usually 0x0001\r
-    uint8_t mFF; // Usually 0xff ...\r
-    uint8_t mAct;    // Last user action state\r
-    // mAct: bit field\r
-    //0x00 = not moving\r
-    //0x01 = Left\r
-    //0x02 = Right\r
-    //0x04 = Forward\r
-    //0x08 = Back\r
-    //0x20 = Pushing down\r
-    //0x40 = Pulling up\r
-\r
-  public:\r
-    inline PVhcCoordinates() { mX = mY = mZ = mAct = 0; mUD = 128; mLR = 34683; mRoll = 32403;}\r
-\r
-    void SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD, uint16_t nLR, uint16_t nRoll, uint8_t nAct = 0, uint16_t nUnknown = 1, uint8_t nFF = 0xff );\r
-    void SetInterpolate( const PVhcCoordinates& Pos1, const PVhcCoordinates& Pos2, float nCoef );\r
-    inline uint16_t GetX() const { return mX; }\r
-    inline uint16_t GetY() const { return mY; }\r
-    inline uint16_t GetZ() const { return mZ; }\r
-    inline uint8_t GetUD() const { return mUD; }\r
-    inline uint16_t GetLR() const { return mLR; }\r
-    inline uint16_t GetRoll() const { return mRoll; }\r
-    inline uint8_t GetAct() const { return mAct; }\r
-    inline uint8_t GetUnknown() const { return mUnknown; }\r
-    inline uint8_t GetFF() const { return mFF; }\r
-};\r
-\r
-class PVehicleInformation\r
-{\r
-    friend class PSpawnedVehicle;\r
-    friend class PVehicles;\r
-\r
-  private:\r
-    uint32_t mVehicleId;\r
-    uint32_t mOwnerCharId;\r
-    uint32_t mHealth; // or float ???\r
-    uint8_t mVehicleType;\r
-    uint8_t mStatus; //vhcStatus 0:parking, 1:in_service, 2:destroyed\r
-\r
-  public:\r
-    inline PVehicleInformation( uint32_t nVehicleId = 0, uint32_t nOwnerCharId = 0, uint32_t nHealth = 0, uint8_t nVehicleType = 0, uint8_t nStatus = 0 ) :\r
-        mVehicleId( nVehicleId ),\r
-        mOwnerCharId( nOwnerCharId ),\r
-        mHealth( nHealth ),\r
-        mVehicleType( nVehicleType ),\r
-        mStatus( nStatus )\r
-    { }\r
-\r
-    inline uint32_t GetVehicleId() const { return mVehicleId; }\r
-    inline uint32_t GetOwnerCharId() const { return mOwnerCharId; }\r
-    inline uint32_t GetHealth() const { return mHealth; } // or float ???\r
-    inline uint8_t GetVehicleType() const { return mVehicleType; }\r
-    inline uint8_t GetStatus() const { return mStatus; }\r
-    bool SetStatus( uint8_t nStatus );\r
-\r
-    bool Load( uint32_t nVehicleId );\r
-    bool Save();\r
-    bool Destroy();\r
-};\r
-\r
-class PSpawnedVehicle\r
-{\r
-  private:\r
-    static const uint8_t mSeatsFlags[];\r
-\r
-  private:\r
-    uint32_t mLocalId;\r
-    PVehicleInformation mInfo;\r
-    uint32_t mLocation;\r
-    PVhcCoordinates mCoords;\r
-    const PDefVhc* mVhcDef;\r
-\r
-    uint32_t mSeatUserId[8];\r
-    uint8_t mFreeSeatsFlags;\r
-    uint8_t mNbFreeSeats;\r
-\r
-    uint16_t minmax[4][2]; //Temp\r
-\r
-  public:\r
-    PSpawnedVehicle( uint32_t nLocalId, PVehicleInformation const* nVhcInfo, uint32_t nLocation, PVhcCoordinates const* nVhcPos );\r
-\r
-    inline uint32_t GetVehicleId() const { return mInfo.mVehicleId; }\r
-    inline uint32_t GetLocalId() const { return mLocalId; }\r
-    inline const PVhcCoordinates& GetPosition() const { return mCoords; }\r
-    inline const PVehicleInformation& GetInformation() const { return mInfo; }\r
-    inline bool SetStatus( uint8_t nStatus ) { return mInfo.SetStatus( nStatus ); }\r
-\r
-    void SetLocation( uint32_t nLocation );\r
-    inline uint32_t GetLocation() const { return mLocation; }\r
-    void SetPosition( PVhcCoordinates const* nVhcPos );\r
-\r
-    inline bool Save() { return mInfo.Save(); }\r
-\r
-    int GetNumSeats() const;\r
-    inline uint32_t GetSeatUser( uint8_t nSeatId ) const { return (( nSeatId < 8 ) ? mSeatUserId[nSeatId] : 0 ); }\r
-    bool SetSeatUser( uint8_t nSeatId, uint32_t nCharId );\r
-    bool UnsetSeatUser( uint8_t nSeatId, uint32_t nCharId );\r
-    bool IsCharInside( uint32_t nCharId ) const;\r
-    inline uint8_t GetFreeSeatsFlags() const { return mFreeSeatsFlags; }\r
-    inline uint8_t GetNbFreeSeats() const { return mNbFreeSeats; }\r
-    uint8_t GetFirstFreeSeat() const;\r
-\r
-    //SetHealth(const uint32_t nHealth);\r
-    //uint32_t DoDamage(const uint32_t nHealthDec);\r
-    //uint32_t DoRepair(const uint32_t nHealthInc);\r
-};\r
-\r
-typedef std::map<uint32_t, PSpawnedVehicle*> PSpawnedVhcMap;\r
-typedef std::queue<PVehicleInformation*> PVhcInfoList;\r
-class PVehicles\r
-{\r
-  private:\r
-    PSpawnedVhcMap mSpawnedVehicles;\r
-\r
-    bool RegisterSpawnedVehicle( PSpawnedVehicle*  nSpawnedVehicle );\r
-    bool UnregisterSpawnedVehicle( uint32_t nVehicleId );\r
-\r
-  public:\r
-    PVehicles();\r
-    ~PVehicles();\r
-\r
-    //uint32_t CreateVehicle(uint32_t nOwnerChar, uint8_t mVehicleType);\r
-    //bool RegisterVehicleOwner(uint32_t nVehiculeId, uint32_t nOwnerChar);\r
-    //bool DestroyVehicle(uint32_t nVehiculeId);\r
-    bool IsValidVehicle( uint32_t nVehicleId, bool nCheckOwner = false, uint32_t nOwnerId = 0 ) const;\r
-    inline bool IsSpawned( uint32_t nVehicleId ) const { return ( mSpawnedVehicles.find( nVehicleId ) != mSpawnedVehicles.end() ); }\r
-    PSpawnedVehicle* GetSpawnedVehicle( uint32_t nVehicleId ) const;\r
-    bool GetVehicleInfo( uint32_t nVehicleId, PVehicleInformation* nInfo ) const;\r
-    PSpawnedVehicle* SpawnVehicle( uint32_t nVehicleId, uint32_t nLocation, PVhcCoordinates const* nVhcPos ); // Refuses for subway zone atm\r
-    bool UnspawnVehicle( uint32_t nVehicleId );\r
-\r
-    PVhcInfoList* GetCharVehicles( uint32_t nCharId, uint16_t nMaxCount = 0, uint16_t nStartIndex = 0 );\r
-\r
-};\r
-\r
-typedef std::vector<PSpawnedVehicle*> PSpawnedVhcVector;\r
-typedef std::queue<PSpawnedVehicle*> PSpawnedVhcList;\r
-\r
-class PSpawnedVehicles\r
-{\r
-    friend class PWorld;\r
-\r
-  public:\r
-    static const uint32_t mVhcBaseLocalId = 0x03fd; //Vhc local Id are allocated downward from this value. Could br 0x3ff, but 0x3fe is used as "target" when shooting nowhere\r
-    static const uint16_t mMaxLocalVhc = 127;\r
-\r
-    inline static bool IsPotentialSpawnedVehicle( uint32_t nLocalId )\r
-    { return (( nLocalId <= mVhcBaseLocalId ) && (( mVhcBaseLocalId - nLocalId ) < mMaxLocalVhc ) ); }\r
-\r
-  private:\r
-    PSpawnedVhcVector mSpawnedVehicles;\r
-    uint16_t mNextFreeHint;\r
-    uint32_t mLocation;\r
-\r
-    inline void SetLocation( uint32_t nLocation ) { mLocation = nLocation; }\r
-\r
-  public:\r
-    PSpawnedVehicles();\r
-    ~PSpawnedVehicles();\r
-\r
-    inline bool IsSpawned( uint32_t nLocalId ) const { return (( nLocalId <= mVhcBaseLocalId ) && (( mVhcBaseLocalId - nLocalId ) < mSpawnedVehicles.size() ) && mSpawnedVehicles[mVhcBaseLocalId-nLocalId] ); }\r
-    PSpawnedVehicle* SpawnVehicle( PVehicleInformation const* nVhcInfo, PVhcCoordinates const* nVhcPos );\r
-    PSpawnedVehicle* GetVehicle( uint32_t nLocalId );\r
-    PSpawnedVehicle* GetVehicleByGlobalId( uint32_t nVehicleId ) const;\r
-    bool UnspawnVehicle( uint32_t nVehicleId );\r
-\r
-    PSpawnedVhcList* GetSpawnedVehicles() const;\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <queue>
+#include <vector>
+
+class PDefVhc;
+
+class PVhcCoordinates {
+    friend class PSpawnedVehicle;
+
+  private:
+    uint16_t mY;     // Y-Position in world
+    uint16_t mZ;     // Z-Position in world
+    uint16_t mX;     // X-Position in world
+    uint8_t mUD;     // Up - Mid - Down (d6 - 80 - 2a) // Pitch
+    uint16_t mLR;     // Yaw
+    uint16_t mRoll;
+    uint16_t mUnknown; // Usually 0x0001
+    uint8_t mFF; // Usually 0xff ...
+    uint8_t mAct;    // Last user action state
+    // mAct: bit field
+    //0x00 = not moving
+    //0x01 = Left
+    //0x02 = Right
+    //0x04 = Forward
+    //0x08 = Back
+    //0x20 = Pushing down
+    //0x40 = Pulling up
+
+  public:
+    inline PVhcCoordinates() { mX = mY = mZ = mAct = 0; mUD = 128; mLR = 34683; mRoll = 32403;}
+
+    void SetPosition( uint16_t nY, uint16_t nZ, uint16_t nX, uint8_t nUD, uint16_t nLR, uint16_t nRoll, uint8_t nAct = 0, uint16_t nUnknown = 1, uint8_t nFF = 0xff );
+    void SetInterpolate( const PVhcCoordinates& Pos1, const PVhcCoordinates& Pos2, float nCoef );
+    inline uint16_t GetX() const { return mX; }
+    inline uint16_t GetY() const { return mY; }
+    inline uint16_t GetZ() const { return mZ; }
+    inline uint8_t GetUD() const { return mUD; }
+    inline uint16_t GetLR() const { return mLR; }
+    inline uint16_t GetRoll() const { return mRoll; }
+    inline uint8_t GetAct() const { return mAct; }
+    inline uint8_t GetUnknown() const { return mUnknown; }
+    inline uint8_t GetFF() const { return mFF; }
+};
+
+class PVehicleInformation
+{
+    friend class PSpawnedVehicle;
+    friend class PVehicles;
+
+  private:
+    uint32_t mVehicleId;
+    uint32_t mOwnerCharId;
+    uint32_t mHealth; // or float ???
+    uint8_t mVehicleType;
+    uint8_t mStatus; //vhcStatus 0:parking, 1:in_service, 2:destroyed
+
+  public:
+    inline PVehicleInformation( uint32_t nVehicleId = 0, uint32_t nOwnerCharId = 0, uint32_t nHealth = 0, uint8_t nVehicleType = 0, uint8_t nStatus = 0 ) :
+        mVehicleId( nVehicleId ),
+        mOwnerCharId( nOwnerCharId ),
+        mHealth( nHealth ),
+        mVehicleType( nVehicleType ),
+        mStatus( nStatus )
+    { }
+
+    inline uint32_t GetVehicleId() const { return mVehicleId; }
+    inline uint32_t GetOwnerCharId() const { return mOwnerCharId; }
+    inline uint32_t GetHealth() const { return mHealth; } // or float ???
+    inline uint8_t GetVehicleType() const { return mVehicleType; }
+    inline uint8_t GetStatus() const { return mStatus; }
+    bool SetStatus( uint8_t nStatus );
+
+    bool Load( uint32_t nVehicleId );
+    bool Save();
+    bool Destroy();
+};
+
+class PSpawnedVehicle
+{
+  private:
+    static const uint8_t mSeatsFlags[];
+
+  private:
+    uint32_t mLocalId;
+    PVehicleInformation mInfo;
+    uint32_t mLocation;
+    PVhcCoordinates mCoords;
+    const PDefVhc* mVhcDef;
+
+    uint32_t mSeatUserId[8];
+    uint8_t mFreeSeatsFlags;
+    uint8_t mNbFreeSeats;
+
+    uint16_t minmax[4][2]; //Temp
+
+  public:
+    PSpawnedVehicle( uint32_t nLocalId, PVehicleInformation const* nVhcInfo, uint32_t nLocation, PVhcCoordinates const* nVhcPos );
+
+    inline uint32_t GetVehicleId() const { return mInfo.mVehicleId; }
+    inline uint32_t GetLocalId() const { return mLocalId; }
+    inline const PVhcCoordinates& GetPosition() const { return mCoords; }
+    inline const PVehicleInformation& GetInformation() const { return mInfo; }
+    inline bool SetStatus( uint8_t nStatus ) { return mInfo.SetStatus( nStatus ); }
+
+    void SetLocation( uint32_t nLocation );
+    inline uint32_t GetLocation() const { return mLocation; }
+    void SetPosition( PVhcCoordinates const* nVhcPos );
+
+    inline bool Save() { return mInfo.Save(); }
+
+    int GetNumSeats() const;
+    inline uint32_t GetSeatUser( uint8_t nSeatId ) const { return (( nSeatId < 8 ) ? mSeatUserId[nSeatId] : 0 ); }
+    bool SetSeatUser( uint8_t nSeatId, uint32_t nCharId );
+    bool UnsetSeatUser( uint8_t nSeatId, uint32_t nCharId );
+    bool IsCharInside( uint32_t nCharId ) const;
+    inline uint8_t GetFreeSeatsFlags() const { return mFreeSeatsFlags; }
+    inline uint8_t GetNbFreeSeats() const { return mNbFreeSeats; }
+    uint8_t GetFirstFreeSeat() const;
+
+    //SetHealth(const uint32_t nHealth);
+    //uint32_t DoDamage(const uint32_t nHealthDec);
+    //uint32_t DoRepair(const uint32_t nHealthInc);
+};
+
+typedef std::map<uint32_t, PSpawnedVehicle*> PSpawnedVhcMap;
+typedef std::queue<PVehicleInformation*> PVhcInfoList;
+class PVehicles
+{
+  private:
+    PSpawnedVhcMap mSpawnedVehicles;
+
+    bool RegisterSpawnedVehicle( PSpawnedVehicle*  nSpawnedVehicle );
+    bool UnregisterSpawnedVehicle( uint32_t nVehicleId );
+
+  public:
+    PVehicles();
+    ~PVehicles();
+
+    //uint32_t CreateVehicle(uint32_t nOwnerChar, uint8_t mVehicleType);
+    //bool RegisterVehicleOwner(uint32_t nVehiculeId, uint32_t nOwnerChar);
+    //bool DestroyVehicle(uint32_t nVehiculeId);
+    bool IsValidVehicle( uint32_t nVehicleId, bool nCheckOwner = false, uint32_t nOwnerId = 0 ) const;
+    inline bool IsSpawned( uint32_t nVehicleId ) const { return ( mSpawnedVehicles.find( nVehicleId ) != mSpawnedVehicles.end() ); }
+    PSpawnedVehicle* GetSpawnedVehicle( uint32_t nVehicleId ) const;
+    bool GetVehicleInfo( uint32_t nVehicleId, PVehicleInformation* nInfo ) const;
+    PSpawnedVehicle* SpawnVehicle( uint32_t nVehicleId, uint32_t nLocation, PVhcCoordinates const* nVhcPos ); // Refuses for subway zone atm
+    bool UnspawnVehicle( uint32_t nVehicleId );
+
+    PVhcInfoList* GetCharVehicles( uint32_t nCharId, uint16_t nMaxCount = 0, uint16_t nStartIndex = 0 );
+
+};
+
+typedef std::vector<PSpawnedVehicle*> PSpawnedVhcVector;
+typedef std::queue<PSpawnedVehicle*> PSpawnedVhcList;
+
+class PSpawnedVehicles
+{
+    friend class PWorld;
+
+  public:
+    static const uint32_t mVhcBaseLocalId = 0x03fd; //Vhc local Id are allocated downward from this value. Could br 0x3ff, but 0x3fe is used as "target" when shooting nowhere
+    static const uint16_t mMaxLocalVhc = 127;
+
+    inline static bool IsPotentialSpawnedVehicle( uint32_t nLocalId )
+    { return (( nLocalId <= mVhcBaseLocalId ) && (( mVhcBaseLocalId - nLocalId ) < mMaxLocalVhc ) ); }
+
+  private:
+    PSpawnedVhcVector mSpawnedVehicles;
+    uint16_t mNextFreeHint;
+    uint32_t mLocation;
+
+    inline void SetLocation( uint32_t nLocation ) { mLocation = nLocation; }
+
+  public:
+    PSpawnedVehicles();
+    ~PSpawnedVehicles();
+
+    inline bool IsSpawned( uint32_t nLocalId ) const { return (( nLocalId <= mVhcBaseLocalId ) && (( mVhcBaseLocalId - nLocalId ) < mSpawnedVehicles.size() ) && mSpawnedVehicles[mVhcBaseLocalId-nLocalId] ); }
+    PSpawnedVehicle* SpawnVehicle( PVehicleInformation const* nVhcInfo, PVhcCoordinates const* nVhcPos );
+    PSpawnedVehicle* GetVehicle( uint32_t nLocalId );
+    PSpawnedVehicle* GetVehicleByGlobalId( uint32_t nVehicleId ) const;
+    bool UnspawnVehicle( uint32_t nVehicleId );
+
+    PSpawnedVhcList* GetSpawnedVehicles() const;
+};
index 423327b..22c9f11 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class PClient;\r
-\r
-/*\r
-Current known WorldActors:\r
-\r
-- Furniture\r
-1       Door\r
-2       Wooden Door\r
-3       Tech Door\r
-5       Lift\r
-6       Shutter\r
-9       Airlock\r
-10      Chair\r
-11      Wooden Chair\r
-12      Bench\r
-13      Table\r
-14      Recreation Unit\r
-\r
-- Interactions\r
-21      Gen rep\r
-22      Go Guardian\r
-99      Outfitter\r
-23/29   Venture Warp\r
-90      City Com\r
-98      Home term\r
-104     Home term\r
-160-195 Hack term\r
-900     Carport Term\r
-\r
-- Cabinets\r
-150     Cabinet\r
-101     Secure Cabinet\r
-105     Safe\r
-106     High Security Safe\r
-\r
-- Hack Boxes\r
-700     Light Weapon Box\r
-703     Medium\r
-720     Ammo Box\r
-740     Armour Box\r
-750     Equipment Box\r
-780     Psi Box\r
-\r
-- Containers\r
-134     Old Bag\r
-120     Trashcan\r
-125     Old Bag\r
-126     Mutant Cooking Pot\r
-127     Rotten Box\r
-128     Rusty Box\r
-133     Steel Box\r
-130     Bunch of Bones\r
-136     Dead Technician (Loot)\r
-137     Corpse (Loot)\r
-\r
-- Others\r
-131     Pile of Stones\r
-8       Rock\r
-510     Tree Trunk\r
-790     Burning Barrel\r
-800     Explosive Barrel\r
-\r
-- Costs\r
-15      Pay 20nc\r
-16      Pay 50nc\r
-17      Pay 100nc\r
-18      Pay 150nc\r
-19      Pay 200nc\r
-20      Pay 500nc\r
-\r
-*/\r
-\r
-// Start from this offset (00 00 80 00)\r
-#define DYNACTORIDSTART 8388608\r
-\r
-class PWorldActors {\r
-    private:\r
-    // SQL Layout\r
-        enum\r
-        {\r
-            wa_id,\r
-            wa_actor_id,\r
-            wa_actor_map,\r
-            wa_actor_model,\r
-            wa_actor_type,\r
-            wa_posX,\r
-            wa_posY,\r
-            wa_posZ,\r
-            wa_rotX,\r
-            wa_rotY,\r
-            wa_rotZ,\r
-            wa_option1,\r
-            wa_option2,\r
-            wa_option3\r
-        };\r
-\r
-        void SpawnWA(uint32_t nWorld, uint16_t nActorID, uint16_t nFunctionID, uint32_t nWOID, uint16_t nPosX, uint16_t nPosY, uint16_t nPosZ, uint8_t nRotX, uint8_t nRotY, uint8_t nRotZ);\r
-        void VanishWA(uint32_t nWorld, uint32_t nWAid);\r
-\r
-        // Get next availeable WorldactorID. First, try to find ID in known .dat files, then\r
-        // Get the currently highest ID from SQL and add +1\r
-        // select distinct wi_worlditem_id from world_items order by wi_worlditem_id desc limit 1;\r
-        uint32_t GetNextFreeWAID();\r
-\r
-    public:\r
-        PWorldActors();\r
-        ~PWorldActors();\r
-\r
-        // Sends initial zone setup to client (after zoning-in)\r
-        void InitWorld(PClient* nClient);\r
-\r
-        // Add new worldactor to database and spawn it. Returns created WorldID\r
-        // Position is taken from nClient, same as the worldID and calls the mainfunction\r
-        // The function values are optional (used for interactive objects, gogo or genrep)\r
-        uint32_t AddWorldActor(PClient* nClient, uint16_t nActorID, uint16_t nFuncID, uint16_t nOpt1 = 0, uint16_t nOpt2 = 0, uint16_t nOpt3 = 0);\r
-\r
-        // Add new worldactor to database and spawn it. Returns created WorldID\r
-        // The function values are optional (used for interactive objects, gogo or genrep)\r
-        uint32_t AddWorldActor(uint32_t nWorldID, uint16_t nActorID, uint16_t nFuncID, uint16_t nPosX, uint16_t nPosY, uint16_t nPosZ, uint8_t nRotX, uint8_t nRotY, uint8_t nRotZ, uint16_t nOpt1 = 0, uint16_t nOpt2 = 0, uint16_t nOpt3 = 0);\r
-\r
-        // Remove worldactor in given world from SQL and game\r
-        void DelWorldActor(PClient* nClient, uint32_t nWAid);\r
-\r
-        // Get functionvalues for worldactor\r
-        void GetWAoption(uint32_t nWAid, uint16_t nWorld, uint16_t &nValue1, uint16_t &nValue2, uint16_t &nValue3);\r
-\r
-        // Get SQL ID from world and worldID\r
-        int GetWASQLID(uint32_t nWAid, uint32_t nWorld);\r
-\r
-        // Check if actorID is dynamic\r
-        bool IsDynamicActor(uint32_t nWAid);\r
-\r
-        // Not needed. Better re-spawn the actor\r
-        //bool EditWorldActor(uint32_t nWorldID, int nOption1 = -1, int nOption2 = -1, int nOption3 = -1);\r
-\r
-        int GetWorldActorFunctionID(uint32_t nWAid);\r
-\r
-        void GetFrontPos(uint32_t nWAID, uint16_t* mX, uint16_t* mY, uint16_t* mZ); // For chairs\r
-        int GetLinkedObjectID(uint32_t nWAID); // OptionValue 1 is used for linked object!\r
-\r
-        // Check if given functionID does exist\r
-        bool IsValidWAFunction(int nFunctionID);\r
-\r
-        // Checks if this functionID required an linked object or not\r
-        bool RequiresLinkedObject(int nFunctionID);\r
-\r
-        // Checks if the given worldobjectID is valid for this type of functionID\r
-        bool IsValidLinkedObject(PClient *nClient, uint16_t nOption1, int nFunctionID);\r
-\r
-        // Checks for double actor-IDs and deletes them from DB\r
-        void DoActorCheck();\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+class PClient;
+
+/*
+Current known WorldActors:
+
+- Furniture
+1       Door
+2       Wooden Door
+3       Tech Door
+5       Lift
+6       Shutter
+9       Airlock
+10      Chair
+11      Wooden Chair
+12      Bench
+13      Table
+14      Recreation Unit
+
+- Interactions
+21      Gen rep
+22      Go Guardian
+99      Outfitter
+23/29   Venture Warp
+90      City Com
+98      Home term
+104     Home term
+160-195 Hack term
+900     Carport Term
+
+- Cabinets
+150     Cabinet
+101     Secure Cabinet
+105     Safe
+106     High Security Safe
+
+- Hack Boxes
+700     Light Weapon Box
+703     Medium
+720     Ammo Box
+740     Armour Box
+750     Equipment Box
+780     Psi Box
+
+- Containers
+134     Old Bag
+120     Trashcan
+125     Old Bag
+126     Mutant Cooking Pot
+127     Rotten Box
+128     Rusty Box
+133     Steel Box
+130     Bunch of Bones
+136     Dead Technician (Loot)
+137     Corpse (Loot)
+
+- Others
+131     Pile of Stones
+8       Rock
+510     Tree Trunk
+790     Burning Barrel
+800     Explosive Barrel
+
+- Costs
+15      Pay 20nc
+16      Pay 50nc
+17      Pay 100nc
+18      Pay 150nc
+19      Pay 200nc
+20      Pay 500nc
+
+*/
+
+// Start from this offset (00 00 80 00)
+#define DYNACTORIDSTART 8388608
+
+class PWorldActors {
+    private:
+    // SQL Layout
+        enum
+        {
+            wa_id,
+            wa_actor_id,
+            wa_actor_map,
+            wa_actor_model,
+            wa_actor_type,
+            wa_posX,
+            wa_posY,
+            wa_posZ,
+            wa_rotX,
+            wa_rotY,
+            wa_rotZ,
+            wa_option1,
+            wa_option2,
+            wa_option3
+        };
+
+        void SpawnWA(uint32_t nWorld, uint16_t nActorID, uint16_t nFunctionID, uint32_t nWOID, uint16_t nPosX, uint16_t nPosY, uint16_t nPosZ, uint8_t nRotX, uint8_t nRotY, uint8_t nRotZ);
+        void VanishWA(uint32_t nWorld, uint32_t nWAid);
+
+        // Get next availeable WorldactorID. First, try to find ID in known .dat files, then
+        // Get the currently highest ID from SQL and add +1
+        // select distinct wi_worlditem_id from world_items order by wi_worlditem_id desc limit 1;
+        uint32_t GetNextFreeWAID();
+
+    public:
+        PWorldActors();
+        ~PWorldActors();
+
+        // Sends initial zone setup to client (after zoning-in)
+        void InitWorld(PClient* nClient);
+
+        // Add new worldactor to database and spawn it. Returns created WorldID
+        // Position is taken from nClient, same as the worldID and calls the mainfunction
+        // The function values are optional (used for interactive objects, gogo or genrep)
+        uint32_t AddWorldActor(PClient* nClient, uint16_t nActorID, uint16_t nFuncID, uint16_t nOpt1 = 0, uint16_t nOpt2 = 0, uint16_t nOpt3 = 0);
+
+        // Add new worldactor to database and spawn it. Returns created WorldID
+        // The function values are optional (used for interactive objects, gogo or genrep)
+        uint32_t AddWorldActor(uint32_t nWorldID, uint16_t nActorID, uint16_t nFuncID, uint16_t nPosX, uint16_t nPosY, uint16_t nPosZ, uint8_t nRotX, uint8_t nRotY, uint8_t nRotZ, uint16_t nOpt1 = 0, uint16_t nOpt2 = 0, uint16_t nOpt3 = 0);
+
+        // Remove worldactor in given world from SQL and game
+        void DelWorldActor(PClient* nClient, uint32_t nWAid);
+
+        // Get functionvalues for worldactor
+        void GetWAoption(uint32_t nWAid, uint16_t nWorld, uint16_t &nValue1, uint16_t &nValue2, uint16_t &nValue3);
+
+        // Get SQL ID from world and worldID
+        int GetWASQLID(uint32_t nWAid, uint32_t nWorld);
+
+        // Check if actorID is dynamic
+        bool IsDynamicActor(uint32_t nWAid);
+
+        // Not needed. Better re-spawn the actor
+        //bool EditWorldActor(uint32_t nWorldID, int nOption1 = -1, int nOption2 = -1, int nOption3 = -1);
+
+        int GetWorldActorFunctionID(uint32_t nWAid);
+
+        void GetFrontPos(uint32_t nWAID, uint16_t* mX, uint16_t* mY, uint16_t* mZ); // For chairs
+        int GetLinkedObjectID(uint32_t nWAID); // OptionValue 1 is used for linked object!
+
+        // Check if given functionID does exist
+        bool IsValidWAFunction(int nFunctionID);
+
+        // Checks if this functionID required an linked object or not
+        bool RequiresLinkedObject(int nFunctionID);
+
+        // Checks if the given worldobjectID is valid for this type of functionID
+        bool IsValidLinkedObject(PClient *nClient, uint16_t nOption1, int nFunctionID);
+
+        // Checks for double actor-IDs and deletes them from DB
+        void DoActorCheck();
+};
index 003863d..4778ed3 100644 (file)
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PWorldDataTemplate::PWorldDataTemplate()\r
-{\r
-    mUseCount = 0;\r
-    for ( int i = 0; i < WORLDDATATEMPLATE_MAXPOSITEMS; ++i )\r
-    {\r
-        mPositionItems[i] = NULL;\r
-    }\r
-}\r
-\r
-PWorldDataTemplate::~PWorldDataTemplate()\r
-{\r
-    DatFileDataCleanup();\r
-}\r
-\r
-void PWorldDataTemplate::DatFileDataCleanup()\r
-{\r
-    for ( PFurnitureItemsMap::iterator i = mFurnitureItems.begin(); i != mFurnitureItems.end(); i++ )\r
-        delete i->second;\r
-    for ( PDoorsMap::iterator i = mDoors.begin(); i != mDoors.end(); i++ )\r
-        delete i->second;\r
-    for ( PNPCsMap::iterator i = mNPCs.begin(); i != mNPCs.end(); i++ )\r
-        delete i->second;\r
-}\r
-\r
-bool PWorldDataTemplate::LoadDatFile( const std::string& WorldTemplateName, const std::string& nFilename, const bool nTestAccesOnly )\r
-{\r
-    PWorldDatParser WDatLoader;\r
-    int LoadResult;\r
-\r
-    DatFileDataCleanup();\r
-    if ( gDevDebug ) Console->Print( "%s Loading %s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nFilename.c_str() );\r
-    LoadResult = WDatLoader.LoadDatFile( nFilename, this, true, nTestAccesOnly ) ; // We want to discard passive objects for now\r
-    switch ( LoadResult )\r
-    {\r
-    case 0:\r
-    {\r
-        mName = nFilename;\r
-        mBspName = WorldTemplateName;\r
-        if ( !nTestAccesOnly )\r
-        {\r
-            SetLinkedObjects(); // temp until better solution found from .dat & .bsp files\r
-        }\r
-        return true;\r
-    }\r
-\r
-    case -1:\r
-    {\r
-        if ( !nTestAccesOnly )\r
-            Console->Print( "%s Can't read file %s", Console->ColorText( RED, BLACK, "[ERROR]" ), nFilename.c_str() );\r
-        break;\r
-    }\r
-\r
-    case - 2:\r
-    {\r
-        Console->Print( "%s Bad data", Console->ColorText( RED, BLACK, "[ERROR]" ) );\r
-        break;\r
-    }\r
-\r
-    case - 3:\r
-    {\r
-        Console->Print( "%s Unexpected end of file", Console->ColorText( RED, BLACK, "[ERROR]" ) );\r
-        break;\r
-    }\r
-\r
-    default:\r
-        Console->Print( "%s Unknown error %d", Console->ColorText( RED, BLACK, "[ERROR]" ), LoadResult );\r
-    }\r
-    return false;\r
-}\r
-\r
-uint32_t PWorldDataTemplate::AddFurnitureItem( PFurnitureItemTemplate* nItem )\r
-{\r
-    if ( nItem )\r
-    {\r
-        if ( mFurnitureItems.insert( std::make_pair( nItem->GetID(), nItem ) ).second )\r
-        {\r
-            if ( gDevDebug ) Console->Print( "%s Furniture item %d added to world template", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nItem->GetID() );\r
-\r
-            if ( nItem->GetFunctionType() == 21 )\r
-            {\r
-                int v = nItem->GetFunctionValue();\r
-                if (( v >= 0 ) && ( v < WORLDDATATEMPLATE_MAXPOSITEMS ) )\r
-                {\r
-                    if ( mPositionItems[v] )\r
-                    {\r
-                        if (( v == WORLDDATATEMPLATE_MAXPOSITEMS - 2 ) && !mPositionItems[v+1] ) // We allow that only for Pos 9 in order not to mess with other pos\r
-                        {\r
-                            Console->Print( "%s Same position %d for two position items ID %d and %d. Last one will be put on next position.", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), v, mPositionItems[v]->GetID(), nItem->GetID() );\r
-                            ++v;\r
-                        }\r
-                        else\r
-                        {\r
-                            Console->Print( "%s Same position %d for two position items ID %d and %d. Only last one kept.", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), v, mPositionItems[v]->GetID(), nItem->GetID() );\r
-                        }\r
-                    }\r
-\r
-                    mPositionItems[v] = nItem;\r
-                    /*\r
-                    Console->Print("Position entity %d (id 0x%x) added to world template", v, nItem->GetID());\r
-                    float fpX, fpY, fpZ;\r
-                    uint16_t pX, pY, pZ;\r
-                    nItem->GetPos(&fpX, &fpY, &fpZ);\r
-                    pX = (uint16_t) (fpX + 32000);\r
-                    pY = (uint16_t) (fpY + 32000);\r
-                    pZ = (uint16_t) (fpZ + 32000);\r
-                    Console->Print("Position Y=%f (0x%04x) Z=%f (0x%04x) X=%f (0x%04x)", fpY, pY, fpZ, pZ, fpX, pX);\r
-                    */\r
-                }\r
-                else\r
-                {\r
-                    Console->Print( "%s Invalid position %d for position item ID %d. Position ignored.", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), v, nItem->GetID() );\r
-                }\r
-            }\r
-            return nItem->GetID();\r
-        }\r
-        else\r
-        {\r
-            Console->Print( "%s Duplicate furniture item ID %d !!! Not added to world template", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), nItem->GetID() );\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-const PFurnitureItemTemplate* PWorldDataTemplate::GetFurnitureItem( uint32_t ItemID )\r
-{\r
-    PFurnitureItemsMap::const_iterator it = mFurnitureItems.find( ItemID );\r
-    if ( it == mFurnitureItems.end() )\r
-        return NULL;\r
-    else\r
-        return it->second;\r
-}\r
-\r
-bool PWorldDataTemplate::getPositionItemPosition( uint8_t PosID, float* pX, float* pY, float* pZ )\r
-{\r
-    if (( PosID < WORLDDATATEMPLATE_MAXPOSITEMS ) && mPositionItems[PosID] )\r
-    {\r
-        mPositionItems[PosID]->GetPos( pX, pY, pZ ) ;\r
-        return true;\r
-    }\r
-    return false;\r
-}\r
-\r
-uint32_t PWorldDataTemplate::AddDoor( PDoorTemplate* nDoor )\r
-{\r
-    if ( nDoor )\r
-    {\r
-        if ( mDoors.insert( std::make_pair( nDoor->GetID(), nDoor ) ).second )\r
-        {\r
-            if ( gDevDebug ) Console->Print( "%s Door %d added to world template", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nDoor->GetID() );\r
-            return nDoor->GetID();\r
-        }\r
-        else\r
-        {\r
-            Console->Print( "%s Duplicate Door ID %d !!! Not added to world template", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), nDoor->GetID() );\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-const PDoorTemplate* PWorldDataTemplate::GetDoor( uint32_t DoorID )\r
-{\r
-    PDoorsMap::const_iterator it = mDoors.find( DoorID );\r
-    if ( it == mDoors.end() )\r
-        return NULL;\r
-    else\r
-        return it->second;\r
-}\r
-\r
-\r
-uint32_t PWorldDataTemplate::AddNPC( PNPCTemplate* nNPC )\r
-{\r
-    if ( nNPC )\r
-    {\r
-        if ( mNPCs.insert( std::make_pair( nNPC->GetNpcID(), nNPC ) ).second )\r
-        {\r
-            if ( gDevDebug ) Console->Print( "%s NPC %d added to world template", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nNPC->GetNpcID() );\r
-            return nNPC->GetNpcID();\r
-        }\r
-        else\r
-        {\r
-            Console->Print( "%s Duplicate NPC ID %d !!! Not added to world template", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), nNPC->GetNpcID() );\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-const PNPCTemplate* PWorldDataTemplate::GetNPC( uint32_t NPCID )\r
-{\r
-    PNPCsMap::const_iterator it = mNPCs.find( NPCID );\r
-    if ( it == mNPCs.end() )\r
-        return NULL;\r
-    else\r
-        return it->second;\r
-}\r
-\r
-void PWorldDataTemplate::SetLinkedObjects()\r
-{\r
-    float xI, yI, zI;\r
-    float xD, yD, zD;\r
-    float D2, minD2;\r
-    uint32_t minObjID;\r
-    uint16_t fnctType;\r
-    uint16_t tGROrder = 0;\r
-\r
-    for ( PFurnitureItemsMap::iterator it = mFurnitureItems.begin(); it != mFurnitureItems.end(); it++ )\r
-    {\r
-        fnctType = it->second->GetFunctionType();\r
-        if (( fnctType == 11 ) || ( fnctType == 12 ) || ( fnctType == 13 ) || ( fnctType == 23 ) ) // if function is apt entry button, door access if, hack button or money button\r
-        {\r
-            it->second->GetPos( &xI, &yI, &zI );\r
-//Console->Print("Button pos: %0.0f %0.0f %0.0f", xI, yI, zI);\r
-            minD2 = 1e9;\r
-            minObjID = 0;\r
-            for ( PDoorsMap::iterator dit = mDoors.begin(); dit != mDoors.end(); dit++ )\r
-            {\r
-//Console->Print("%s Found door %d (%s) : %s triggered, %s", Console->ColorText(GREEN, BLACK, "[Debug]"), dit->first, dit->second->GetName().c_str(), (dit->second->IsTriggeredDoor()?"":"not"), (dit->second->IsDoubleDoor()?"double":"single") );\r
-                if ( dit->second->IsTriggeredDoor() )\r
-                {\r
-                    dit->second->GetPos( &xD, &yD, &zD );\r
-//Console->Print("Door pos: %0.0f %0.0f %0.0f", xD, yD, zD);\r
-                    D2 = ( xI - xD ) * ( xI - xD ) + ( yI - yD ) * ( yI - yD ) + ( zI - zD ) * ( zI - zD );\r
-//Console->Print("Dist D2:%0.0f minD2:%0.0f", D2, minD2);\r
-                    if ( D2 < minD2 )\r
-                    {\r
-                        minD2 = D2;\r
-                        minObjID = 1 + dit->first;\r
-                    }\r
-                }\r
-            }\r
-            if ( minObjID-- )\r
-            {\r
-                it->second->SetLinkedObjectID( minObjID );\r
-                if ( gDevDebug ) Console->Print( "%s Found triggered door %d (%s) for button %d (%s)", Console->ColorText( GREEN, BLACK, "[Debug]" ), minObjID, GetDoor( minObjID )->GetName().c_str(), it->first, it->second->GetName().c_str() );\r
-\r
-            }\r
-            else\r
-            {\r
-                Console->Print( "%s No triggered door found for button %d (%s) in World data template %s", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), it->first, it->second->GetName().c_str(), this->GetName().c_str() );\r
-            }\r
-        }\r
-        else if ( fnctType == 6 ) // if function is genrep\r
-        {\r
-            it->second->SetLinkedObjectID( ++tGROrder );\r
-        }\r
-    }\r
-\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PWorldDataTemplate::PWorldDataTemplate()
+{
+    mUseCount = 0;
+    for ( int i = 0; i < WORLDDATATEMPLATE_MAXPOSITEMS; ++i )
+    {
+        mPositionItems[i] = NULL;
+    }
+}
+
+PWorldDataTemplate::~PWorldDataTemplate()
+{
+    DatFileDataCleanup();
+}
+
+void PWorldDataTemplate::DatFileDataCleanup()
+{
+    for ( PFurnitureItemsMap::iterator i = mFurnitureItems.begin(); i != mFurnitureItems.end(); i++ )
+        delete i->second;
+    for ( PDoorsMap::iterator i = mDoors.begin(); i != mDoors.end(); i++ )
+        delete i->second;
+    for ( PNPCsMap::iterator i = mNPCs.begin(); i != mNPCs.end(); i++ )
+        delete i->second;
+}
+
+bool PWorldDataTemplate::LoadDatFile( const std::string& WorldTemplateName, const std::string& nFilename, const bool nTestAccesOnly )
+{
+    PWorldDatParser WDatLoader;
+    int LoadResult;
+
+    DatFileDataCleanup();
+    if ( gDevDebug ) Console->Print( "%s Loading %s", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nFilename.c_str() );
+    LoadResult = WDatLoader.LoadDatFile( nFilename, this, true, nTestAccesOnly ) ; // We want to discard passive objects for now
+    switch ( LoadResult )
+    {
+    case 0:
+    {
+        mName = nFilename;
+        mBspName = WorldTemplateName;
+        if ( !nTestAccesOnly )
+        {
+            SetLinkedObjects(); // temp until better solution found from .dat & .bsp files
+        }
+        return true;
+    }
+
+    case -1:
+    {
+        if ( !nTestAccesOnly )
+            Console->Print( "%s Can't read file %s", Console->ColorText( RED, BLACK, "[ERROR]" ), nFilename.c_str() );
+        break;
+    }
+
+    case - 2:
+    {
+        Console->Print( "%s Bad data", Console->ColorText( RED, BLACK, "[ERROR]" ) );
+        break;
+    }
+
+    case - 3:
+    {
+        Console->Print( "%s Unexpected end of file", Console->ColorText( RED, BLACK, "[ERROR]" ) );
+        break;
+    }
+
+    default:
+        Console->Print( "%s Unknown error %d", Console->ColorText( RED, BLACK, "[ERROR]" ), LoadResult );
+    }
+    return false;
+}
+
+uint32_t PWorldDataTemplate::AddFurnitureItem( PFurnitureItemTemplate* nItem )
+{
+    if ( nItem )
+    {
+        if ( mFurnitureItems.insert( std::make_pair( nItem->GetID(), nItem ) ).second )
+        {
+            if ( gDevDebug ) Console->Print( "%s Furniture item %d added to world template", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nItem->GetID() );
+
+            if ( nItem->GetFunctionType() == 21 )
+            {
+                int v = nItem->GetFunctionValue();
+                if (( v >= 0 ) && ( v < WORLDDATATEMPLATE_MAXPOSITEMS ) )
+                {
+                    if ( mPositionItems[v] )
+                    {
+                        if (( v == WORLDDATATEMPLATE_MAXPOSITEMS - 2 ) && !mPositionItems[v+1] ) // We allow that only for Pos 9 in order not to mess with other pos
+                        {
+                            Console->Print( "%s Same position %d for two position items ID %d and %d. Last one will be put on next position.", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), v, mPositionItems[v]->GetID(), nItem->GetID() );
+                            ++v;
+                        }
+                        else
+                        {
+                            Console->Print( "%s Same position %d for two position items ID %d and %d. Only last one kept.", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), v, mPositionItems[v]->GetID(), nItem->GetID() );
+                        }
+                    }
+
+                    mPositionItems[v] = nItem;
+                    /*
+                    Console->Print("Position entity %d (id 0x%x) added to world template", v, nItem->GetID());
+                    float fpX, fpY, fpZ;
+                    uint16_t pX, pY, pZ;
+                    nItem->GetPos(&fpX, &fpY, &fpZ);
+                    pX = (uint16_t) (fpX + 32000);
+                    pY = (uint16_t) (fpY + 32000);
+                    pZ = (uint16_t) (fpZ + 32000);
+                    Console->Print("Position Y=%f (0x%04x) Z=%f (0x%04x) X=%f (0x%04x)", fpY, pY, fpZ, pZ, fpX, pX);
+                    */
+                }
+                else
+                {
+                    Console->Print( "%s Invalid position %d for position item ID %d. Position ignored.", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), v, nItem->GetID() );
+                }
+            }
+            return nItem->GetID();
+        }
+        else
+        {
+            Console->Print( "%s Duplicate furniture item ID %d !!! Not added to world template", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), nItem->GetID() );
+        }
+    }
+    return 0;
+}
+
+const PFurnitureItemTemplate* PWorldDataTemplate::GetFurnitureItem( uint32_t ItemID )
+{
+    PFurnitureItemsMap::const_iterator it = mFurnitureItems.find( ItemID );
+    if ( it == mFurnitureItems.end() )
+        return NULL;
+    else
+        return it->second;
+}
+
+bool PWorldDataTemplate::getPositionItemPosition( uint8_t PosID, float* pX, float* pY, float* pZ )
+{
+    if (( PosID < WORLDDATATEMPLATE_MAXPOSITEMS ) && mPositionItems[PosID] )
+    {
+        mPositionItems[PosID]->GetPos( pX, pY, pZ ) ;
+        return true;
+    }
+    return false;
+}
+
+uint32_t PWorldDataTemplate::AddDoor( PDoorTemplate* nDoor )
+{
+    if ( nDoor )
+    {
+        if ( mDoors.insert( std::make_pair( nDoor->GetID(), nDoor ) ).second )
+        {
+            if ( gDevDebug ) Console->Print( "%s Door %d added to world template", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nDoor->GetID() );
+            return nDoor->GetID();
+        }
+        else
+        {
+            Console->Print( "%s Duplicate Door ID %d !!! Not added to world template", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), nDoor->GetID() );
+        }
+    }
+    return 0;
+}
+
+const PDoorTemplate* PWorldDataTemplate::GetDoor( uint32_t DoorID )
+{
+    PDoorsMap::const_iterator it = mDoors.find( DoorID );
+    if ( it == mDoors.end() )
+        return NULL;
+    else
+        return it->second;
+}
+
+
+uint32_t PWorldDataTemplate::AddNPC( PNPCTemplate* nNPC )
+{
+    if ( nNPC )
+    {
+        if ( mNPCs.insert( std::make_pair( nNPC->GetNpcID(), nNPC ) ).second )
+        {
+            if ( gDevDebug ) Console->Print( "%s NPC %d added to world template", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), nNPC->GetNpcID() );
+            return nNPC->GetNpcID();
+        }
+        else
+        {
+            Console->Print( "%s Duplicate NPC ID %d !!! Not added to world template", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), nNPC->GetNpcID() );
+        }
+    }
+    return 0;
+}
+
+const PNPCTemplate* PWorldDataTemplate::GetNPC( uint32_t NPCID )
+{
+    PNPCsMap::const_iterator it = mNPCs.find( NPCID );
+    if ( it == mNPCs.end() )
+        return NULL;
+    else
+        return it->second;
+}
+
+void PWorldDataTemplate::SetLinkedObjects()
+{
+    float xI, yI, zI;
+    float xD, yD, zD;
+    float D2, minD2;
+    uint32_t minObjID;
+    uint16_t fnctType;
+    uint16_t tGROrder = 0;
+
+    for ( PFurnitureItemsMap::iterator it = mFurnitureItems.begin(); it != mFurnitureItems.end(); it++ )
+    {
+        fnctType = it->second->GetFunctionType();
+        if (( fnctType == 11 ) || ( fnctType == 12 ) || ( fnctType == 13 ) || ( fnctType == 23 ) ) // if function is apt entry button, door access if, hack button or money button
+        {
+            it->second->GetPos( &xI, &yI, &zI );
+//Console->Print("Button pos: %0.0f %0.0f %0.0f", xI, yI, zI);
+            minD2 = 1e9;
+            minObjID = 0;
+            for ( PDoorsMap::iterator dit = mDoors.begin(); dit != mDoors.end(); dit++ )
+            {
+//Console->Print("%s Found door %d (%s) : %s triggered, %s", Console->ColorText(GREEN, BLACK, "[Debug]"), dit->first, dit->second->GetName().c_str(), (dit->second->IsTriggeredDoor()?"":"not"), (dit->second->IsDoubleDoor()?"double":"single") );
+                if ( dit->second->IsTriggeredDoor() )
+                {
+                    dit->second->GetPos( &xD, &yD, &zD );
+//Console->Print("Door pos: %0.0f %0.0f %0.0f", xD, yD, zD);
+                    D2 = ( xI - xD ) * ( xI - xD ) + ( yI - yD ) * ( yI - yD ) + ( zI - zD ) * ( zI - zD );
+//Console->Print("Dist D2:%0.0f minD2:%0.0f", D2, minD2);
+                    if ( D2 < minD2 )
+                    {
+                        minD2 = D2;
+                        minObjID = 1 + dit->first;
+                    }
+                }
+            }
+            if ( minObjID-- )
+            {
+                it->second->SetLinkedObjectID( minObjID );
+                if ( gDevDebug ) Console->Print( "%s Found triggered door %d (%s) for button %d (%s)", Console->ColorText( GREEN, BLACK, "[Debug]" ), minObjID, GetDoor( minObjID )->GetName().c_str(), it->first, it->second->GetName().c_str() );
+
+            }
+            else
+            {
+                Console->Print( "%s No triggered door found for button %d (%s) in World data template %s", Console->ColorText( YELLOW, BLACK, "[NOTICE]" ), it->first, it->second->GetName().c_str(), this->GetName().c_str() );
+            }
+        }
+        else if ( fnctType == 6 ) // if function is genrep
+        {
+            it->second->SetLinkedObjectID( ++tGROrder );
+        }
+    }
+
+}
index d93f4ba..c052b68 100644 (file)
@@ -1,74 +1,74 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-\r
-#define WORLDDATATEMPLATE_MAXPOSITEMS 11\r
-\r
-class PFurnitureItemTemplate;\r
-typedef std::map<uint32_t, PFurnitureItemTemplate*> PFurnitureItemsMap;\r
-\r
-class PDoorTemplate;\r
-typedef std::map<uint32_t, PDoorTemplate*> PDoorsMap;\r
-\r
-class PNPCTemplate;\r
-typedef std::map<uint32_t, PNPCTemplate*> PNPCsMap;\r
-\r
-class PWorldDataTemplate\r
-{\r
-private:\r
-    std::string mName; // (datfile) relative path+filename without leading ./ or ./worlds/ nor .dat extension\r
-    std::string mBspName; // (bsp file) relative path+filename without leading ./ or ./worlds/ nor .bsp extension\r
-    PFurnitureItemsMap mFurnitureItems;\r
-    PDoorsMap mDoors;\r
-    PNPCsMap mNPCs;\r
-    PFurnitureItemTemplate* mPositionItems[WORLDDATATEMPLATE_MAXPOSITEMS];\r
-\r
-    int mUseCount;\r
-\r
-    void DatFileDataCleanup();\r
-    void SetLinkedObjects(); // This method implements some workarouds for some world objects on which we lack info.\r
-\r
-public:\r
-    PWorldDataTemplate();\r
-    ~PWorldDataTemplate();\r
-\r
-    bool LoadDatFile(const std::string& WorldTemplateName, const std::string& nFilename, const bool nTestAccesOnly = false);\r
-    inline const std::string& GetName()\r
-    {\r
-        return mName;\r
-    }\r
-    inline const std::string& GetBspName()\r
-    {\r
-        return mBspName;\r
-    }\r
-\r
-    inline void IncreaseUseCount()\r
-    {\r
-        ++mUseCount;\r
-    }\r
-    inline int DecreaseUseCount()\r
-    {\r
-        return (mUseCount ? --mUseCount : 0);\r
-    }\r
-    inline int GetUseCount()\r
-    {\r
-        return mUseCount;\r
-    }\r
-\r
-    uint32_t AddFurnitureItem(PFurnitureItemTemplate* nItem);\r
-    const PFurnitureItemTemplate* GetFurnitureItem(uint32_t ItemID);\r
-    bool getPositionItemPosition(uint8_t PosID, float* pX, float* pY, float* pZ);\r
-\r
-    uint32_t AddDoor(PDoorTemplate* nDoor);\r
-    const PDoorTemplate* GetDoor(uint32_t DoorID);\r
-\r
-    uint32_t AddNPC(PNPCTemplate* nNPC);\r
-\r
-    // External functions for NPCManager\r
-    const PNPCTemplate* GetNPC(uint32_t NPCID);\r
-    inline const PNPCsMap *GetNPCMap() const\r
-    {\r
-        return &mNPCs;\r
-    }; // called by class PNPCWorld to get all NPCs for this world\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+#define WORLDDATATEMPLATE_MAXPOSITEMS 11
+
+class PFurnitureItemTemplate;
+typedef std::map<uint32_t, PFurnitureItemTemplate*> PFurnitureItemsMap;
+
+class PDoorTemplate;
+typedef std::map<uint32_t, PDoorTemplate*> PDoorsMap;
+
+class PNPCTemplate;
+typedef std::map<uint32_t, PNPCTemplate*> PNPCsMap;
+
+class PWorldDataTemplate
+{
+private:
+    std::string mName; // (datfile) relative path+filename without leading ./ or ./worlds/ nor .dat extension
+    std::string mBspName; // (bsp file) relative path+filename without leading ./ or ./worlds/ nor .bsp extension
+    PFurnitureItemsMap mFurnitureItems;
+    PDoorsMap mDoors;
+    PNPCsMap mNPCs;
+    PFurnitureItemTemplate* mPositionItems[WORLDDATATEMPLATE_MAXPOSITEMS];
+
+    int mUseCount;
+
+    void DatFileDataCleanup();
+    void SetLinkedObjects(); // This method implements some workarouds for some world objects on which we lack info.
+
+public:
+    PWorldDataTemplate();
+    ~PWorldDataTemplate();
+
+    bool LoadDatFile(const std::string& WorldTemplateName, const std::string& nFilename, const bool nTestAccesOnly = false);
+    inline const std::string& GetName()
+    {
+        return mName;
+    }
+    inline const std::string& GetBspName()
+    {
+        return mBspName;
+    }
+
+    inline void IncreaseUseCount()
+    {
+        ++mUseCount;
+    }
+    inline int DecreaseUseCount()
+    {
+        return (mUseCount ? --mUseCount : 0);
+    }
+    inline int GetUseCount()
+    {
+        return mUseCount;
+    }
+
+    uint32_t AddFurnitureItem(PFurnitureItemTemplate* nItem);
+    const PFurnitureItemTemplate* GetFurnitureItem(uint32_t ItemID);
+    bool getPositionItemPosition(uint8_t PosID, float* pX, float* pY, float* pZ);
+
+    uint32_t AddDoor(PDoorTemplate* nDoor);
+    const PDoorTemplate* GetDoor(uint32_t DoorID);
+
+    uint32_t AddNPC(PNPCTemplate* nNPC);
+
+    // External functions for NPCManager
+    const PNPCTemplate* GetNPC(uint32_t NPCID);
+    inline const PNPCsMap *GetNPCMap() const
+    {
+        return &mNPCs;
+    }; // called by class PNPCWorld to get all NPCs for this world
+};
index 5efc667..57bf7a0 100644 (file)
-#include <set>\r
-#include "GameServer/Includes.hxx"\r
-#include "GameServer/Definitions/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/**** PWorld ****/\r
-uint16_t const PWorld::mZoneOutLimitOffset = 0x100;\r
-uint16_t const PWorld::mBottomZoneOutLimit = 0x4800 - PWorld::mZoneOutLimitOffset;\r
-uint16_t const PWorld::mBottomZoneInLimit = 0x4a00;\r
-uint16_t const PWorld::mTopZoneOutLimit = 0xb200 + PWorld::mZoneOutLimitOffset;\r
-uint16_t const PWorld::mTopZoneInLimit = 0xb000;\r
-const std::string EmptyString;\r
-\r
-PWorld::PWorld()\r
-{\r
-  mID = 0;\r
-  mUseCount = 0;\r
-  mWorldDataTemplate = NULL;\r
-}\r
-\r
-PWorld::~PWorld()\r
-{\r
-}\r
-\r
-bool PWorld::Load( uint32_t nWorldID )\r
-{\r
-  std::string WorldTemplateName;\r
-  std::string tFileName;\r
-  bool tCheckOK;\r
-\r
-  if ( nWorldID > PWorlds::mAptBaseWorldId )\r
-  {\r
-    //int AptTmplID = Appartements->GetAptType(nWorldID - PWorlds::mAptBaseWorldId);\r
-    int AptTmplID = Appartements->GetAptType( nWorldID );\r
-    if ( !AptTmplID )\r
-    {\r
-      Console->Print( "%s PWorld::Load - invalid apt %d", Console->ColorText( RED, BLACK, "[WARNING]" ), nWorldID - PWorlds::mAptBaseWorldId );\r
-      return false;\r
-    }\r
-    const PDefAppartement* nAppDef = GameDefs->Appartements()->GetDef( AptTmplID );\r
-    if ( !nAppDef )\r
-    {\r
-      Console->Print( "%s PWorld::Load - invalid apt type %d", Console->ColorText( RED, BLACK, "[WARNING]" ), AptTmplID );\r
-      return false;\r
-    }\r
-    WorldTemplateName = nAppDef->GetWorldName();\r
-\r
-    tFileName = std::string( "worlds/" ) + WorldTemplateName + ".dat";\r
-    tCheckOK = Worlds->LeaseWorldDataTemplate( WorldTemplateName, tFileName );\r
-    if ( !tCheckOK )\r
-    {\r
-      tFileName = WorldTemplateName + ".dat";\r
-      tCheckOK = Worlds->LeaseWorldDataTemplate( WorldTemplateName, tFileName );\r
-    }\r
-    if ( !tCheckOK )\r
-    {\r
-      Console->Print( "%s PWorld::Load - unable to lease apt world %s (%s)", Console->ColorText( RED, BLACK, "[WARNING]" ), WorldTemplateName.c_str(), tFileName.c_str() );\r
-      return false;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    const PDefWorldFile* nWorldFileDef;\r
-\r
-    if (( nWorldID > 90000 ) && ( nWorldID < 90017 ) ) // hardcoded holomatch hack\r
-    {\r
-      nWorldFileDef = NULL;\r
-      char worldName[19];\r
-      int MatchID = nWorldID - 90000;\r
-      if ( MatchID > 8 ) // to care for Neofrag 1 & 2\r
-        MatchID -= 8;\r
-      if ( MatchID > 6 )\r
-        MatchID = 6; // holomatch 7 and 8 are same as 6\r
-      snprintf( worldName, 19, "holomatch/neofrag%d", MatchID );\r
-      WorldTemplateName = worldName;\r
-    }\r
-    else\r
-    {\r
-      nWorldFileDef = GameDefs->WorldFiles()->GetDef( nWorldID );\r
-      if ( !nWorldFileDef )\r
-        return false;\r
-      WorldTemplateName = nWorldFileDef->GetName();\r
-    }\r
-\r
-    const PDefWorld* tWorldDef = GameDefs->Worlds()->GetDef( nWorldID );\r
-    if ( tWorldDef ) // should always be true here\r
-    {\r
-      if ( !( tWorldDef->GetDatFile().empty() ) )\r
-        tFileName = tWorldDef->GetDatFile();\r
-      else if ( nWorldFileDef )\r
-        tFileName = nWorldFileDef->GetBasicFileName() + ".dat";\r
-      else\r
-      {\r
-        tFileName = "worlds/";\r
-        tFileName += WorldTemplateName;\r
-        tFileName += ".dat";\r
-      }\r
-    }\r
-    else\r
-      return false; // should'nt happen here\r
-\r
-    if ( !Worlds->LeaseWorldDataTemplate( WorldTemplateName, tFileName ) )\r
-      return false;\r
-  }\r
-\r
-  mWorldDataTemplate = Worlds->GetWorldDataTemplate( tFileName );\r
-  if ( !mWorldDataTemplate )\r
-  {\r
-    Console->Print( "%s PWorld::Load : Unexpected world %d not found error", Console->ColorText( RED, BLACK, "[WARNING]" ), nWorldID );\r
-    return false;\r
-  }\r
-\r
-  mID = nWorldID;\r
-  mSpawnedVehicles.SetLocation( nWorldID );\r
-  // furniture & other world stuff loading here\r
-  Console->Print( "%s Loaded world %d", Console->ColorText( GREEN, BLACK, "[DEBUG]" ), nWorldID );\r
-  return true;\r
-}\r
-\r
-std::string PWorld::GetName()\r
-{\r
-    return ( mWorldDataTemplate ? mWorldDataTemplate->GetName() : EmptyString );\r
-}\r
-\r
-std::string PWorld::GetBspName()\r
-{\r
-    return ( mWorldDataTemplate ? mWorldDataTemplate->GetBspName() : EmptyString );\r
-}\r
-\r
-bool PWorld::IsAppartment()\r
-{\r
-    return mIsAppartment;\r
-}\r
-\r
-const PFurnitureItemTemplate *PWorld::GetFurnitureItemTemplate( uint32_t nItemID )\r
-{\r
-    return ( mWorldDataTemplate ? mWorldDataTemplate->GetFurnitureItem( nItemID ) : NULL ) ;\r
-}\r
-\r
-const PDefWorldModel *PWorld::GetFurnitureItemModel(uint32_t nItemID)\r
-{\r
-  if ( mWorldDataTemplate )\r
-  {\r
-    const PFurnitureItemTemplate* tFurniture = mWorldDataTemplate->GetFurnitureItem( nItemID );\r
-    if ( tFurniture )\r
-      return tFurniture->GetDefWorldModel();\r
-  }\r
-  return nullptr;\r
-}\r
-\r
-const PDoorTemplate *PWorld::GetDoor(uint32_t nDoorID)\r
-{\r
-    return (mWorldDataTemplate ? mWorldDataTemplate->GetDoor(nDoorID) : nullptr);\r
-}\r
-\r
-bool PWorld::getPositionItemPosition(uint8_t PosID, float *pX, float *pY, float *pZ)\r
-{\r
-    return (mWorldDataTemplate ? mWorldDataTemplate->getPositionItemPosition(PosID, pX, pY, pZ) : false);\r
-}\r
-\r
-bool PWorld::CharUseChair( int CharLocalID, uint32_t nItemID )\r
-{\r
-  PChairsInUseMap::iterator it = mChairsInUseMap.find( nItemID );\r
-  if ( it == mChairsInUseMap.end() ) // chair is free\r
-  {\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Localchar %d now using free chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID );\r
-    mChairsInUseMap.insert( std::make_pair( nItemID, CharLocalID ) );\r
-    return true;\r
-  }\r
-  else // chair is already in use\r
-  {\r
-    if ( gDevDebug )\r
-    {\r
-      if ( it->second == CharLocalID )\r
-      {\r
-        Console->Print( "%s Localchar %d already using chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID );\r
-      }\r
-      else\r
-      {\r
-        Console->Print( "%s Localchar %d can't sit on chair %d used by localchar %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID, it->second );\r
-      }\r
-    }\r
-    return ( it->second == CharLocalID );\r
-  }\r
-}\r
-\r
-void PWorld::CharLeaveChair( int CharLocalID, uint32_t nItemID )\r
-{\r
-  PChairsInUseMap::iterator it = mChairsInUseMap.find( nItemID );\r
-  if (( it != mChairsInUseMap.end() ) && ( it->second == CharLocalID ) ) // chair is in use by this char\r
-  {\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Localchar %d leaving chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID );\r
-    mChairsInUseMap.erase( it );\r
-  }\r
-}\r
-\r
-PClient* PWorld::GetClientByCharLocalId( uint32_t rawObjectId ) const\r
-{\r
-  // Temp implementation\r
-  return ClientManager->GetClientByCharLocalId( rawObjectId, mID );\r
-}\r
-\r
-PSpawnedVehicles *PWorld::GetSpawnedVehicles()\r
-{\r
-    return &mSpawnedVehicles;\r
-}\r
-\r
-bool PWorld::CheckVhcNeedZoning( PVhcCoordinates const* nPos ) const\r
-{\r
-  if ( ( nPos->GetX() <= mBottomZoneOutLimit ) || ( nPos->GetX() >= mTopZoneOutLimit ) || ( nPos->GetY() <= mBottomZoneOutLimit )   || ( nPos->GetY() >= mTopZoneOutLimit ) )\r
-    return true;\r
-  else\r
-    return false;\r
-}\r
-\r
-uint32_t PWorld::GetVhcZoningDestination( PSpawnedVehicle const* nVhc, PVhcCoordinates* nPos ) const\r
-{\r
-  uint32_t destWorldId = 0;\r
-  int16_t vChange = 0;\r
-  int16_t hChange = 0;\r
-  PVhcCoordinates const vhcPos = nVhc->GetPosition();\r
-  uint16_t posX = vhcPos.GetX();\r
-  uint16_t posY = vhcPos.GetY();\r
-\r
-  if ( posX <= mBottomZoneOutLimit )\r
-  {\r
-    vChange = 1;\r
-  }\r
-  else if ( posX >= mTopZoneOutLimit )\r
-  {\r
-    vChange = -1;\r
-  }\r
-\r
-  if ( posY <= mBottomZoneOutLimit )\r
-  {\r
-    hChange = -1;\r
-  }\r
-  else if ( posY >= mTopZoneOutLimit )\r
-  {\r
-    hChange = 1;\r
-  }\r
-\r
-  if ( vChange || hChange )\r
-  {\r
-    //Console->Print( YELLOW, BLACK, "[DEBUG] Limit Reached V:%d H:%d mapId:%d", vChange,hChange,mID );\r
-    uint8_t currH = 0;\r
-    uint8_t currV = 0;\r
-    int16_t newH, newV;\r
-\r
-    if ( Worlds->GetWorldmapFromWorldId( mID, currH, currV ) )\r
-    {\r
-      //Console->Print( YELLOW, BLACK, "[DEBUG] current map pos V:%d H:%d", currV,currH );\r
-      newH = currH + hChange;\r
-      if ( newH < 0 )\r
-        newH = 0;\r
-      else if ( newH >= PWorlds::mOutdoorWorldmapHSize )\r
-        newH = PWorlds::mOutdoorWorldmapHSize;\r
-\r
-      newV = currV + vChange;\r
-      if ( newV < 0 )\r
-        newV = 0;\r
-      else if ( newV >= PWorlds::mOutdoorWorldmapHSize )\r
-        newV = PWorlds::mOutdoorWorldmapHSize;\r
-\r
-      //Console->Print( YELLOW, BLACK, "[DEBUG] new map pos V:%d H:%d", newV,newH );\r
-      if (( newH != currH ) || ( newV != currV ) )\r
-      {\r
-        destWorldId = Worlds->GetWorldIdFromWorldmap( newH, newV );\r
-\r
-        if ( destWorldId && nPos )\r
-        {\r
-          if ( vChange == 1 )\r
-            posX = mTopZoneInLimit;\r
-          else if ( vChange == -1 )\r
-            posX = mBottomZoneInLimit;\r
-\r
-          if ( hChange == -1 )\r
-            posY = mTopZoneInLimit;\r
-          else if ( hChange == 1 )\r
-            posY = mBottomZoneInLimit;\r
-\r
-          nPos->SetPosition( posY, vhcPos.GetZ(), posX, vhcPos.GetUD(), vhcPos.GetLR(), vhcPos.GetRoll(), vhcPos.GetAct(), vhcPos.GetUnknown(), vhcPos.GetFF() );\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  return destWorldId;\r
-}\r
-\r
-const PNPCsMap *PWorld::GetNPCMap() const\r
-{\r
-    return (mWorldDataTemplate ? mWorldDataTemplate->GetNPCMap() : nullptr);\r
-}\r
-\r
-const PNPCTemplate *PWorld::GetNPCTemplate(uint32_t nNPCID) const\r
-{\r
-    return (mWorldDataTemplate ? mWorldDataTemplate->GetNPC(nNPCID) : nullptr);\r
-}\r
-\r
-/**** PWorlds ****/\r
-uint32_t const PWorlds::mNcSubwayWorldId = 1000;\r
-uint32_t const PWorlds::mAptBaseWorldId = 100000;\r
-uint32_t const PWorlds::mOutdoorBaseWorldId = 2001;\r
-uint32_t const PWorlds::mOutdoorWorldIdVIncrement = 20;\r
-uint8_t const PWorlds::mOutdoorWorldmapHSize = 16;\r
-uint8_t const PWorlds::mOutdoorWorldmapVSize = 11;\r
-uint32_t const PWorlds::mOutdoorMaxWorldId = PWorlds::mOutdoorBaseWorldId + PWorlds::mOutdoorWorldIdVIncrement * ( PWorlds::mOutdoorWorldmapVSize - 1 ) + PWorlds::mOutdoorWorldmapHSize - 1;\r
-\r
-PWorlds::PWorlds()\r
-{\r
-  mPreloadWorldsTemplates = false; // to be put as config option\r
-  mPreloadStaticWorlds = false; // to be put as config option\r
-}\r
-\r
-PWorlds::~PWorlds()\r
-{\r
-  for ( PWorldsMap::iterator i = mStaticWorldsMap.begin(); i != mStaticWorldsMap.end(); i++ )\r
-    if ( i->second )\r
-    {\r
-      delete i->second;\r
-    }\r
-  for ( PWorldsMap::iterator i = mOnDemandWorldsMap.begin(); i != mOnDemandWorldsMap.end(); i++ )\r
-    if ( i->second )\r
-    {\r
-      delete i->second;\r
-    }\r
-  for ( PWorldDataTemplatesMap::iterator i = mWorldDataTemplatesMap.begin(); i != mWorldDataTemplatesMap.end(); i++ )\r
-    if ( i->second )\r
-    {\r
-      delete i->second;\r
-    }\r
-}\r
-\r
-bool PWorlds::LeaseWorldDataTemplate( const std::string& nBspName, const std::string& nFileName, const bool nPreloadPhase )\r
-{\r
-  PWorldDataTemplate* tWorldDataTemplate;\r
-\r
-  PWorldDataTemplatesMap::iterator it = mWorldDataTemplatesMap.find( nFileName );\r
-  if ( it == mWorldDataTemplatesMap.end() ) // template unkown yet\r
-  {\r
-    if ( nPreloadPhase ) // if in preload phase, we try to load it or make it known\r
-    {\r
-      tWorldDataTemplate = new PWorldDataTemplate;\r
-      if ( tWorldDataTemplate->LoadDatFile( nBspName, nFileName, !mPreloadWorldsTemplates ) )\r
-      {\r
-        if ( mPreloadWorldsTemplates )\r
-        {\r
-          mWorldDataTemplatesMap.insert( std::make_pair( nFileName, tWorldDataTemplate ) );\r
-          tWorldDataTemplate->IncreaseUseCount();\r
-        }\r
-        else\r
-        {\r
-          mWorldDataTemplatesMap.insert( std::make_pair( nFileName, ( PWorldDataTemplate* )NULL ) ); // NULL means file access OK but not preloaded yet\r
-          delete tWorldDataTemplate;\r
-        }\r
-        //return true;\r
-      }\r
-      else\r
-      {\r
-        delete tWorldDataTemplate;\r
-        return false;\r
-      }\r
-    }\r
-    else\r
-    {\r
-      return false;\r
-    }\r
-  }\r
-  else // template already known\r
-  {\r
-    if ( !it->second  &&  !nPreloadPhase ) // template known but not already loaded and not in preload ?\r
-    {\r
-      tWorldDataTemplate = new PWorldDataTemplate;\r
-      if ( tWorldDataTemplate->LoadDatFile( nBspName, nFileName ) )\r
-      {\r
-        it->second = tWorldDataTemplate;\r
-      }\r
-      else\r
-      {\r
-        Console->Print( "%s Invalid world data template file %s", Console->ColorText( RED, BLACK, "[ERROR]" ), nFileName.c_str() );\r
-        mWorldDataTemplatesMap.erase( it );\r
-        delete tWorldDataTemplate;\r
-        return false;\r
-      }\r
-    }\r
-\r
-    if ( !nPreloadPhase )\r
-      it->second->IncreaseUseCount();\r
-\r
-    //return true;\r
-  }\r
-\r
-  return true;\r
-}\r
-\r
-void PWorlds::ReleaseWorldDataTemplate( const std::string& nFileName )\r
-{\r
-  PWorldDataTemplatesMap::iterator it = mWorldDataTemplatesMap.find( nFileName );\r
-  if (( it != mWorldDataTemplatesMap.end() ) && it->second )\r
-  {\r
-    it->second->DecreaseUseCount();\r
-  }\r
-  else\r
-    Console->Print( "%s PWorlds::ReleaseWorldDataTemplate : try to relese not loaded template %s", Console->ColorText( RED, BLACK, "[Warning]" ), nFileName.c_str() );\r
-}\r
-\r
-void PWorlds::UnloadWorldDataTemplate( const std::string& nFileName )\r
-{\r
-  PWorldDataTemplate* tWorldDataTemplate;\r
-\r
-  PWorldDataTemplatesMap::iterator it = mWorldDataTemplatesMap.find( nFileName );\r
-  if (( it != mWorldDataTemplatesMap.end() ) && it->second )\r
-  {\r
-    tWorldDataTemplate = it->second;\r
-    if ( mPreloadWorldsTemplates || ( tWorldDataTemplate->GetUseCount() > 0 ) )\r
-      Console->Print( "%s PWorlds::UnloadWorldDataTemplate : attempt to unload template %s when use count not null ou preload set", Console->ColorText( RED, BLACK, "[Warning]" ), nFileName.c_str() );\r
-    else\r
-    {\r
-      it->second = ( PWorldDataTemplate* )NULL;\r
-      delete tWorldDataTemplate;\r
-    }\r
-  }\r
-  else\r
-    Console->Print( "%s PWorlds::UnloadWorldDataTemplate : attempt to release not loaded template %s", Console->ColorText( RED, BLACK, "[Warning]" ), nFileName.c_str() );\r
-}\r
-\r
-PWorldDataTemplate* PWorlds::GetWorldDataTemplate( const std::string& nFileName )\r
-{\r
-  PWorldDataTemplatesMap::const_iterator it = mWorldDataTemplatesMap.find( nFileName );\r
-  if ( it != mWorldDataTemplatesMap.end() )\r
-    return it->second;\r
-  else\r
-    return NULL;\r
-}\r
-\r
-bool PWorlds::LoadWorlds() // once Load is done, only WorldDataTemplate registred in mWorldDataTemplatesMap\r
-{\r
-  //   will be considered as valid\r
-  std::string tFileName;\r
-  std::string tBspName;\r
-  const PDefWorld* tDefWorld;\r
-  bool tCheckOK;\r
-  int ValidCount = 0, InvalidCount = 0, DblInvCount = 0;\r
-  int DatTmplCount, BadDatTmplCount;\r
-  std::set<std::string>\r
-  InvalideFiles;\r
-\r
-  // Appartment templates checking or preloading\r
-  std::map<int, PDefAppartement*>::const_iterator itAptStart = GameDefs->Appartements()->ConstIteratorBegin();\r
-  std::map<int, PDefAppartement*>::const_iterator itAptEnd = GameDefs->Appartements()->ConstIteratorEnd();\r
-  for ( std::map<int, PDefAppartement*>::const_iterator i = itAptStart; i != itAptEnd; i++ )\r
-  {\r
-    tCheckOK = false;\r
-    tBspName = i->second->GetWorldName();\r
-    tFileName = std::string( "worlds/" ) + tBspName + ".dat";\r
-    if ( !InvalideFiles.count( tFileName ) )\r
-    {\r
-      tCheckOK = LeaseWorldDataTemplate( tBspName, tFileName, true );\r
-      if ( !tCheckOK )\r
-      {\r
-        InvalideFiles.insert( tFileName );\r
-        if ( gDevDebug )\r
-          Console->Print( RED, BLACK, "Template file %s invalid", tFileName.c_str() );\r
-      }\r
-    }\r
-    if ( !tCheckOK ) // in case full path was given without omiting worlds/ or in another dir/archive ...\r
-    {\r
-      tFileName = tBspName + ".dat";\r
-      if ( !InvalideFiles.count( tFileName ) )\r
-      {\r
-        tCheckOK = LeaseWorldDataTemplate( tBspName, tFileName, true );\r
-        if ( !tCheckOK )\r
-        {\r
-          InvalideFiles.insert( tFileName );\r
-          ++DblInvCount;\r
-        }\r
-      }\r
-    }\r
-\r
-    if ( tCheckOK )\r
-    {\r
-      ++ValidCount;\r
-      if ( gDevDebug )\r
-        Console->Print( GREEN, BLACK, "Template file %s for appartment %d (%s) loaded", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );\r
-    }\r
-    else\r
-    {\r
-      ++InvalidCount;\r
-      if ( gDevDebug )\r
-        Console->Print( RED, BLACK, "Template file %s for appartment %d (%s) not available or invalid", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );\r
-    }\r
-  }\r
-\r
-  DatTmplCount = mWorldDataTemplatesMap.size();\r
-  BadDatTmplCount = InvalideFiles.size();\r
-  Console->Print( "%s %d valid appartement templates checked (%d dat files)", Console->ColorText( GREEN, BLACK, "[Success]" ), ValidCount, DatTmplCount );\r
-  if ( InvalidCount )\r
-    Console->Print( "%s %d invalid appartement templates rejected (%d dat files)", Console->ColorText( YELLOW, BLACK, "[Notice]" ), InvalidCount, BadDatTmplCount - DblInvCount );\r
-\r
-  // Static worlds & static worlds templates checking or preloading\r
-  ValidCount = InvalidCount = 0;\r
-  const PDefWorldFile* tDefWorldFile;\r
-  std::map<int, PDefWorldFile*>::const_iterator itFilStart = GameDefs->WorldFiles()->ConstIteratorBegin();\r
-  std::map<int, PDefWorldFile*>::const_iterator itFilEnd = GameDefs->WorldFiles()->ConstIteratorEnd();\r
-  for ( std::map<int, PDefWorldFile*>::const_iterator i = itFilStart; i != itFilEnd; i++ )\r
-  {\r
-    tDefWorldFile = i->second;\r
-\r
-    tDefWorld = GameDefs->Worlds()->GetDef( tDefWorldFile->GetIndex() );\r
-    if ( tDefWorld ) // we only care for worlds that are present in worldinfo.def too\r
-    {\r
-      tBspName = tDefWorldFile->GetName();\r
-      if ( !( tDefWorld->GetDatFile().empty() ) )\r
-        tFileName = tDefWorld->GetDatFile();\r
-      else\r
-        tFileName = i->second->GetBasicFileName() + ".dat";\r
-\r
-      tCheckOK = false;\r
-      if ( !InvalideFiles.count( tFileName ) )\r
-      {\r
-        tCheckOK = LeaseWorldDataTemplate( tBspName, tFileName, true );\r
-        if ( !tCheckOK )\r
-        {\r
-          InvalideFiles.insert( tFileName );\r
-          if ( gDevDebug )\r
-            Console->Print( RED, BLACK, "Template file %s invalid", tFileName.c_str() );\r
-        }\r
-      }\r
-\r
-      if ( tCheckOK )\r
-      {\r
-        ++ValidCount;\r
-        if ( mPreloadStaticWorlds )\r
-        {\r
-          LeaseWorld( tDefWorldFile->GetIndex(), true ); // This will make the world ready and kept in mem (use count always >0 )\r
-        }\r
-        else\r
-        {\r
-          mStaticWorldsMap.insert( std::make_pair( tDefWorldFile->GetIndex(), ( PWorld* )NULL ) );\r
-        }\r
-        if ( gDevDebug )\r
-          Console->Print( GREEN, BLACK, "Template file %s for world %d (%s) loaded", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );\r
-      }\r
-      else\r
-      {\r
-        ++InvalidCount;\r
-        if ( gDevDebug )\r
-          Console->Print( RED, BLACK, "Template file %s for world %d (%s) not available or invalid", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );\r
-      }\r
-    }\r
-  }\r
-\r
-  // Hardcoded neofrag worlds ... oO ... and neofrag4.dat can't be found :-/\r
-  for ( int i = 1; i <= 16; i++ )\r
-  {\r
-    char worldName[19];\r
-    int MatchID = i;\r
-    if ( MatchID > 8 ) // to care for Neofrag 1 & 2\r
-      MatchID -= 8;\r
-    if ( MatchID > 6 )\r
-      MatchID = 6; // holomatch 7 and 8 are same as 6\r
-    snprintf( worldName, 19, "holomatch/neofrag%d", MatchID );\r
-\r
-    tDefWorld = GameDefs->Worlds()->GetDef( 90000 + i );\r
-    if ( tDefWorld ) // we only care for worlds that are present in worldinfo.def too\r
-    {\r
-      if ( !( tDefWorld->GetDatFile().empty() ) )\r
-        tFileName = tDefWorld->GetDatFile();\r
-      else\r
-      {\r
-        tFileName = "worlds/";\r
-        tFileName += worldName;\r
-        tFileName += ".dat";\r
-      }\r
-\r
-      tCheckOK = false;\r
-      if ( !InvalideFiles.count( tFileName ) )\r
-      {\r
-        tCheckOK = LeaseWorldDataTemplate( worldName, tFileName, true );\r
-        if ( !tCheckOK )\r
-        {\r
-          InvalideFiles.insert( tFileName );\r
-          if ( gDevDebug )\r
-            Console->Print( RED, BLACK, "Template file %s invalid", tFileName.c_str() );\r
-        }\r
-      }\r
-\r
-      if ( tCheckOK )\r
-      {\r
-        ++ValidCount;\r
-        if ( mPreloadStaticWorlds )\r
-        {\r
-          LeaseWorld( 90000 + i, true ); // This will make the world ready and kept in mem (use count always >0 )\r
-        }\r
-        else\r
-        {\r
-          mStaticWorldsMap.insert( std::make_pair( 90000 + i, ( PWorld* )NULL ) );\r
-        }\r
-        if ( gDevDebug )\r
-          Console->Print( GREEN, BLACK, "Template file %s for world %d (%s) loaded", tFileName.c_str(), 90000 + i, worldName );\r
-      }\r
-      else\r
-      {\r
-        ++InvalidCount;\r
-        if ( gDevDebug )\r
-          Console->Print( RED, BLACK, "Template file %s for world %d (%s) not available or invalid", tFileName.c_str(), 90000 + i, worldName );\r
-      }\r
-    }\r
-  }\r
-\r
-  Console->Print( "%s %d valid world templates checked (%d dat files)", Console->ColorText( GREEN, BLACK, "[Success]" ), ValidCount, mWorldDataTemplatesMap.size() - DatTmplCount );\r
-  if ( InvalidCount )\r
-    Console->Print( "%s %d invalid world templates rejected (%d dat files)", Console->ColorText( YELLOW, BLACK, "[Notice]" ), InvalidCount, InvalideFiles.size() - BadDatTmplCount - DblInvCount );\r
-  Console->Print( "%s %d static worlds prepared", Console->ColorText( GREEN, BLACK, "[Success]" ), mStaticWorldsMap.size() );\r
-\r
-  // release memory if World templates preload activated, this cache that won't be used anymore\r
-  // if (mPreloadWorldsTemplates) Filesystem->ClearCache();\r
-\r
-  return true;\r
-}\r
-\r
-bool PWorlds::IsValidWorld( uint32_t nWorldID ) const\r
-{\r
-  if ( nWorldID > PWorlds::mAptBaseWorldId )\r
-  {\r
-    if ( mOnDemandWorldsMap.count( nWorldID ) ) // Check if already loaded\r
-      return true;\r
-    else //should better do a check using a PAppartements class object to get the world template\r
-    {\r
-      //int AptTmplID = Appartements->GetAptType(nWorldID - PWorlds::mAptBaseWorldId);\r
-      int AptTmplID = Appartements->GetAptType( nWorldID );\r
-      if ( !AptTmplID )\r
-        return false;\r
-\r
-      const PDefAppartement* nAppDef = GameDefs->Appartements()->GetDef( AptTmplID );\r
-      if ( !nAppDef )\r
-        return false;\r
-\r
-      std::string tFileName = "worlds/" + nAppDef->GetWorldName() + ".dat";\r
-      PWorldDataTemplatesMap::const_iterator it = mWorldDataTemplatesMap.find( tFileName );\r
-      return ( it != mWorldDataTemplatesMap.end() );\r
-    }\r
-  }\r
-  else\r
-  {\r
-    if ( gDevDebug )\r
-      Console->Print( "%s Checking validity for world %d : %s", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID, mStaticWorldsMap.count( nWorldID ) ? "OK" : "BAD" );\r
-    return ( mStaticWorldsMap.count( nWorldID ) );\r
-  }\r
-}\r
-\r
-PWorld* PWorlds::LeaseWorld( uint32_t nWorldID, const bool nPreloadPhase )\r
-{\r
-  PWorldsMap::iterator it;\r
-\r
-  if ( nWorldID > PWorlds::mAptBaseWorldId )\r
-  {\r
-    it = mOnDemandWorldsMap.find( nWorldID ); // Check if already loaded\r
-    if (( it != mOnDemandWorldsMap.end() ) && it->second ) // Dynamic world shall not have a NULL it->second\r
-    {\r
-      // if loaded\r
-      it->second->IncreaseUseCount();\r
-      if ( gDevDebug )\r
-        Console->Print( "%s Leased world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );\r
-      return it->second;\r
-    }\r
-    else // not loaded yet or invalid\r
-    {\r
-      PWorld* nWorld = new PWorld;\r
-      if ( ! nWorld->Load( nWorldID ) ) // Error when loading (shouldn't happen)\r
-      {\r
-        delete nWorld;\r
-        Console->Print( "% Could not load world %d - World now set as invalid", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );\r
-        return NULL;\r
-      }\r
-      else\r
-      {\r
-        mOnDemandWorldsMap.insert( std::make_pair( nWorldID, nWorld ) );\r
-        nWorld->IncreaseUseCount();\r
-        if ( gDevDebug )\r
-          Console->Print( "%s Leased world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );\r
-        return nWorld;\r
-      }\r
-    }\r
-  }\r
-  else\r
-  {\r
-    it = mStaticWorldsMap.find( nWorldID ); // Check if already loaded\r
-    if (( it == mStaticWorldsMap.end() ) && nPreloadPhase )\r
-    {\r
-      mStaticWorldsMap.insert( std::make_pair( nWorldID, ( PWorld* )NULL ) );\r
-      it = mStaticWorldsMap.find( nWorldID );\r
-    }\r
-    if ( it != mStaticWorldsMap.end() )\r
-    {\r
-      // if valid\r
-      if ( ! it->second ) // if not loaded yet\r
-      {\r
-        it->second = new PWorld;\r
-        if ( ! it->second->Load( nWorldID ) ) // Error when loading (shouldn't happen)\r
-        {\r
-          delete it->second;\r
-          Console->Print( "%s Could not load world %d - World now set as invalid", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );\r
-          mStaticWorldsMap.erase( it ); // remove from valid worlds map\r
-          return NULL;\r
-        }\r
-      }\r
-      it->second->IncreaseUseCount();\r
-      if ( gDevDebug )\r
-        Console->Print( "%s Leased world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );\r
-      return it->second;\r
-    }\r
-    else // invalid worldID\r
-    {\r
-      return NULL;\r
-    }\r
-  }\r
-}\r
-\r
-PWorld* PWorlds::GetWorld( uint32_t nWorldID )\r
-{\r
-  PWorldsMap* tMap;\r
-  PWorldsMap::iterator it;\r
-\r
-  tMap = (( nWorldID > PWorlds::mAptBaseWorldId ) ? &mOnDemandWorldsMap : &mStaticWorldsMap );\r
-\r
-  it = tMap->find( nWorldID );\r
-  if (( it != tMap->end() ) && it->second )\r
-  {\r
-    return it->second;\r
-  }\r
-  else\r
-  {\r
-    Console->Print( "%s PWorlds::GetWorld : Trying to get world %d without lease !", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );\r
-    return NULL;\r
-  }\r
-}\r
-\r
-void PWorlds::ReleaseWorld( uint32_t nWorldID ) // no dynamic unload is performed atm + don't forget spawned vhc !\r
-{\r
-  PWorld* tWorld = GetWorld( nWorldID );\r
-  if ( tWorld )\r
-  {\r
-    if ( tWorld->GetUseCount() ) // this check is for dev time only\r
-    {\r
-      tWorld->DecreaseUseCount();\r
-      if ( gDevDebug )\r
-        Console->Print( "%s Released world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );\r
-    }\r
-    else\r
-    {\r
-      Console->Print( "%s PWorlds::ReleaseWorld : Trying to release world %d with use count 0 !", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );\r
-    }\r
-  }\r
-  else\r
-  {\r
-    Console->Print( "%s PWorlds::ReleaseWorld : Generated the invalid get world %d", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );\r
-  }\r
-}\r
-\r
-bool PWorlds::IsAppartment( uint32_t nWorldID )\r
-{\r
-  return (( nWorldID > PWorlds::mAptBaseWorldId ) && IsValidWorld( nWorldID ) );\r
-}\r
-\r
-void PWorlds::Update()\r
-{}\r
-\r
-void PWorlds::Shutdown()\r
-{}\r
-\r
-uint32_t PWorlds::GetWorldIdFromWorldmap( uint8_t mapH, uint8_t mapV ) const\r
-{\r
-  uint32_t loc = 0;\r
-  if (( mapH < mOutdoorWorldmapHSize ) && ( mapV < mOutdoorWorldmapVSize ) )\r
-  {\r
-    loc = mOutdoorBaseWorldId + mOutdoorWorldIdVIncrement * mapV + mapH;\r
-    if ( ! IsValidWorld( loc ) )\r
-      loc = 0;\r
-  }\r
-  return loc;\r
-}\r
-\r
-bool PWorlds::GetWorldmapFromWorldId( uint32_t nWorldId, uint8_t& mapH, uint8_t& mapV ) const\r
-{\r
-  if (( nWorldId >= mOutdoorBaseWorldId ) && ( nWorldId <= mOutdoorMaxWorldId ) )\r
-  {\r
-    mapV = ( nWorldId - mOutdoorBaseWorldId ) / mOutdoorWorldIdVIncrement;\r
-    mapH = ( nWorldId - mOutdoorBaseWorldId ) % mOutdoorWorldIdVIncrement;\r
-    return true;\r
-  }\r
-  return false;\r
-}\r
+#include <set>
+#include "GameServer/Includes.hxx"
+#include "GameServer/Definitions/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/**** PWorld ****/
+uint16_t const PWorld::mZoneOutLimitOffset = 0x100;
+uint16_t const PWorld::mBottomZoneOutLimit = 0x4800 - PWorld::mZoneOutLimitOffset;
+uint16_t const PWorld::mBottomZoneInLimit = 0x4a00;
+uint16_t const PWorld::mTopZoneOutLimit = 0xb200 + PWorld::mZoneOutLimitOffset;
+uint16_t const PWorld::mTopZoneInLimit = 0xb000;
+const std::string EmptyString;
+
+PWorld::PWorld()
+{
+  mID = 0;
+  mUseCount = 0;
+  mWorldDataTemplate = NULL;
+}
+
+PWorld::~PWorld()
+{
+}
+
+bool PWorld::Load( uint32_t nWorldID )
+{
+  std::string WorldTemplateName;
+  std::string tFileName;
+  bool tCheckOK;
+
+  if ( nWorldID > PWorlds::mAptBaseWorldId )
+  {
+    //int AptTmplID = Appartements->GetAptType(nWorldID - PWorlds::mAptBaseWorldId);
+    int AptTmplID = Appartements->GetAptType( nWorldID );
+    if ( !AptTmplID )
+    {
+      Console->Print( "%s PWorld::Load - invalid apt %d", Console->ColorText( RED, BLACK, "[WARNING]" ), nWorldID - PWorlds::mAptBaseWorldId );
+      return false;
+    }
+    const PDefAppartement* nAppDef = GameDefs->Appartements()->GetDef( AptTmplID );
+    if ( !nAppDef )
+    {
+      Console->Print( "%s PWorld::Load - invalid apt type %d", Console->ColorText( RED, BLACK, "[WARNING]" ), AptTmplID );
+      return false;
+    }
+    WorldTemplateName = nAppDef->GetWorldName();
+
+    tFileName = std::string( "worlds/" ) + WorldTemplateName + ".dat";
+    tCheckOK = Worlds->LeaseWorldDataTemplate( WorldTemplateName, tFileName );
+    if ( !tCheckOK )
+    {
+      tFileName = WorldTemplateName + ".dat";
+      tCheckOK = Worlds->LeaseWorldDataTemplate( WorldTemplateName, tFileName );
+    }
+    if ( !tCheckOK )
+    {
+      Console->Print( "%s PWorld::Load - unable to lease apt world %s (%s)", Console->ColorText( RED, BLACK, "[WARNING]" ), WorldTemplateName.c_str(), tFileName.c_str() );
+      return false;
+    }
+  }
+  else
+  {
+    const PDefWorldFile* nWorldFileDef;
+
+    if (( nWorldID > 90000 ) && ( nWorldID < 90017 ) ) // hardcoded holomatch hack
+    {
+      nWorldFileDef = NULL;
+      char worldName[19];
+      int MatchID = nWorldID - 90000;
+      if ( MatchID > 8 ) // to care for Neofrag 1 & 2
+        MatchID -= 8;
+      if ( MatchID > 6 )
+        MatchID = 6; // holomatch 7 and 8 are same as 6
+      snprintf( worldName, 19, "holomatch/neofrag%d", MatchID );
+      WorldTemplateName = worldName;
+    }
+    else
+    {
+      nWorldFileDef = GameDefs->WorldFiles()->GetDef( nWorldID );
+      if ( !nWorldFileDef )
+        return false;
+      WorldTemplateName = nWorldFileDef->GetName();
+    }
+
+    const PDefWorld* tWorldDef = GameDefs->Worlds()->GetDef( nWorldID );
+    if ( tWorldDef ) // should always be true here
+    {
+      if ( !( tWorldDef->GetDatFile().empty() ) )
+        tFileName = tWorldDef->GetDatFile();
+      else if ( nWorldFileDef )
+        tFileName = nWorldFileDef->GetBasicFileName() + ".dat";
+      else
+      {
+        tFileName = "worlds/";
+        tFileName += WorldTemplateName;
+        tFileName += ".dat";
+      }
+    }
+    else
+      return false; // should'nt happen here
+
+    if ( !Worlds->LeaseWorldDataTemplate( WorldTemplateName, tFileName ) )
+      return false;
+  }
+
+  mWorldDataTemplate = Worlds->GetWorldDataTemplate( tFileName );
+  if ( !mWorldDataTemplate )
+  {
+    Console->Print( "%s PWorld::Load : Unexpected world %d not found error", Console->ColorText( RED, BLACK, "[WARNING]" ), nWorldID );
+    return false;
+  }
+
+  mID = nWorldID;
+  mSpawnedVehicles.SetLocation( nWorldID );
+  // furniture & other world stuff loading here
+  Console->Print( "%s Loaded world %d", Console->ColorText( GREEN, BLACK, "[DEBUG]" ), nWorldID );
+  return true;
+}
+
+std::string PWorld::GetName()
+{
+    return ( mWorldDataTemplate ? mWorldDataTemplate->GetName() : EmptyString );
+}
+
+std::string PWorld::GetBspName()
+{
+    return ( mWorldDataTemplate ? mWorldDataTemplate->GetBspName() : EmptyString );
+}
+
+bool PWorld::IsAppartment()
+{
+    return mIsAppartment;
+}
+
+const PFurnitureItemTemplate *PWorld::GetFurnitureItemTemplate( uint32_t nItemID )
+{
+    return ( mWorldDataTemplate ? mWorldDataTemplate->GetFurnitureItem( nItemID ) : NULL ) ;
+}
+
+const PDefWorldModel *PWorld::GetFurnitureItemModel(uint32_t nItemID)
+{
+  if ( mWorldDataTemplate )
+  {
+    const PFurnitureItemTemplate* tFurniture = mWorldDataTemplate->GetFurnitureItem( nItemID );
+    if ( tFurniture )
+      return tFurniture->GetDefWorldModel();
+  }
+  return nullptr;
+}
+
+const PDoorTemplate *PWorld::GetDoor(uint32_t nDoorID)
+{
+    return (mWorldDataTemplate ? mWorldDataTemplate->GetDoor(nDoorID) : nullptr);
+}
+
+bool PWorld::getPositionItemPosition(uint8_t PosID, float *pX, float *pY, float *pZ)
+{
+    return (mWorldDataTemplate ? mWorldDataTemplate->getPositionItemPosition(PosID, pX, pY, pZ) : false);
+}
+
+bool PWorld::CharUseChair( int CharLocalID, uint32_t nItemID )
+{
+  PChairsInUseMap::iterator it = mChairsInUseMap.find( nItemID );
+  if ( it == mChairsInUseMap.end() ) // chair is free
+  {
+    if ( gDevDebug )
+      Console->Print( "%s Localchar %d now using free chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID );
+    mChairsInUseMap.insert( std::make_pair( nItemID, CharLocalID ) );
+    return true;
+  }
+  else // chair is already in use
+  {
+    if ( gDevDebug )
+    {
+      if ( it->second == CharLocalID )
+      {
+        Console->Print( "%s Localchar %d already using chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID );
+      }
+      else
+      {
+        Console->Print( "%s Localchar %d can't sit on chair %d used by localchar %d", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID, it->second );
+      }
+    }
+    return ( it->second == CharLocalID );
+  }
+}
+
+void PWorld::CharLeaveChair( int CharLocalID, uint32_t nItemID )
+{
+  PChairsInUseMap::iterator it = mChairsInUseMap.find( nItemID );
+  if (( it != mChairsInUseMap.end() ) && ( it->second == CharLocalID ) ) // chair is in use by this char
+  {
+    if ( gDevDebug )
+      Console->Print( "%s Localchar %d leaving chair %d.", Console->ColorText( CYAN, BLACK, "[DEBUG]" ), CharLocalID, nItemID );
+    mChairsInUseMap.erase( it );
+  }
+}
+
+PClient* PWorld::GetClientByCharLocalId( uint32_t rawObjectId ) const
+{
+  // Temp implementation
+  return ClientManager->GetClientByCharLocalId( rawObjectId, mID );
+}
+
+PSpawnedVehicles *PWorld::GetSpawnedVehicles()
+{
+    return &mSpawnedVehicles;
+}
+
+bool PWorld::CheckVhcNeedZoning( PVhcCoordinates const* nPos ) const
+{
+  if ( ( nPos->GetX() <= mBottomZoneOutLimit ) || ( nPos->GetX() >= mTopZoneOutLimit ) || ( nPos->GetY() <= mBottomZoneOutLimit )   || ( nPos->GetY() >= mTopZoneOutLimit ) )
+    return true;
+  else
+    return false;
+}
+
+uint32_t PWorld::GetVhcZoningDestination( PSpawnedVehicle const* nVhc, PVhcCoordinates* nPos ) const
+{
+  uint32_t destWorldId = 0;
+  int16_t vChange = 0;
+  int16_t hChange = 0;
+  PVhcCoordinates const vhcPos = nVhc->GetPosition();
+  uint16_t posX = vhcPos.GetX();
+  uint16_t posY = vhcPos.GetY();
+
+  if ( posX <= mBottomZoneOutLimit )
+  {
+    vChange = 1;
+  }
+  else if ( posX >= mTopZoneOutLimit )
+  {
+    vChange = -1;
+  }
+
+  if ( posY <= mBottomZoneOutLimit )
+  {
+    hChange = -1;
+  }
+  else if ( posY >= mTopZoneOutLimit )
+  {
+    hChange = 1;
+  }
+
+  if ( vChange || hChange )
+  {
+    //Console->Print( YELLOW, BLACK, "[DEBUG] Limit Reached V:%d H:%d mapId:%d", vChange,hChange,mID );
+    uint8_t currH = 0;
+    uint8_t currV = 0;
+    int16_t newH, newV;
+
+    if ( Worlds->GetWorldmapFromWorldId( mID, currH, currV ) )
+    {
+      //Console->Print( YELLOW, BLACK, "[DEBUG] current map pos V:%d H:%d", currV,currH );
+      newH = currH + hChange;
+      if ( newH < 0 )
+        newH = 0;
+      else if ( newH >= PWorlds::mOutdoorWorldmapHSize )
+        newH = PWorlds::mOutdoorWorldmapHSize;
+
+      newV = currV + vChange;
+      if ( newV < 0 )
+        newV = 0;
+      else if ( newV >= PWorlds::mOutdoorWorldmapHSize )
+        newV = PWorlds::mOutdoorWorldmapHSize;
+
+      //Console->Print( YELLOW, BLACK, "[DEBUG] new map pos V:%d H:%d", newV,newH );
+      if (( newH != currH ) || ( newV != currV ) )
+      {
+        destWorldId = Worlds->GetWorldIdFromWorldmap( newH, newV );
+
+        if ( destWorldId && nPos )
+        {
+          if ( vChange == 1 )
+            posX = mTopZoneInLimit;
+          else if ( vChange == -1 )
+            posX = mBottomZoneInLimit;
+
+          if ( hChange == -1 )
+            posY = mTopZoneInLimit;
+          else if ( hChange == 1 )
+            posY = mBottomZoneInLimit;
+
+          nPos->SetPosition( posY, vhcPos.GetZ(), posX, vhcPos.GetUD(), vhcPos.GetLR(), vhcPos.GetRoll(), vhcPos.GetAct(), vhcPos.GetUnknown(), vhcPos.GetFF() );
+        }
+      }
+    }
+  }
+
+  return destWorldId;
+}
+
+const PNPCsMap *PWorld::GetNPCMap() const
+{
+    return (mWorldDataTemplate ? mWorldDataTemplate->GetNPCMap() : nullptr);
+}
+
+const PNPCTemplate *PWorld::GetNPCTemplate(uint32_t nNPCID) const
+{
+    return (mWorldDataTemplate ? mWorldDataTemplate->GetNPC(nNPCID) : nullptr);
+}
+
+/**** PWorlds ****/
+uint32_t const PWorlds::mNcSubwayWorldId = 1000;
+uint32_t const PWorlds::mAptBaseWorldId = 100000;
+uint32_t const PWorlds::mOutdoorBaseWorldId = 2001;
+uint32_t const PWorlds::mOutdoorWorldIdVIncrement = 20;
+uint8_t const PWorlds::mOutdoorWorldmapHSize = 16;
+uint8_t const PWorlds::mOutdoorWorldmapVSize = 11;
+uint32_t const PWorlds::mOutdoorMaxWorldId = PWorlds::mOutdoorBaseWorldId + PWorlds::mOutdoorWorldIdVIncrement * ( PWorlds::mOutdoorWorldmapVSize - 1 ) + PWorlds::mOutdoorWorldmapHSize - 1;
+
+PWorlds::PWorlds()
+{
+  mPreloadWorldsTemplates = false; // to be put as config option
+  mPreloadStaticWorlds = false; // to be put as config option
+}
+
+PWorlds::~PWorlds()
+{
+  for ( PWorldsMap::iterator i = mStaticWorldsMap.begin(); i != mStaticWorldsMap.end(); i++ )
+    if ( i->second )
+    {
+      delete i->second;
+    }
+  for ( PWorldsMap::iterator i = mOnDemandWorldsMap.begin(); i != mOnDemandWorldsMap.end(); i++ )
+    if ( i->second )
+    {
+      delete i->second;
+    }
+  for ( PWorldDataTemplatesMap::iterator i = mWorldDataTemplatesMap.begin(); i != mWorldDataTemplatesMap.end(); i++ )
+    if ( i->second )
+    {
+      delete i->second;
+    }
+}
+
+bool PWorlds::LeaseWorldDataTemplate( const std::string& nBspName, const std::string& nFileName, const bool nPreloadPhase )
+{
+  PWorldDataTemplate* tWorldDataTemplate;
+
+  PWorldDataTemplatesMap::iterator it = mWorldDataTemplatesMap.find( nFileName );
+  if ( it == mWorldDataTemplatesMap.end() ) // template unkown yet
+  {
+    if ( nPreloadPhase ) // if in preload phase, we try to load it or make it known
+    {
+      tWorldDataTemplate = new PWorldDataTemplate;
+      if ( tWorldDataTemplate->LoadDatFile( nBspName, nFileName, !mPreloadWorldsTemplates ) )
+      {
+        if ( mPreloadWorldsTemplates )
+        {
+          mWorldDataTemplatesMap.insert( std::make_pair( nFileName, tWorldDataTemplate ) );
+          tWorldDataTemplate->IncreaseUseCount();
+        }
+        else
+        {
+          mWorldDataTemplatesMap.insert( std::make_pair( nFileName, ( PWorldDataTemplate* )NULL ) ); // NULL means file access OK but not preloaded yet
+          delete tWorldDataTemplate;
+        }
+        //return true;
+      }
+      else
+      {
+        delete tWorldDataTemplate;
+        return false;
+      }
+    }
+    else
+    {
+      return false;
+    }
+  }
+  else // template already known
+  {
+    if ( !it->second  &&  !nPreloadPhase ) // template known but not already loaded and not in preload ?
+    {
+      tWorldDataTemplate = new PWorldDataTemplate;
+      if ( tWorldDataTemplate->LoadDatFile( nBspName, nFileName ) )
+      {
+        it->second = tWorldDataTemplate;
+      }
+      else
+      {
+        Console->Print( "%s Invalid world data template file %s", Console->ColorText( RED, BLACK, "[ERROR]" ), nFileName.c_str() );
+        mWorldDataTemplatesMap.erase( it );
+        delete tWorldDataTemplate;
+        return false;
+      }
+    }
+
+    if ( !nPreloadPhase )
+      it->second->IncreaseUseCount();
+
+    //return true;
+  }
+
+  return true;
+}
+
+void PWorlds::ReleaseWorldDataTemplate( const std::string& nFileName )
+{
+  PWorldDataTemplatesMap::iterator it = mWorldDataTemplatesMap.find( nFileName );
+  if (( it != mWorldDataTemplatesMap.end() ) && it->second )
+  {
+    it->second->DecreaseUseCount();
+  }
+  else
+    Console->Print( "%s PWorlds::ReleaseWorldDataTemplate : try to relese not loaded template %s", Console->ColorText( RED, BLACK, "[Warning]" ), nFileName.c_str() );
+}
+
+void PWorlds::UnloadWorldDataTemplate( const std::string& nFileName )
+{
+  PWorldDataTemplate* tWorldDataTemplate;
+
+  PWorldDataTemplatesMap::iterator it = mWorldDataTemplatesMap.find( nFileName );
+  if (( it != mWorldDataTemplatesMap.end() ) && it->second )
+  {
+    tWorldDataTemplate = it->second;
+    if ( mPreloadWorldsTemplates || ( tWorldDataTemplate->GetUseCount() > 0 ) )
+      Console->Print( "%s PWorlds::UnloadWorldDataTemplate : attempt to unload template %s when use count not null ou preload set", Console->ColorText( RED, BLACK, "[Warning]" ), nFileName.c_str() );
+    else
+    {
+      it->second = ( PWorldDataTemplate* )NULL;
+      delete tWorldDataTemplate;
+    }
+  }
+  else
+    Console->Print( "%s PWorlds::UnloadWorldDataTemplate : attempt to release not loaded template %s", Console->ColorText( RED, BLACK, "[Warning]" ), nFileName.c_str() );
+}
+
+PWorldDataTemplate* PWorlds::GetWorldDataTemplate( const std::string& nFileName )
+{
+  PWorldDataTemplatesMap::const_iterator it = mWorldDataTemplatesMap.find( nFileName );
+  if ( it != mWorldDataTemplatesMap.end() )
+    return it->second;
+  else
+    return NULL;
+}
+
+bool PWorlds::LoadWorlds() // once Load is done, only WorldDataTemplate registred in mWorldDataTemplatesMap
+{
+  //   will be considered as valid
+  std::string tFileName;
+  std::string tBspName;
+  const PDefWorld* tDefWorld;
+  bool tCheckOK;
+  int ValidCount = 0, InvalidCount = 0, DblInvCount = 0;
+  int DatTmplCount, BadDatTmplCount;
+  std::set<std::string>
+  InvalideFiles;
+
+  // Appartment templates checking or preloading
+  std::map<int, PDefAppartement*>::const_iterator itAptStart = GameDefs->Appartements()->ConstIteratorBegin();
+  std::map<int, PDefAppartement*>::const_iterator itAptEnd = GameDefs->Appartements()->ConstIteratorEnd();
+  for ( std::map<int, PDefAppartement*>::const_iterator i = itAptStart; i != itAptEnd; i++ )
+  {
+    tCheckOK = false;
+    tBspName = i->second->GetWorldName();
+    tFileName = std::string( "worlds/" ) + tBspName + ".dat";
+    if ( !InvalideFiles.count( tFileName ) )
+    {
+      tCheckOK = LeaseWorldDataTemplate( tBspName, tFileName, true );
+      if ( !tCheckOK )
+      {
+        InvalideFiles.insert( tFileName );
+        if ( gDevDebug )
+          Console->Print( RED, BLACK, "Template file %s invalid", tFileName.c_str() );
+      }
+    }
+    if ( !tCheckOK ) // in case full path was given without omiting worlds/ or in another dir/archive ...
+    {
+      tFileName = tBspName + ".dat";
+      if ( !InvalideFiles.count( tFileName ) )
+      {
+        tCheckOK = LeaseWorldDataTemplate( tBspName, tFileName, true );
+        if ( !tCheckOK )
+        {
+          InvalideFiles.insert( tFileName );
+          ++DblInvCount;
+        }
+      }
+    }
+
+    if ( tCheckOK )
+    {
+      ++ValidCount;
+      if ( gDevDebug )
+        Console->Print( GREEN, BLACK, "Template file %s for appartment %d (%s) loaded", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );
+    }
+    else
+    {
+      ++InvalidCount;
+      if ( gDevDebug )
+        Console->Print( RED, BLACK, "Template file %s for appartment %d (%s) not available or invalid", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );
+    }
+  }
+
+  DatTmplCount = mWorldDataTemplatesMap.size();
+  BadDatTmplCount = InvalideFiles.size();
+  Console->Print( "%s %d valid appartement templates checked (%d dat files)", Console->ColorText( GREEN, BLACK, "[Success]" ), ValidCount, DatTmplCount );
+  if ( InvalidCount )
+    Console->Print( "%s %d invalid appartement templates rejected (%d dat files)", Console->ColorText( YELLOW, BLACK, "[Notice]" ), InvalidCount, BadDatTmplCount - DblInvCount );
+
+  // Static worlds & static worlds templates checking or preloading
+  ValidCount = InvalidCount = 0;
+  const PDefWorldFile* tDefWorldFile;
+  std::map<int, PDefWorldFile*>::const_iterator itFilStart = GameDefs->WorldFiles()->ConstIteratorBegin();
+  std::map<int, PDefWorldFile*>::const_iterator itFilEnd = GameDefs->WorldFiles()->ConstIteratorEnd();
+  for ( std::map<int, PDefWorldFile*>::const_iterator i = itFilStart; i != itFilEnd; i++ )
+  {
+    tDefWorldFile = i->second;
+
+    tDefWorld = GameDefs->Worlds()->GetDef( tDefWorldFile->GetIndex() );
+    if ( tDefWorld ) // we only care for worlds that are present in worldinfo.def too
+    {
+      tBspName = tDefWorldFile->GetName();
+      if ( !( tDefWorld->GetDatFile().empty() ) )
+        tFileName = tDefWorld->GetDatFile();
+      else
+        tFileName = i->second->GetBasicFileName() + ".dat";
+
+      tCheckOK = false;
+      if ( !InvalideFiles.count( tFileName ) )
+      {
+        tCheckOK = LeaseWorldDataTemplate( tBspName, tFileName, true );
+        if ( !tCheckOK )
+        {
+          InvalideFiles.insert( tFileName );
+          if ( gDevDebug )
+            Console->Print( RED, BLACK, "Template file %s invalid", tFileName.c_str() );
+        }
+      }
+
+      if ( tCheckOK )
+      {
+        ++ValidCount;
+        if ( mPreloadStaticWorlds )
+        {
+          LeaseWorld( tDefWorldFile->GetIndex(), true ); // This will make the world ready and kept in mem (use count always >0 )
+        }
+        else
+        {
+          mStaticWorldsMap.insert( std::make_pair( tDefWorldFile->GetIndex(), ( PWorld* )NULL ) );
+        }
+        if ( gDevDebug )
+          Console->Print( GREEN, BLACK, "Template file %s for world %d (%s) loaded", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );
+      }
+      else
+      {
+        ++InvalidCount;
+        if ( gDevDebug )
+          Console->Print( RED, BLACK, "Template file %s for world %d (%s) not available or invalid", tFileName.c_str(), i->second->GetIndex(), i->second->GetName().c_str() );
+      }
+    }
+  }
+
+  // Hardcoded neofrag worlds ... oO ... and neofrag4.dat can't be found :-/
+  for ( int i = 1; i <= 16; i++ )
+  {
+    char worldName[19];
+    int MatchID = i;
+    if ( MatchID > 8 ) // to care for Neofrag 1 & 2
+      MatchID -= 8;
+    if ( MatchID > 6 )
+      MatchID = 6; // holomatch 7 and 8 are same as 6
+    snprintf( worldName, 19, "holomatch/neofrag%d", MatchID );
+
+    tDefWorld = GameDefs->Worlds()->GetDef( 90000 + i );
+    if ( tDefWorld ) // we only care for worlds that are present in worldinfo.def too
+    {
+      if ( !( tDefWorld->GetDatFile().empty() ) )
+        tFileName = tDefWorld->GetDatFile();
+      else
+      {
+        tFileName = "worlds/";
+        tFileName += worldName;
+        tFileName += ".dat";
+      }
+
+      tCheckOK = false;
+      if ( !InvalideFiles.count( tFileName ) )
+      {
+        tCheckOK = LeaseWorldDataTemplate( worldName, tFileName, true );
+        if ( !tCheckOK )
+        {
+          InvalideFiles.insert( tFileName );
+          if ( gDevDebug )
+            Console->Print( RED, BLACK, "Template file %s invalid", tFileName.c_str() );
+        }
+      }
+
+      if ( tCheckOK )
+      {
+        ++ValidCount;
+        if ( mPreloadStaticWorlds )
+        {
+          LeaseWorld( 90000 + i, true ); // This will make the world ready and kept in mem (use count always >0 )
+        }
+        else
+        {
+          mStaticWorldsMap.insert( std::make_pair( 90000 + i, ( PWorld* )NULL ) );
+        }
+        if ( gDevDebug )
+          Console->Print( GREEN, BLACK, "Template file %s for world %d (%s) loaded", tFileName.c_str(), 90000 + i, worldName );
+      }
+      else
+      {
+        ++InvalidCount;
+        if ( gDevDebug )
+          Console->Print( RED, BLACK, "Template file %s for world %d (%s) not available or invalid", tFileName.c_str(), 90000 + i, worldName );
+      }
+    }
+  }
+
+  Console->Print( "%s %d valid world templates checked (%d dat files)", Console->ColorText( GREEN, BLACK, "[Success]" ), ValidCount, mWorldDataTemplatesMap.size() - DatTmplCount );
+  if ( InvalidCount )
+    Console->Print( "%s %d invalid world templates rejected (%d dat files)", Console->ColorText( YELLOW, BLACK, "[Notice]" ), InvalidCount, InvalideFiles.size() - BadDatTmplCount - DblInvCount );
+  Console->Print( "%s %d static worlds prepared", Console->ColorText( GREEN, BLACK, "[Success]" ), mStaticWorldsMap.size() );
+
+  // release memory if World templates preload activated, this cache that won't be used anymore
+  // if (mPreloadWorldsTemplates) Filesystem->ClearCache();
+
+  return true;
+}
+
+bool PWorlds::IsValidWorld( uint32_t nWorldID ) const
+{
+  if ( nWorldID > PWorlds::mAptBaseWorldId )
+  {
+    if ( mOnDemandWorldsMap.count( nWorldID ) ) // Check if already loaded
+      return true;
+    else //should better do a check using a PAppartements class object to get the world template
+    {
+      //int AptTmplID = Appartements->GetAptType(nWorldID - PWorlds::mAptBaseWorldId);
+      int AptTmplID = Appartements->GetAptType( nWorldID );
+      if ( !AptTmplID )
+        return false;
+
+      const PDefAppartement* nAppDef = GameDefs->Appartements()->GetDef( AptTmplID );
+      if ( !nAppDef )
+        return false;
+
+      std::string tFileName = "worlds/" + nAppDef->GetWorldName() + ".dat";
+      PWorldDataTemplatesMap::const_iterator it = mWorldDataTemplatesMap.find( tFileName );
+      return ( it != mWorldDataTemplatesMap.end() );
+    }
+  }
+  else
+  {
+    if ( gDevDebug )
+      Console->Print( "%s Checking validity for world %d : %s", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID, mStaticWorldsMap.count( nWorldID ) ? "OK" : "BAD" );
+    return ( mStaticWorldsMap.count( nWorldID ) );
+  }
+}
+
+PWorld* PWorlds::LeaseWorld( uint32_t nWorldID, const bool nPreloadPhase )
+{
+  PWorldsMap::iterator it;
+
+  if ( nWorldID > PWorlds::mAptBaseWorldId )
+  {
+    it = mOnDemandWorldsMap.find( nWorldID ); // Check if already loaded
+    if (( it != mOnDemandWorldsMap.end() ) && it->second ) // Dynamic world shall not have a NULL it->second
+    {
+      // if loaded
+      it->second->IncreaseUseCount();
+      if ( gDevDebug )
+        Console->Print( "%s Leased world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );
+      return it->second;
+    }
+    else // not loaded yet or invalid
+    {
+      PWorld* nWorld = new PWorld;
+      if ( ! nWorld->Load( nWorldID ) ) // Error when loading (shouldn't happen)
+      {
+        delete nWorld;
+        Console->Print( "% Could not load world %d - World now set as invalid", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );
+        return NULL;
+      }
+      else
+      {
+        mOnDemandWorldsMap.insert( std::make_pair( nWorldID, nWorld ) );
+        nWorld->IncreaseUseCount();
+        if ( gDevDebug )
+          Console->Print( "%s Leased world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );
+        return nWorld;
+      }
+    }
+  }
+  else
+  {
+    it = mStaticWorldsMap.find( nWorldID ); // Check if already loaded
+    if (( it == mStaticWorldsMap.end() ) && nPreloadPhase )
+    {
+      mStaticWorldsMap.insert( std::make_pair( nWorldID, ( PWorld* )NULL ) );
+      it = mStaticWorldsMap.find( nWorldID );
+    }
+    if ( it != mStaticWorldsMap.end() )
+    {
+      // if valid
+      if ( ! it->second ) // if not loaded yet
+      {
+        it->second = new PWorld;
+        if ( ! it->second->Load( nWorldID ) ) // Error when loading (shouldn't happen)
+        {
+          delete it->second;
+          Console->Print( "%s Could not load world %d - World now set as invalid", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );
+          mStaticWorldsMap.erase( it ); // remove from valid worlds map
+          return NULL;
+        }
+      }
+      it->second->IncreaseUseCount();
+      if ( gDevDebug )
+        Console->Print( "%s Leased world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );
+      return it->second;
+    }
+    else // invalid worldID
+    {
+      return NULL;
+    }
+  }
+}
+
+PWorld* PWorlds::GetWorld( uint32_t nWorldID )
+{
+  PWorldsMap* tMap;
+  PWorldsMap::iterator it;
+
+  tMap = (( nWorldID > PWorlds::mAptBaseWorldId ) ? &mOnDemandWorldsMap : &mStaticWorldsMap );
+
+  it = tMap->find( nWorldID );
+  if (( it != tMap->end() ) && it->second )
+  {
+    return it->second;
+  }
+  else
+  {
+    Console->Print( "%s PWorlds::GetWorld : Trying to get world %d without lease !", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );
+    return NULL;
+  }
+}
+
+void PWorlds::ReleaseWorld( uint32_t nWorldID ) // no dynamic unload is performed atm + don't forget spawned vhc !
+{
+  PWorld* tWorld = GetWorld( nWorldID );
+  if ( tWorld )
+  {
+    if ( tWorld->GetUseCount() ) // this check is for dev time only
+    {
+      tWorld->DecreaseUseCount();
+      if ( gDevDebug )
+        Console->Print( "%s Released world %d", Console->ColorText( GREEN, BLACK, "[Debug]" ), nWorldID );
+    }
+    else
+    {
+      Console->Print( "%s PWorlds::ReleaseWorld : Trying to release world %d with use count 0 !", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );
+    }
+  }
+  else
+  {
+    Console->Print( "%s PWorlds::ReleaseWorld : Generated the invalid get world %d", Console->ColorText( RED, BLACK, "[Warning]" ), nWorldID );
+  }
+}
+
+bool PWorlds::IsAppartment( uint32_t nWorldID )
+{
+  return (( nWorldID > PWorlds::mAptBaseWorldId ) && IsValidWorld( nWorldID ) );
+}
+
+void PWorlds::Update()
+{}
+
+void PWorlds::Shutdown()
+{}
+
+uint32_t PWorlds::GetWorldIdFromWorldmap( uint8_t mapH, uint8_t mapV ) const
+{
+  uint32_t loc = 0;
+  if (( mapH < mOutdoorWorldmapHSize ) && ( mapV < mOutdoorWorldmapVSize ) )
+  {
+    loc = mOutdoorBaseWorldId + mOutdoorWorldIdVIncrement * mapV + mapH;
+    if ( ! IsValidWorld( loc ) )
+      loc = 0;
+  }
+  return loc;
+}
+
+bool PWorlds::GetWorldmapFromWorldId( uint32_t nWorldId, uint8_t& mapH, uint8_t& mapV ) const
+{
+  if (( nWorldId >= mOutdoorBaseWorldId ) && ( nWorldId <= mOutdoorMaxWorldId ) )
+  {
+    mapV = ( nWorldId - mOutdoorBaseWorldId ) / mOutdoorWorldIdVIncrement;
+    mapH = ( nWorldId - mOutdoorBaseWorldId ) % mOutdoorWorldIdVIncrement;
+    return true;
+  }
+  return false;
+}
index 8f35f74..14923d9 100644 (file)
@@ -1,36 +1,36 @@
-#include "GameServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-// TODO: Put get the fallback world from config\r
-//       Check for file existence before sending info to client to avoid client crash and bad location in char info\r
-\r
-void SendZone(PClient *Client, uint32_t loc)\r
-{\r
-    //TODO : FIX case for worldroute and 5 missing id 505\r
-  std::string worldName;\r
-    ConnectionTCP *Socket = Client->getTCPConn();\r
-    //PChar *Char = Chars->GetChar(Client->GetCharID());\r
-\r
-    Socket->SetTimeOutValue(0xffff);\r
-\r
-  PWorld* CurrentWorld = Worlds->GetWorld(loc);\r
-  if (CurrentWorld)\r
-  {\r
-    worldName = CurrentWorld->GetBspName();\r
-    if (worldName.empty())\r
-    {\r
-      worldName = "plaza/plaza_p1"; // Should be a config entry\r
-      Console->Print("Client %d: Empty name for world %d. Redirecting to %s", Console->ColorText(RED, BLACK, "Warning"), Client->GetID(), loc, worldName.c_str());\r
-      loc = 1;\r
-    }\r
-  }\r
-  else\r
-  {\r
-    worldName = "plaza/plaza_p1"; // Should be a config entry\r
-    Console->Print("Client %d: Invalid or not loaded world %d. Redirecting to %s", Console->ColorText(YELLOW, BLACK, "Warning"), Client->GetID(), loc, worldName.c_str());\r
-    loc = 1;\r
-  }\r
-\r
-  PMessage* cMsg = MsgBuilder->BuildSendZoneTCPMsg(loc, &worldName);\r
-    Client->SendTCPMessage(cMsg);\r
-}\r
+#include "GameServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+// TODO: Put get the fallback world from config
+//       Check for file existence before sending info to client to avoid client crash and bad location in char info
+
+void SendZone(PClient *Client, uint32_t loc)
+{
+    //TODO : FIX case for worldroute and 5 missing id 505
+  std::string worldName;
+    ConnectionTCP *Socket = Client->getTCPConn();
+    //PChar *Char = Chars->GetChar(Client->GetCharID());
+
+    Socket->SetTimeOutValue(0xffff);
+
+  PWorld* CurrentWorld = Worlds->GetWorld(loc);
+  if (CurrentWorld)
+  {
+    worldName = CurrentWorld->GetBspName();
+    if (worldName.empty())
+    {
+      worldName = "plaza/plaza_p1"; // Should be a config entry
+      Console->Print("Client %d: Empty name for world %d. Redirecting to %s", Console->ColorText(RED, BLACK, "Warning"), Client->GetID(), loc, worldName.c_str());
+      loc = 1;
+    }
+  }
+  else
+  {
+    worldName = "plaza/plaza_p1"; // Should be a config entry
+    Console->Print("Client %d: Invalid or not loaded world %d. Redirecting to %s", Console->ColorText(YELLOW, BLACK, "Warning"), Client->GetID(), loc, worldName.c_str());
+    loc = 1;
+  }
+
+  PMessage* cMsg = MsgBuilder->BuildSendZoneTCPMsg(loc, &worldName);
+    Client->SendTCPMessage(cMsg);
+}
index 6f6950c..c006087 100644 (file)
@@ -1,8 +1,8 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class PClient;\r
-\r
-//void SendZone(PClient *Client, PGameState *State,int loc);\r
-void SendZone(PClient *Client, uint32_t loc);\r
+#pragma once
+
+#include <cstdint>
+
+class PClient;
+
+//void SendZone(PClient *Client, PGameState *State,int loc);
+void SendZone(PClient *Client, uint32_t loc);
index 9872c0c..ee05c3d 100644 (file)
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-/*\r
-NOTE ABOUT ACCESS LEVELS IN THE MYSQL DATABASE:\r
-a_priv:\r
-0 = unregistered user\r
-1 = Registered user\r
-30 = volunteer\r
-50 = GM\r
-100 = Admin\r
-\r
-a_status:\r
-0 = Offline\r
-1 = Online\r
-2 = Banned\r
-*/\r
-\r
-/** Static members **/\r
-RegEx* PAccount::mUsernameRegexFilter = nullptr;\r
-RegEx* PAccount::mPasswordRegexFilter = nullptr;\r
-\r
-bool PAccount::SetUsernameRegexFilter(const char* RegexStr)\r
-{\r
-  if(mUsernameRegexFilter)\r
-  {\r
-    delete mUsernameRegexFilter;\r
-    mUsernameRegexFilter = NULL;\r
-  }\r
-\r
-  if(RegexStr)\r
-  {\r
-    try {\r
-      mUsernameRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);\r
-    }\r
-    catch (...) {\r
-      return false;\r
-    }\r
-  }\r
-  return true;\r
-}\r
-\r
-bool PAccount::SetPasswordRegexFilter(const char* RegexStr)\r
-{\r
-  if(mPasswordRegexFilter)\r
-  {\r
-    delete mPasswordRegexFilter;\r
-    mPasswordRegexFilter = NULL;\r
-  }\r
-\r
-  if(RegexStr)\r
-  {\r
-    try {\r
-      mPasswordRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);\r
-    }\r
-    catch (...) {\r
-      return false;\r
-    }\r
-  }\r
-  return true;\r
-}\r
-\r
-bool PAccount::IsUsernameWellFormed(const char *Username)\r
-{\r
-  if(mUsernameRegexFilter)\r
-  {\r
-    return mUsernameRegexFilter->Search(Username);\r
-  }\r
-  else\r
-    return true;\r
-}\r
-\r
-bool PAccount::IsPasswordWellFormed(const char *Password)\r
-{\r
-  if(mPasswordRegexFilter)\r
-  {\r
-    return mPasswordRegexFilter->Search(Password);\r
-  }\r
-  else\r
-    return true;\r
-}\r
-\r
-/** Instance members **/\r
-PAccount::PAccount()\r
-{\r
-    mID = 0;\r
-    mLevel = PAL_BANNED;\r
-  mStatus = PAS_OFFLINE;\r
-  mBannedUntil = 0;\r
-}\r
-\r
-PAccount::PAccount(const uint32_t AccountId)\r
-{\r
-  char query[256];\r
-  mID = 0;\r
-  snprintf(query, 256, "SELECT * FROM accounts WHERE a_id = %d LIMIT 1;", AccountId);\r
-  LoadFromQuery(query);\r
-}\r
-\r
-PAccount::PAccount(const char *Username)\r
-{\r
-  char query[256];\r
-  mID = 0;\r
-  if(IsUsernameWellFormed(Username)) {\r
-    char escUsername[256];\r
-    MySQL->EscapeString(Username, escUsername, 256);\r
-    snprintf(query, 256, "SELECT * FROM accounts WHERE a_username = '%s' LIMIT 1;", escUsername);\r
-    LoadFromQuery(query);\r
-  }\r
-}\r
-\r
-bool PAccount::LoadFromQuery(char* query)\r
-{\r
-  MYSQL_ROW row = 0;\r
-  MYSQL_RES *result = 0;\r
-\r
-  bool FinalResult = false;\r
-\r
-  //result = MySQL->InfoResQuery(query);\r
-  result = MySQL->ResQuery(query);\r
-  if(result == NULL)\r
-  {\r
-      Console->Print(RED, BLACK, "Failed to load AccountData from SQL");\r
-      //MySQL->ShowInfoSQLError();\r
-      MySQL->ShowSQLError();\r
-      return false;\r
-  }\r
-\r
-  if((row = mysql_fetch_row(result)))\r
-  {\r
-    mID = atoi(row[a_id]);\r
-    mName = row[a_username];\r
-    mPassword = row[a_password];\r
-\r
-    mBannedUntil = atoi(row[a_bandate]);\r
-    if(mBannedUntil > std::time(NULL))\r
-    {\r
-      mStatus = PAS_BANNED;\r
-      mLevel = PAL_BANNED;\r
-    }\r
-    else\r
-    {\r
-      mStatus = PAS_OFFLINE;\r
-      mLevel = atoi(row[a_priv]);\r
-    }\r
-\r
-    FinalResult = true;\r
-  }\r
-  else\r
-  {\r
-Console->Print(YELLOW, BLACK, "Failed to load AccountData from SQL; Nothing to load...");\r
-  }\r
-\r
-  //MySQL->FreeInfoSQLResult(result);\r
-  MySQL->FreeSQLResult(result);\r
-  return FinalResult;\r
-}\r
-\r
-uint32_t PAccount::GetID() const\r
-{\r
-    return mID;\r
-}\r
-\r
-bool PAccount::SetName(const std::string &Username)\r
-{\r
-  if(IsUsernameWellFormed(Username.c_str()))\r
-  {\r
-    mName = Username;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-const std::string &PAccount::GetName() const\r
-{\r
-    return mName;\r
-}\r
-\r
-bool PAccount::SetPassword(const std::string &Password)\r
-{\r
-  if(IsPasswordWellFormed(Password.c_str()))\r
-  {\r
-    mPassword = Password;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::SetPasswordEncoded(const uint8_t* PasswordData, int PassLen, const uint8_t* Key)\r
-{\r
-    char Pass[128];\r
-\r
-    if(DecodePassword(PasswordData, PassLen, Key, Pass))\r
-  {\r
-        return SetPassword((std::string)Pass);\r
-    }\r
-    else\r
-    {\r
-        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);\r
-        return false;\r
-    }\r
-}\r
-\r
-const std::string &PAccount::GetPassword() const\r
-{\r
-    return mPassword;\r
-}\r
-\r
-bool PAccount::SetLevel(int newLevel)\r
-{\r
-  if((newLevel >= PAL_BANNED) && (newLevel <= PAL_ADMIN))\r
-  {\r
-    mLevel = newLevel;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-int32_t PAccount::GetLevel() const\r
-{\r
-    return mLevel;\r
-}\r
-\r
-std::string PAccount::GetLevelString() const\r
-{\r
-    switch(mLevel)\r
-    {\r
-        case PAL_BANNED : return "banned";\r
-        case PAL_UNREGPLAYER : return "unregplayer";\r
-        case PAL_REGPLAYER : return "regplayer";\r
-        case PAL_VOLUNTEER : return "volunteer";\r
-        case PAL_GM : return "gm";\r
-        case PAL_ADMIN : return "admin";\r
-    }\r
-\r
-    return "custom";\r
-}\r
-\r
-bool PAccount::SetStatus(PAccountStatus Status)\r
-{\r
-  mStatus = Status;\r
-  return true;\r
-}\r
-\r
-PAccountStatus PAccount::GetStatus() const\r
-{\r
-    return mStatus;\r
-}\r
-\r
-bool PAccount::SetBannedUntilTime(std::time_t BannedUntil)\r
-{\r
-  if ((BannedUntil == 0) || (BannedUntil > std::time(NULL)))\r
-  {\r
-    mBannedUntil = BannedUntil;\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::IsBanned() const\r
-{\r
-    return (mBannedUntil > std::time(nullptr));\r
-}\r
-\r
-bool PAccount::DecodePassword(const uint8_t* PasswordData, int PassLen, const uint8_t *Key, char* ClearPassword)\r
-{\r
-  ClearPassword[0] = 0;\r
-\r
-  if(PassLen < 128)\r
-    {\r
-        if(Key[0]>7) // TODO: >7 correct?\r
-        {\r
-            for(int i=0; i<PassLen; i+=2)\r
-                ClearPassword[i>>1] = (char)(((PasswordData[i]&0xf0)>>4)\r
-                    +((PasswordData[i+1]&0x0f)<<4)-Key[0]);\r
-            ClearPassword[PassLen>>1]=0;\r
-        }\r
-        else\r
-        {\r
-            for(int i=0; i<PassLen; i++)\r
-                ClearPassword[i] = (char)(PasswordData[i]-Key[0]);\r
-            ClearPassword[PassLen]=0;\r
-        }\r
-        return true;\r
-    }\r
-    else\r
-      return false;\r
-}\r
-\r
-bool PAccount::Authenticate(const uint8_t* PasswordData, int PassLen, const uint8_t *Key)\r
-{\r
-    char Pass[128];\r
-\r
-    if(DecodePassword(PasswordData, PassLen, Key, Pass))\r
-  {\r
-        return Authenticate(Pass);\r
-    }\r
-    else\r
-    {\r
-        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);\r
-        return false;\r
-    }\r
-}\r
-\r
-bool PAccount::Authenticate(const char *Password) const\r
-{\r
-    if(mID == 0) // User doesn't exist and that hasn't been checked !\r
-    {\r
-      Console->Print(RED, BLACK, "[Bug]: user %s doesn't exist and was not checked by code !", mName.c_str());\r
-      return false;\r
-    }\r
-\r
-    return(mPassword == Password);\r
-}\r
-\r
-bool PAccount::Create()\r
-{\r
-  if(Save(true)) {\r
-    //mID = MySQL->GetLastInfoInsertId();\r
-    mID = MySQL->GetLastInsertId();\r
-    return true;\r
-  }\r
-  else\r
-  {\r
-    return false;\r
-  }\r
-}\r
-\r
-bool PAccount::Save(bool CreateMode)\r
-{\r
-  char escUsername[256];\r
-  char escPassword[256];\r
-  MySQL->EscapeString(mName.c_str(), escUsername, 256);\r
-  MySQL->EscapeString(mPassword.c_str(), escPassword, 256);\r
-\r
-  std::string Query;\r
-  Query = CreateMode ? "INSERT INTO" : "UPDATE";\r
-  Query += " accounts SET ";\r
-  Query += Ssprintf(" a_username='%s', a_password = '%s'", escUsername, escPassword);\r
-  Query += Ssprintf(", a_priv = %d, a_status = %d, a_bandate = %d", mLevel, mStatus, mBannedUntil);\r
-  if(!CreateMode )\r
-  {\r
-    Query += Ssprintf(" a_lastused = NOW()");\r
-    Query += Ssprintf(" WHERE a_id = %d LIMIT 1", mID);\r
-  }\r
-  else\r
-    Query += Ssprintf(" a_creationdate = NOW()");\r
-\r
-  //if(MySQL->InfoQuery(Query.c_str()))\r
-  if(MySQL->Query(Query.c_str()))\r
-  {\r
-      Console->Print(RED, BLACK, "[Error] Failed to %s account %s (id %d)", CreateMode ? "create" : "update", mName.c_str(), mID);\r
-      //MySQL->ShowInfoSQLError();\r
-      MySQL->ShowSQLError();\r
-      return false;\r
-  }\r
-  return true;\r
-}\r
-\r
-std::string PAccount::GetBannedTime() const\r
-{\r
-  const char* unit[5] = {"seconds", "minutes", "hours", "days", "weeks"};\r
-\r
-  std::time_t timediff = mBannedUntil - std::time(NULL);\r
-  if(timediff <=0)\r
-  {\r
-    return "0 more seconds. Please relog";\r
-  }\r
-\r
-  long counter;\r
-  int type;\r
-\r
-  if(timediff > 86400)   // days\r
-  {\r
-    counter = timediff / 86400;\r
-    type = 3;\r
-  }\r
-  else if(timediff > 3600)    // hours\r
-  {\r
-    counter = timediff / 3600;\r
-    type = 2;\r
-  }\r
-  else if(timediff > 60)      // Minutes\r
-  {\r
-    counter  = timediff / 60;\r
-    type = 1;\r
-  }\r
-  else      // Seconds\r
-  {\r
-    counter = timediff;\r
-    type = 0;\r
-  }\r
-\r
-  return Ssprintf("%d more %s", counter, unit[type]);\r
-}\r
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+/*
+NOTE ABOUT ACCESS LEVELS IN THE MYSQL DATABASE:
+a_priv:
+0 = unregistered user
+1 = Registered user
+30 = volunteer
+50 = GM
+100 = Admin
+
+a_status:
+0 = Offline
+1 = Online
+2 = Banned
+*/
+
+/** Static members **/
+RegEx* PAccount::mUsernameRegexFilter = nullptr;
+RegEx* PAccount::mPasswordRegexFilter = nullptr;
+
+bool PAccount::SetUsernameRegexFilter(const char* RegexStr)
+{
+  if(mUsernameRegexFilter)
+  {
+    delete mUsernameRegexFilter;
+    mUsernameRegexFilter = NULL;
+  }
+
+  if(RegexStr)
+  {
+    try {
+      mUsernameRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);
+    }
+    catch (...) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool PAccount::SetPasswordRegexFilter(const char* RegexStr)
+{
+  if(mPasswordRegexFilter)
+  {
+    delete mPasswordRegexFilter;
+    mPasswordRegexFilter = NULL;
+  }
+
+  if(RegexStr)
+  {
+    try {
+      mPasswordRegexFilter = new RegEx(RegexStr, PCRE_CASELESS);
+    }
+    catch (...) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool PAccount::IsUsernameWellFormed(const char *Username)
+{
+  if(mUsernameRegexFilter)
+  {
+    return mUsernameRegexFilter->Search(Username);
+  }
+  else
+    return true;
+}
+
+bool PAccount::IsPasswordWellFormed(const char *Password)
+{
+  if(mPasswordRegexFilter)
+  {
+    return mPasswordRegexFilter->Search(Password);
+  }
+  else
+    return true;
+}
+
+/** Instance members **/
+PAccount::PAccount()
+{
+    mID = 0;
+    mLevel = PAL_BANNED;
+  mStatus = PAS_OFFLINE;
+  mBannedUntil = 0;
+}
+
+PAccount::PAccount(const uint32_t AccountId)
+{
+  char query[256];
+  mID = 0;
+  snprintf(query, 256, "SELECT * FROM accounts WHERE a_id = %d LIMIT 1;", AccountId);
+  LoadFromQuery(query);
+}
+
+PAccount::PAccount(const char *Username)
+{
+  char query[256];
+  mID = 0;
+  if(IsUsernameWellFormed(Username)) {
+    char escUsername[256];
+    MySQL->EscapeString(Username, escUsername, 256);
+    snprintf(query, 256, "SELECT * FROM accounts WHERE a_username = '%s' LIMIT 1;", escUsername);
+    LoadFromQuery(query);
+  }
+}
+
+bool PAccount::LoadFromQuery(char* query)
+{
+  MYSQL_ROW row = 0;
+  MYSQL_RES *result = 0;
+
+  bool FinalResult = false;
+
+  //result = MySQL->InfoResQuery(query);
+  result = MySQL->ResQuery(query);
+  if(result == NULL)
+  {
+      Console->Print(RED, BLACK, "Failed to load AccountData from SQL");
+      //MySQL->ShowInfoSQLError();
+      MySQL->ShowSQLError();
+      return false;
+  }
+
+  if((row = mysql_fetch_row(result)))
+  {
+    mID = atoi(row[a_id]);
+    mName = row[a_username];
+    mPassword = row[a_password];
+
+    mBannedUntil = atoi(row[a_bandate]);
+    if(mBannedUntil > std::time(NULL))
+    {
+      mStatus = PAS_BANNED;
+      mLevel = PAL_BANNED;
+    }
+    else
+    {
+      mStatus = PAS_OFFLINE;
+      mLevel = atoi(row[a_priv]);
+    }
+
+    FinalResult = true;
+  }
+  else
+  {
+Console->Print(YELLOW, BLACK, "Failed to load AccountData from SQL; Nothing to load...");
+  }
+
+  //MySQL->FreeInfoSQLResult(result);
+  MySQL->FreeSQLResult(result);
+  return FinalResult;
+}
+
+uint32_t PAccount::GetID() const
+{
+    return mID;
+}
+
+bool PAccount::SetName(const std::string &Username)
+{
+  if(IsUsernameWellFormed(Username.c_str()))
+  {
+    mName = Username;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+const std::string &PAccount::GetName() const
+{
+    return mName;
+}
+
+bool PAccount::SetPassword(const std::string &Password)
+{
+  if(IsPasswordWellFormed(Password.c_str()))
+  {
+    mPassword = Password;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::SetPasswordEncoded(const uint8_t* PasswordData, int PassLen, const uint8_t* Key)
+{
+    char Pass[128];
+
+    if(DecodePassword(PasswordData, PassLen, Key, Pass))
+  {
+        return SetPassword((std::string)Pass);
+    }
+    else
+    {
+        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);
+        return false;
+    }
+}
+
+const std::string &PAccount::GetPassword() const
+{
+    return mPassword;
+}
+
+bool PAccount::SetLevel(int newLevel)
+{
+  if((newLevel >= PAL_BANNED) && (newLevel <= PAL_ADMIN))
+  {
+    mLevel = newLevel;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+int32_t PAccount::GetLevel() const
+{
+    return mLevel;
+}
+
+std::string PAccount::GetLevelString() const
+{
+    switch(mLevel)
+    {
+        case PAL_BANNED : return "banned";
+        case PAL_UNREGPLAYER : return "unregplayer";
+        case PAL_REGPLAYER : return "regplayer";
+        case PAL_VOLUNTEER : return "volunteer";
+        case PAL_GM : return "gm";
+        case PAL_ADMIN : return "admin";
+    }
+
+    return "custom";
+}
+
+bool PAccount::SetStatus(PAccountStatus Status)
+{
+  mStatus = Status;
+  return true;
+}
+
+PAccountStatus PAccount::GetStatus() const
+{
+    return mStatus;
+}
+
+bool PAccount::SetBannedUntilTime(std::time_t BannedUntil)
+{
+  if ((BannedUntil == 0) || (BannedUntil > std::time(NULL)))
+  {
+    mBannedUntil = BannedUntil;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::IsBanned() const
+{
+    return (mBannedUntil > std::time(nullptr));
+}
+
+bool PAccount::DecodePassword(const uint8_t* PasswordData, int PassLen, const uint8_t *Key, char* ClearPassword)
+{
+  ClearPassword[0] = 0;
+
+  if(PassLen < 128)
+    {
+        if(Key[0]>7) // TODO: >7 correct?
+        {
+            for(int i=0; i<PassLen; i+=2)
+                ClearPassword[i>>1] = (char)(((PasswordData[i]&0xf0)>>4)
+                    +((PasswordData[i+1]&0x0f)<<4)-Key[0]);
+            ClearPassword[PassLen>>1]=0;
+        }
+        else
+        {
+            for(int i=0; i<PassLen; i++)
+                ClearPassword[i] = (char)(PasswordData[i]-Key[0]);
+            ClearPassword[PassLen]=0;
+        }
+        return true;
+    }
+    else
+      return false;
+}
+
+bool PAccount::Authenticate(const uint8_t* PasswordData, int PassLen, const uint8_t *Key)
+{
+    char Pass[128];
+
+    if(DecodePassword(PasswordData, PassLen, Key, Pass))
+  {
+        return Authenticate(Pass);
+    }
+    else
+    {
+        Console->Print(RED, BLACK, "[Error]: user %s : malformed auth data (size=%d)", mName.c_str(), PassLen);
+        return false;
+    }
+}
+
+bool PAccount::Authenticate(const char *Password) const
+{
+    if(mID == 0) // User doesn't exist and that hasn't been checked !
+    {
+      Console->Print(RED, BLACK, "[Bug]: user %s doesn't exist and was not checked by code !", mName.c_str());
+      return false;
+    }
+
+    return(mPassword == Password);
+}
+
+bool PAccount::Create()
+{
+  if(Save(true)) {
+    //mID = MySQL->GetLastInfoInsertId();
+    mID = MySQL->GetLastInsertId();
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool PAccount::Save(bool CreateMode)
+{
+  char escUsername[256];
+  char escPassword[256];
+  MySQL->EscapeString(mName.c_str(), escUsername, 256);
+  MySQL->EscapeString(mPassword.c_str(), escPassword, 256);
+
+  std::string Query;
+  Query = CreateMode ? "INSERT INTO" : "UPDATE";
+  Query += " accounts SET ";
+  Query += Ssprintf(" a_username='%s', a_password = '%s'", escUsername, escPassword);
+  Query += Ssprintf(", a_priv = %d, a_status = %d, a_bandate = %d", mLevel, mStatus, mBannedUntil);
+  if(!CreateMode )
+  {
+    Query += Ssprintf(" a_lastused = NOW()");
+    Query += Ssprintf(" WHERE a_id = %d LIMIT 1", mID);
+  }
+  else
+    Query += Ssprintf(" a_creationdate = NOW()");
+
+  //if(MySQL->InfoQuery(Query.c_str()))
+  if(MySQL->Query(Query.c_str()))
+  {
+      Console->Print(RED, BLACK, "[Error] Failed to %s account %s (id %d)", CreateMode ? "create" : "update", mName.c_str(), mID);
+      //MySQL->ShowInfoSQLError();
+      MySQL->ShowSQLError();
+      return false;
+  }
+  return true;
+}
+
+std::string PAccount::GetBannedTime() const
+{
+  const char* unit[5] = {"seconds", "minutes", "hours", "days", "weeks"};
+
+  std::time_t timediff = mBannedUntil - std::time(NULL);
+  if(timediff <=0)
+  {
+    return "0 more seconds. Please relog";
+  }
+
+  long counter;
+  int type;
+
+  if(timediff > 86400)   // days
+  {
+    counter = timediff / 86400;
+    type = 3;
+  }
+  else if(timediff > 3600)    // hours
+  {
+    counter = timediff / 3600;
+    type = 2;
+  }
+  else if(timediff > 60)      // Minutes
+  {
+    counter  = timediff / 60;
+    type = 1;
+  }
+  else      // Seconds
+  {
+    counter = timediff;
+    type = 0;
+  }
+
+  return Ssprintf("%d more %s", counter, unit[type]);
+}
index 96bd185..6ad130c 100644 (file)
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <ctime>\r
-#include <string>\r
-\r
-class RegEx;\r
-\r
-/*\r
-0 = unregistered user\r
-1 = Registered user\r
-30 = volunteer\r
-50 = GM\r
-100 = Admin\r
-*/\r
-\r
-// New way of AccountLevel handling:\r
-// Every level is possible, the following values are only edge values. We need a bit control about that\r
-#define PAL_BANNED -1\r
-#define PAL_UNREGPLAYER 0\r
-#define PAL_REGPLAYER 1\r
-#define PAL_VOLUNTEER 30\r
-#define PAL_GM 50\r
-#define PAL_ADMIN 100\r
-\r
-// Max number of char slots per account\r
-#define MAX_CHARS_PER_ACCOUNT  4\r
-\r
-/*\r
-0 = Offline\r
-1 = Online\r
-2 = Banned\r
-*/\r
-\r
-enum PAccountStatus\r
-{\r
-    PAS_OFFLINE = 0,\r
-    PAS_ONLINE = 1,\r
-    PAS_BANNED = 2\r
-};\r
-\r
-class PAccount\r
-{\r
-    private :\r
-    // SQL Layout\r
-    enum {\r
-        a_id,\r
-        a_username,\r
-        a_password,\r
-        a_priv,\r
-        a_status,\r
-        a_bandate,\r
-        a_emailaddress,\r
-        a_creationdate,\r
-        a_lastused\r
-    };\r
-\r
-    // static members\r
-    static RegEx *mUsernameRegexFilter;\r
-    static RegEx *mPasswordRegexFilter;\r
-\r
-    // instance members\r
-    uint32_t mID;\r
-    std::string mName;\r
-    std::string mPassword;\r
-    int32_t mLevel;\r
-    PAccountStatus mStatus;\r
-    std::time_t mBannedUntil;\r
-\r
-    bool LoadFromQuery(char *query);\r
-    bool DecodePassword(const uint8_t *PasswordData, int32_t PassLen, const uint8_t *Key, char *ClearPassword);\r
-\r
-public:\r
-    PAccount();\r
-    PAccount(const uint32_t AccountId);\r
-    PAccount(const char *Username);\r
-\r
-    static bool SetUsernameRegexFilter(const char *RegexStr);\r
-    static bool SetPasswordRegexFilter(const char *RegexStr);\r
-    static bool IsUsernameWellFormed(const char *Username);\r
-    static bool IsPasswordWellFormed(const char *Password);\r
-\r
-    uint32_t GetID() const;\r
-    bool SetName(const std::string &Pass);\r
-    const std::string &GetName() const;\r
-    bool SetPassword(const std::string &Pass);\r
-    bool SetPasswordEncoded(const uint8_t *PasswordData, int32_t PassLen, const uint8_t *Key);\r
-    const std::string &GetPassword() const;\r
-    bool SetLevel(int32_t newLevel);\r
-    int32_t GetLevel() const;\r
-    std::string GetLevelString() const;\r
-    bool SetStatus(PAccountStatus Status);\r
-    PAccountStatus GetStatus() const;\r
-    bool SetBannedUntilTime(std::time_t BannedUntil);\r
-    bool IsBanned() const;\r
-    std::string GetBannedTime() const;\r
-    bool Authenticate(const uint8_t *PasswordData, int32_t PassLen, const uint8_t *Key);\r
-    bool Authenticate(const char *Password) const;\r
-    bool Create();\r
-    bool Save(bool CreateMode = false);\r
-\r
-    //u32 GetCharIdBySlot(const u32 SlotId);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <ctime>
+#include <string>
+
+class RegEx;
+
+/*
+0 = unregistered user
+1 = Registered user
+30 = volunteer
+50 = GM
+100 = Admin
+*/
+
+// New way of AccountLevel handling:
+// Every level is possible, the following values are only edge values. We need a bit control about that
+#define PAL_BANNED -1
+#define PAL_UNREGPLAYER 0
+#define PAL_REGPLAYER 1
+#define PAL_VOLUNTEER 30
+#define PAL_GM 50
+#define PAL_ADMIN 100
+
+// Max number of char slots per account
+#define MAX_CHARS_PER_ACCOUNT  4
+
+/*
+0 = Offline
+1 = Online
+2 = Banned
+*/
+
+enum PAccountStatus
+{
+    PAS_OFFLINE = 0,
+    PAS_ONLINE = 1,
+    PAS_BANNED = 2
+};
+
+class PAccount
+{
+    private :
+    // SQL Layout
+    enum {
+        a_id,
+        a_username,
+        a_password,
+        a_priv,
+        a_status,
+        a_bandate,
+        a_emailaddress,
+        a_creationdate,
+        a_lastused
+    };
+
+    // static members
+    static RegEx *mUsernameRegexFilter;
+    static RegEx *mPasswordRegexFilter;
+
+    // instance members
+    uint32_t mID;
+    std::string mName;
+    std::string mPassword;
+    int32_t mLevel;
+    PAccountStatus mStatus;
+    std::time_t mBannedUntil;
+
+    bool LoadFromQuery(char *query);
+    bool DecodePassword(const uint8_t *PasswordData, int32_t PassLen, const uint8_t *Key, char *ClearPassword);
+
+public:
+    PAccount();
+    PAccount(const uint32_t AccountId);
+    PAccount(const char *Username);
+
+    static bool SetUsernameRegexFilter(const char *RegexStr);
+    static bool SetPasswordRegexFilter(const char *RegexStr);
+    static bool IsUsernameWellFormed(const char *Username);
+    static bool IsPasswordWellFormed(const char *Password);
+
+    uint32_t GetID() const;
+    bool SetName(const std::string &Pass);
+    const std::string &GetName() const;
+    bool SetPassword(const std::string &Pass);
+    bool SetPasswordEncoded(const uint8_t *PasswordData, int32_t PassLen, const uint8_t *Key);
+    const std::string &GetPassword() const;
+    bool SetLevel(int32_t newLevel);
+    int32_t GetLevel() const;
+    std::string GetLevelString() const;
+    bool SetStatus(PAccountStatus Status);
+    PAccountStatus GetStatus() const;
+    bool SetBannedUntilTime(std::time_t BannedUntil);
+    bool IsBanned() const;
+    std::string GetBannedTime() const;
+    bool Authenticate(const uint8_t *PasswordData, int32_t PassLen, const uint8_t *Key);
+    bool Authenticate(const char *Password) const;
+    bool Create();
+    bool Save(bool CreateMode = false);
+
+    //u32 GetCharIdBySlot(const u32 SlotId);
+};
index 12ea790..7a6898a 100644 (file)
@@ -1,84 +1,84 @@
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PClient::PClient(int32_t Index)\r
-{\r
-    mIndex = Index;\r
-    mConnection = PCC_NONE;\r
-    mAccountID = 0;\r
-}\r
-\r
-PClient::~PClient()\r
-{\r
-    if(m_TCPConnection)\r
-    {\r
-        delete m_TCPConnection;\r
-    }\r
-}\r
-\r
-int32_t PClient::GetIndex() const\r
-{\r
-    return mIndex;\r
-}\r
-\r
-void PClient::setTCPConnection(ConnectionTCP *conn)\r
-{\r
-    m_TCPConnection = conn; mConnection = PCC_INFO;\r
-}\r
-\r
-ConnectionTCP *PClient::getTCPConn() const\r
-{\r
-    return m_TCPConnection;\r
-}\r
-\r
-int32_t PClient::GetConnection() const\r
-{\r
-    return mConnection;\r
-}\r
-\r
-const char *PClient::GetAddress() const\r
-{\r
-    return m_TCPConnection->getRemoteAddress();\r
-}\r
-\r
-void PClient::setAccountID(uint32_t nAccountID)\r
-{\r
-    mAccountID = nAccountID;\r
-}\r
-\r
-uint32_t PClient::getAccountID()\r
-{\r
-    return mAccountID;\r
-}\r
-\r
-void PClient::InfoDisconnect()\r
-{\r
-    if(m_TCPConnection)\r
-    {\r
-        delete m_TCPConnection;\r
-    }\r
-    m_TCPConnection = 0;\r
-\r
-    //mConnection &= ~PCC_INFO;\r
-    mConnection = PCC_NONE;\r
-    mAccountID = 0;\r
-}\r
-\r
-void PClient::Update()\r
-{\r
-    if(m_TCPConnection)\r
-    {\r
-        if(m_TCPConnection->timeOut())\r
-        {\r
-                Console->Print("InfoSocket: Client %i: timeout", mIndex);\r
-                InfoServer->ClientDisconnected(this);\r
-        }\r
-        else\r
-        {\r
-            if(!m_TCPConnection->update())\r
-            {\r
-                InfoServer->ClientDisconnected(this);\r
-            }\r
-        }\r
-    }\r
-}\r
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PClient::PClient(int32_t Index)
+{
+    mIndex = Index;
+    mConnection = PCC_NONE;
+    mAccountID = 0;
+}
+
+PClient::~PClient()
+{
+    if(m_TCPConnection)
+    {
+        delete m_TCPConnection;
+    }
+}
+
+int32_t PClient::GetIndex() const
+{
+    return mIndex;
+}
+
+void PClient::setTCPConnection(ConnectionTCP *conn)
+{
+    m_TCPConnection = conn; mConnection = PCC_INFO;
+}
+
+ConnectionTCP *PClient::getTCPConn() const
+{
+    return m_TCPConnection;
+}
+
+int32_t PClient::GetConnection() const
+{
+    return mConnection;
+}
+
+const char *PClient::GetAddress() const
+{
+    return m_TCPConnection->getRemoteAddress();
+}
+
+void PClient::setAccountID(uint32_t nAccountID)
+{
+    mAccountID = nAccountID;
+}
+
+uint32_t PClient::getAccountID()
+{
+    return mAccountID;
+}
+
+void PClient::InfoDisconnect()
+{
+    if(m_TCPConnection)
+    {
+        delete m_TCPConnection;
+    }
+    m_TCPConnection = 0;
+
+    //mConnection &= ~PCC_INFO;
+    mConnection = PCC_NONE;
+    mAccountID = 0;
+}
+
+void PClient::Update()
+{
+    if(m_TCPConnection)
+    {
+        if(m_TCPConnection->timeOut())
+        {
+                Console->Print("InfoSocket: Client %i: timeout", mIndex);
+                InfoServer->ClientDisconnected(this);
+        }
+        else
+        {
+            if(!m_TCPConnection->update())
+            {
+                InfoServer->ClientDisconnected(this);
+            }
+        }
+    }
+}
index 44d284b..4d7b884 100644 (file)
@@ -1,33 +1,33 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class ConnectionTCP;\r
-\r
-enum PClientConnection\r
-{\r
-    PCC_NONE = 0,\r
-    PCC_INFO = 1\r
-};\r
-\r
-class PClient {\r
-private:\r
-    ConnectionTCP* m_TCPConnection;\r
-    int32_t mIndex;\r
-    int32_t mConnection;\r
-    uint32_t mAccountID;\r
-\r
-public:\r
-    PClient(int32_t Index);\r
-    ~PClient();\r
-\r
-    int32_t GetIndex() const;\r
-    void setTCPConnection(ConnectionTCP *conn);\r
-    ConnectionTCP *getTCPConn() const;\r
-    int32_t GetConnection() const;\r
-    const char *GetAddress() const;\r
-    void setAccountID(uint32_t nAccountID);\r
-    uint32_t getAccountID();\r
-    void InfoDisconnect();\r
-    void Update();\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+class ConnectionTCP;
+
+enum PClientConnection
+{
+    PCC_NONE = 0,
+    PCC_INFO = 1
+};
+
+class PClient {
+private:
+    ConnectionTCP* m_TCPConnection;
+    int32_t mIndex;
+    int32_t mConnection;
+    uint32_t mAccountID;
+
+public:
+    PClient(int32_t Index);
+    ~PClient();
+
+    int32_t GetIndex() const;
+    void setTCPConnection(ConnectionTCP *conn);
+    ConnectionTCP *getTCPConn() const;
+    int32_t GetConnection() const;
+    const char *GetAddress() const;
+    void setAccountID(uint32_t nAccountID);
+    uint32_t getAccountID();
+    void InfoDisconnect();
+    void Update();
+};
index 92eced8..8e4ac9a 100644 (file)
@@ -1,30 +1,30 @@
-#pragma once\r
-\r
-static const char *InfoConfigTemplate[][2] = {\r
-  // {option_name, default_value} if default_value is empty string, it means option is mandatory\r
-  // List ends with empty string for option_name\r
-  {"sql_host", "127.0.0.1"}, // should be renanmed to info_sql_host\r
-  {"sql_port", "3306"}, // should be renanmed to info_sql_port\r
-  {"sql_username", ""}, // should be renanmed to info_sql_username\r
-  {"sql_password", ""}, // should be renanmed to info_sql_password\r
-  {"global_sql_database", "infoserver"}, // should be renanmed to info_sql_database\r
-  {"mysql_wait_timeout", "28800"}, // value of the wait_timout system variable from the MySQL server (same for game & info DB atm). 0 to disable keepalive.\r
-  {"auto_accounts", "0"},\r
-  {"infoserver_port", "7000"},\r
-  {"gameserver_livecheck", "60"},\r
-  {"minlevel", "0"},\r
-  {"maxclients", "50"},\r
-  {"require_validation", "0"},\r
-  {"isc_method", "1"},\r
-  {"isc_infoserverport", "9991"},\r
-  {"isc_connect_pw", "changeme"},\r
-  {"username_filter", "^[a-z][\\w\\-]{2,14}$"},\r
-  {"password_filter", "^[[:graph:]]{3,15}$"},\r
-  {"sqlite_databasefile", "infoDB.s3db"},\r
-  {"database_type", "sqlite"},\r
-\r
-// For futur use:\r
-//  {"max_chars_per_account", "4"},\r
-\r
-  {"", ""} // do not change this line (end mark)\r
-};\r
+#pragma once
+
+static const char *InfoConfigTemplate[][2] = {
+  // {option_name, default_value} if default_value is empty string, it means option is mandatory
+  // List ends with empty string for option_name
+  {"sql_host", "127.0.0.1"}, // should be renanmed to info_sql_host
+  {"sql_port", "3306"}, // should be renanmed to info_sql_port
+  {"sql_username", ""}, // should be renanmed to info_sql_username
+  {"sql_password", ""}, // should be renanmed to info_sql_password
+  {"global_sql_database", "infoserver"}, // should be renanmed to info_sql_database
+  {"mysql_wait_timeout", "28800"}, // value of the wait_timout system variable from the MySQL server (same for game & info DB atm). 0 to disable keepalive.
+  {"auto_accounts", "0"},
+  {"infoserver_port", "7000"},
+  {"gameserver_livecheck", "60"},
+  {"minlevel", "0"},
+  {"maxclients", "50"},
+  {"require_validation", "0"},
+  {"isc_method", "1"},
+  {"isc_infoserverport", "9991"},
+  {"isc_connect_pw", "changeme"},
+  {"username_filter", "^[a-z][\\w\\-]{2,14}$"},
+  {"password_filter", "^[[:graph:]]{3,15}$"},
+  {"sqlite_databasefile", "infoDB.s3db"},
+  {"database_type", "sqlite"},
+
+// For futur use:
+//  {"max_chars_per_account", "4"},
+
+  {"", ""} // do not change this line (end mark)
+};
index 28ea027..d61e1a2 100644 (file)
-#include <cstring>\r
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-const char ServerVersion[] = TINNS_INFO_VERSION;\r
-const char SVNRevision[] = TINNS_SVN_REVISION;\r
-\r
-ServerSocket* ServerSock = 0;\r
-PMySQL *MySQL = 0;\r
-PConsole *Console = 0;\r
-PServer *Server = 0;\r
-PConfig *Config = 0;\r
-PInfoServer *InfoServer = 0;\r
-//PAccounts *Accounts = 0;  // To be removed\r
-\r
-bool Init()\r
-{\r
-    Console = new PConsole("log/infoserver.log"); // Make that from config file !!!\r
-    Console->Print("Starting TinNS Infoserver");\r
-    Console->Print(WHITE, BLUE, "/-------------------------------------------------------------------\\");\r
-    Console->Print(WHITE, BLUE, "|               TinNS (TinNS is not a Neocron Server)               |");\r
-  Console->Print(WHITE, BLUE, "|            Copyright (C) 2005 Linux Addicted Community            |");\r
-    Console->Print(WHITE, BLUE, "|                  maintainer Akiko <akiko@gmx.org>                 |");\r
-    Console->Print(WHITE, BLUE, "|             ==========================================            |");\r
-    Console->Print(WHITE, BLUE, "|      Head coders:                   The packet analyzing team:    |");\r
-    Console->Print(WHITE, BLUE, "|      - Akiko                         - MaxxJag                    |");\r
-    Console->Print(WHITE, BLUE, "|      - bakkdoor                      - Sting                      |");\r
-    Console->Print(WHITE, BLUE, "|      - Namikon                       - Balm                       |");\r
-    Console->Print(WHITE, BLUE, "|      - Hammag                                                     |");\r
-    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");\r
-    Console->Print(WHITE, BLUE, "|  This project would'nt be at its current stage without the help   |");\r
-  Console->Print(WHITE, BLUE, "|        from the NeoPolis team, special thanks to you guys!        |");\r
-    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");\r
-    Console->Print(WHITE, BLUE, "|  This project is under GPL, see any source file for more details  |");\r
-    Console->Print(WHITE, BLUE, "\\-------------------------------------------------------------------/");\r
-\r
-    //char svnrev[10];\r
-    //GetSVNRev(svnrev);\r
-    Console->LPrint("You are running TinNS Infoserver version");\r
-    Console->LPrint(GREEN, BLACK, " %s", ServerVersion);\r
-    Console->LPrint(WHITE, BLACK, " - SVN Rev");\r
-    Console->LPrint(GREEN, BLACK, " %s", SVNRevision);\r
-    Console->LClose();\r
-\r
-    Config = new PConfig();\r
-    if(!Config->LoadOptions(InfoConfigTemplate, "./conf/infoserver.conf"))\r
-        return false; //Shutdown();\r
-  if(!AdditionnalConfigChecks())\r
-    return false; //Shutdown();\r
-\r
-    ServerSock = new ServerSocket();\r
-    Server = new PServer();\r
-\r
-    MySQL = new PMySQL();\r
-    if(MySQL->Connect() == false)\r
-        return false; //Shutdown();\r
-\r
-    InfoServer = new PInfoServer();\r
-    //Accounts = new PAccounts(); // To be removed\r
-\r
-    return true;\r
-}\r
-\r
-void Shutdown()\r
-{\r
-  if(Server) Server->Shutdown();\r
-    if(InfoServer) delete InfoServer;\r
-    if(MySQL) delete MySQL;\r
-    if(Config) delete Config;\r
-    if(Console) delete Console;\r
-    if(ServerSock) delete ServerSock;\r
-    exit(0);\r
-}\r
-\r
-bool AdditionnalConfigChecks()\r
-{\r
-  //NOTA: empty config values are never accepted by PConfig objects\r
-\r
-    int numErr, numWarn;\r
-\r
-    //std::string sqlhost = Config->GetOption("sql_host");\r
-    std::string sqlusername = Config->GetOption("sql_username");\r
-    //std::string sqlpassword = Config->GetOption("sql_password");\r
-    //std::string global_sql_database = Config->GetOption("global_sql_database");\r
-    int sqlport = Config->GetOptionInt("sql_port");\r
-    int auto_accounts = Config->GetOptionInt("auto_accounts");\r
-    int infoserver_port = Config->GetOptionInt("infoserver_port");\r
-    int gameserver_livecheck = Config->GetOptionInt("gameserver_livecheck");\r
-    int minlevel = Config->GetOptionInt("minlevel");\r
-    int maxclients = Config->GetOptionInt("maxclients");\r
-\r
-    numErr = numWarn = 0;\r
-\r
-    /*if(strcmp(sqlhost.c_str(), "") == 0)\r
-    {\r
-        Console->Print("%s sql_host is empty", Console->ColorText(RED, BLACK, "Config error:"));\r
-        numErr++;\r
-    }*/\r
-\r
-    /*if(strcmp(sqlusername.c_str(), "") == 0)\r
-    {\r
-        Console->Print("%s sql_username is empty", Console->ColorText(RED, BLACK, "Config error:"));\r
-        numErr++;\r
-    }\r
-    else*/\r
-      if(strcmp(sqlusername.c_str(), "root") ==0)\r
-    {\r
-        Console->Print("%s Config: sqlusername is \"root\", which is pretty insecure.", Console->ColorText(YELLOW, BLACK, "[Warning]"));\r
-        numWarn++;\r
-    }\r
-\r
-    /*if(strcmp(sqlpassword.c_str(), "") == 0);\r
-    {\r
-        Console->Print("%s sql_password is empty", Console->ColorText(RED, BLACK, "Config error:"));\r
-        numErr++;\r
-    }\r
-\r
-    if(strcmp(global_sql_database.c_str(), "") == 0);\r
-    {\r
-        Console->Print("%s global_sql_database is empty", Console->ColorText(RED, BLACK, "Config error:"));\r
-        numErr++;\r
-    }*/\r
-\r
-    if(sqlport < 1025 || sqlport > 65535)\r
-    {\r
-        Console->Print("%s Config: sql_port is usually between 1025 and 65535!", Console->ColorText(YELLOW, BLACK, "[Warning]"));\r
-        numWarn++;\r
-    }\r
-\r
-    if(auto_accounts != 0 && auto_accounts != 1)\r
-    {\r
-        Console->Print("%s Config: auto_accounts has to be either 0 or 1!", Console->ColorText(RED, BLACK, "[Error]"));\r
-        numErr++;\r
-    }\r
-\r
-    if(infoserver_port < 1025 || infoserver_port > 65535)\r
-    {\r
-        Console->Print("%s Config: infoserver_port has to be between 1025 and 65535!", Console->ColorText(RED, BLACK, "[Error]"));\r
-        numErr++;\r
-    }\r
-    // This assertion is wrong, as sql server and info server can be on differents computers\r
-    /*else if(infoserver_port == sqlport)\r
-    {\r
-        Console->Print("%s infoserver_port has to be different from sql_port!", Console->ColorText(RED, BLACK, "Config error:"));\r
-        numErr++;\r
-    }*/\r
-\r
-    if(gameserver_livecheck <= 0)\r
-    {\r
-        Console->Print("%s Config: gameserver_livecheck cannot equal or less than 0", Console->ColorText(RED, BLACK, "[Error]"));\r
-        numErr++;\r
-    }\r
-    else if(gameserver_livecheck < 2)\r
-    {\r
-        Console->Print("%s Config: gameserver_livecheck is pretty low, this may cause increased mysql load", Console->ColorText(YELLOW, BLACK, "[Warning]"));\r
-        numWarn++;\r
-    }\r
-    else if(gameserver_livecheck > 120 && gameserver_livecheck < 600)\r
-    {\r
-        Console->Print("%s Config: gameserver_livecheck is pretty high, this may cause offline servers shown as online and a wrong usercount", Console->ColorText(YELLOW, BLACK, "[Warning]"));\r
-        numWarn++;\r
-    }\r
-    else if(gameserver_livecheck > 600)\r
-    {\r
-        Console->Print("%s Config: gameserver_livecheck is too high. Use a value between 0 and 600", Console->ColorText(RED, BLACK, "[Error]"));\r
-        numErr++;\r
-    }\r
-\r
-    if(minlevel < 0 || minlevel > 255)\r
-    {\r
-        Console->Print("%s Config: minlevel has to be between 0 and 255", Console->ColorText(RED, BLACK, "[Error]"));\r
-        numErr++;\r
-    }\r
-\r
-    if(maxclients < 1 )\r
-    {\r
-        Console->Print("%s Config: maxclients has to be higher or equal to 1", Console->ColorText(RED, BLACK, "[Error]"));\r
-        numErr++;\r
-    }\r
-\r
-    if(numErr == 0 /*&& numWarn == 0*/)\r
-        return true;\r
-    else\r
-        return false;\r
-}\r
+#include <cstring>
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+const char ServerVersion[] = TINNS_INFO_VERSION;
+const char SVNRevision[] = TINNS_SVN_REVISION;
+
+ServerSocket* ServerSock = 0;
+PMySQL *MySQL = 0;
+PConsole *Console = 0;
+PServer *Server = 0;
+PConfig *Config = 0;
+PInfoServer *InfoServer = 0;
+//PAccounts *Accounts = 0;  // To be removed
+
+bool Init()
+{
+    Console = new PConsole("log/infoserver.log"); // Make that from config file !!!
+    Console->Print("Starting TinNS Infoserver");
+    Console->Print(WHITE, BLUE, "/-------------------------------------------------------------------\\");
+    Console->Print(WHITE, BLUE, "|               TinNS (TinNS is not a Neocron Server)               |");
+  Console->Print(WHITE, BLUE, "|            Copyright (C) 2005 Linux Addicted Community            |");
+    Console->Print(WHITE, BLUE, "|                  maintainer Akiko <akiko@gmx.org>                 |");
+    Console->Print(WHITE, BLUE, "|             ==========================================            |");
+    Console->Print(WHITE, BLUE, "|      Head coders:                   The packet analyzing team:    |");
+    Console->Print(WHITE, BLUE, "|      - Akiko                         - MaxxJag                    |");
+    Console->Print(WHITE, BLUE, "|      - bakkdoor                      - Sting                      |");
+    Console->Print(WHITE, BLUE, "|      - Namikon                       - Balm                       |");
+    Console->Print(WHITE, BLUE, "|      - Hammag                                                     |");
+    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");
+    Console->Print(WHITE, BLUE, "|  This project would'nt be at its current stage without the help   |");
+  Console->Print(WHITE, BLUE, "|        from the NeoPolis team, special thanks to you guys!        |");
+    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");
+    Console->Print(WHITE, BLUE, "|  This project is under GPL, see any source file for more details  |");
+    Console->Print(WHITE, BLUE, "\\-------------------------------------------------------------------/");
+
+    //char svnrev[10];
+    //GetSVNRev(svnrev);
+    Console->LPrint("You are running TinNS Infoserver version");
+    Console->LPrint(GREEN, BLACK, " %s", ServerVersion);
+    Console->LPrint(WHITE, BLACK, " - SVN Rev");
+    Console->LPrint(GREEN, BLACK, " %s", SVNRevision);
+    Console->LClose();
+
+    Config = new PConfig();
+    if(!Config->LoadOptions(InfoConfigTemplate, "./conf/infoserver.conf"))
+        return false; //Shutdown();
+  if(!AdditionnalConfigChecks())
+    return false; //Shutdown();
+
+    ServerSock = new ServerSocket();
+    Server = new PServer();
+
+    MySQL = new PMySQL();
+    if(MySQL->Connect() == false)
+        return false; //Shutdown();
+
+    InfoServer = new PInfoServer();
+    //Accounts = new PAccounts(); // To be removed
+
+    return true;
+}
+
+void Shutdown()
+{
+  if(Server) Server->Shutdown();
+    if(InfoServer) delete InfoServer;
+    if(MySQL) delete MySQL;
+    if(Config) delete Config;
+    if(Console) delete Console;
+    if(ServerSock) delete ServerSock;
+    exit(0);
+}
+
+bool AdditionnalConfigChecks()
+{
+  //NOTA: empty config values are never accepted by PConfig objects
+
+    int numErr, numWarn;
+
+    //std::string sqlhost = Config->GetOption("sql_host");
+    std::string sqlusername = Config->GetOption("sql_username");
+    //std::string sqlpassword = Config->GetOption("sql_password");
+    //std::string global_sql_database = Config->GetOption("global_sql_database");
+    int sqlport = Config->GetOptionInt("sql_port");
+    int auto_accounts = Config->GetOptionInt("auto_accounts");
+    int infoserver_port = Config->GetOptionInt("infoserver_port");
+    int gameserver_livecheck = Config->GetOptionInt("gameserver_livecheck");
+    int minlevel = Config->GetOptionInt("minlevel");
+    int maxclients = Config->GetOptionInt("maxclients");
+
+    numErr = numWarn = 0;
+
+    /*if(strcmp(sqlhost.c_str(), "") == 0)
+    {
+        Console->Print("%s sql_host is empty", Console->ColorText(RED, BLACK, "Config error:"));
+        numErr++;
+    }*/
+
+    /*if(strcmp(sqlusername.c_str(), "") == 0)
+    {
+        Console->Print("%s sql_username is empty", Console->ColorText(RED, BLACK, "Config error:"));
+        numErr++;
+    }
+    else*/
+      if(strcmp(sqlusername.c_str(), "root") ==0)
+    {
+        Console->Print("%s Config: sqlusername is \"root\", which is pretty insecure.", Console->ColorText(YELLOW, BLACK, "[Warning]"));
+        numWarn++;
+    }
+
+    /*if(strcmp(sqlpassword.c_str(), "") == 0);
+    {
+        Console->Print("%s sql_password is empty", Console->ColorText(RED, BLACK, "Config error:"));
+        numErr++;
+    }
+
+    if(strcmp(global_sql_database.c_str(), "") == 0);
+    {
+        Console->Print("%s global_sql_database is empty", Console->ColorText(RED, BLACK, "Config error:"));
+        numErr++;
+    }*/
+
+    if(sqlport < 1025 || sqlport > 65535)
+    {
+        Console->Print("%s Config: sql_port is usually between 1025 and 65535!", Console->ColorText(YELLOW, BLACK, "[Warning]"));
+        numWarn++;
+    }
+
+    if(auto_accounts != 0 && auto_accounts != 1)
+    {
+        Console->Print("%s Config: auto_accounts has to be either 0 or 1!", Console->ColorText(RED, BLACK, "[Error]"));
+        numErr++;
+    }
+
+    if(infoserver_port < 1025 || infoserver_port > 65535)
+    {
+        Console->Print("%s Config: infoserver_port has to be between 1025 and 65535!", Console->ColorText(RED, BLACK, "[Error]"));
+        numErr++;
+    }
+    // This assertion is wrong, as sql server and info server can be on differents computers
+    /*else if(infoserver_port == sqlport)
+    {
+        Console->Print("%s infoserver_port has to be different from sql_port!", Console->ColorText(RED, BLACK, "Config error:"));
+        numErr++;
+    }*/
+
+    if(gameserver_livecheck <= 0)
+    {
+        Console->Print("%s Config: gameserver_livecheck cannot equal or less than 0", Console->ColorText(RED, BLACK, "[Error]"));
+        numErr++;
+    }
+    else if(gameserver_livecheck < 2)
+    {
+        Console->Print("%s Config: gameserver_livecheck is pretty low, this may cause increased mysql load", Console->ColorText(YELLOW, BLACK, "[Warning]"));
+        numWarn++;
+    }
+    else if(gameserver_livecheck > 120 && gameserver_livecheck < 600)
+    {
+        Console->Print("%s Config: gameserver_livecheck is pretty high, this may cause offline servers shown as online and a wrong usercount", Console->ColorText(YELLOW, BLACK, "[Warning]"));
+        numWarn++;
+    }
+    else if(gameserver_livecheck > 600)
+    {
+        Console->Print("%s Config: gameserver_livecheck is too high. Use a value between 0 and 600", Console->ColorText(RED, BLACK, "[Error]"));
+        numErr++;
+    }
+
+    if(minlevel < 0 || minlevel > 255)
+    {
+        Console->Print("%s Config: minlevel has to be between 0 and 255", Console->ColorText(RED, BLACK, "[Error]"));
+        numErr++;
+    }
+
+    if(maxclients < 1 )
+    {
+        Console->Print("%s Config: maxclients has to be higher or equal to 1", Console->ColorText(RED, BLACK, "[Error]"));
+        numErr++;
+    }
+
+    if(numErr == 0 /*&& numWarn == 0*/)
+        return true;
+    else
+        return false;
+}
index eff92ed..1253897 100644 (file)
@@ -1,24 +1,24 @@
-#pragma once\r
-\r
-#include "InfoServer/Accounts.hxx"\r
-#include "InfoServer/ConfigTemplate.hxx"\r
-#include "InfoServer/Client.hxx"\r
-#include "InfoServer/InfoServer.hxx"\r
-#include "InfoServer/Server.hxx"\r
-#include "InfoServer/Sql.hxx"\r
-\r
-extern class ServerSocket* ServerSock;\r
-extern class PConsole *Console;\r
-extern class PServer *Server;\r
-extern class PConfig *Config;\r
-extern class PInfoServer *InfoServer;\r
-\r
-extern class PMySQL* MySQL;\r
-//extern class PAccounts* Accounts;  // To be removed\r
-\r
-extern const char ServerVersion[];\r
-extern const char SVNRevision[];\r
-\r
-bool Init();\r
-void Shutdown();\r
-bool AdditionnalConfigChecks();\r
+#pragma once
+
+#include "InfoServer/Accounts.hxx"
+#include "InfoServer/ConfigTemplate.hxx"
+#include "InfoServer/Client.hxx"
+#include "InfoServer/InfoServer.hxx"
+#include "InfoServer/Server.hxx"
+#include "InfoServer/Sql.hxx"
+
+extern class ServerSocket* ServerSock;
+extern class PConsole *Console;
+extern class PServer *Server;
+extern class PConfig *Config;
+extern class PInfoServer *InfoServer;
+
+extern class PMySQL* MySQL;
+//extern class PAccounts* Accounts;  // To be removed
+
+extern const char ServerVersion[];
+extern const char SVNRevision[];
+
+bool Init();
+void Shutdown();
+bool AdditionnalConfigChecks();
index 3d92783..9b2f990 100644 (file)
-#include <cstring>\r
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-struct PInfoState\r
-{\r
-    enum State\r
-    {\r
-        IS_UNKNOWN,\r
-        IS_CONNECTED,\r
-        IS_HANDSHAKE0,\r
-        IS_AUTHENTICATE,\r
-        IS_SERVERLIST\r
-    } mState;\r
-\r
-    bool mWaitSend; // wait-for-completition flag\r
-    PInfoState()\r
-    {\r
-        mState = IS_UNKNOWN;\r
-        mWaitSend = false;\r
-    };\r
-};\r
-\r
-PInfoServer::PInfoServer()\r
-{\r
-    //mNumClients = 1;\r
-    mLivecheckInterval = Config->GetOptionInt("gameserver_livecheck");\r
-}\r
-\r
-PInfoServer::~PInfoServer()\r
-{\r
-    Console->Print("Closing Infoserver...");\r
-\r
-    ServerSock->closeServer();\r
-\r
-    for(InfoStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end(); i++)\r
-        delete i->second;\r
-}\r
-\r
-void PInfoServer::Start()\r
-{\r
-    uint16_t Port = Config->GetOptionInt("infoserver_port");\r
-    Console->LPrint("Starting Infoserver on port %i...", Port);\r
-\r
-    if(ServerSock->open(Port))\r
-    {\r
-        Console->LPrint(GREEN, BLACK, "Success");\r
-        Console->LClose();\r
-    }\r
-    else\r
-    {\r
-        Console->LPrint(RED, BLACK, "Failed");\r
-        Console->LClose();\r
-    }\r
-    ServerSock->settimeout(0, 10000);\r
-    GSLiveCheck();\r
-}\r
-\r
-void PInfoServer::Update()\r
-{\r
-    if(ServerSock->newConnection())\r
-    {\r
-        int32_t clid = Server->NewClient();\r
-        if(clid!=-1)\r
-        {\r
-            Console->Print(GREEN, BLACK, "Infoserver: client [%i] connected", clid);\r
-            PClient *Client = Server->GetClient(clid);\r
-\r
-            ConnectionTCP* tcpConn = ServerSock->getTCPConnection();\r
-            Client->setTCPConnection(tcpConn);\r
-\r
-            Console->Print("Client address: %s", Client->GetAddress());\r
-            //++mNumClients;\r
-\r
-            PInfoState *state = new PInfoState();\r
-            ClientStates.insert(std::make_pair(Client, state));\r
-            state->mState = PInfoState::IS_CONNECTED;\r
-        } else\r
-        {\r
-            Console->Print("Infoserver: Client connection refused (server full?)");\r
-        }\r
-    }\r
-\r
-    for(InfoStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end();)\r
-    {\r
-        PClient *Client = i->first;\r
-        PInfoState *State = i->second;\r
-        // node gets erased in FinalizeClient, increment iterator now\r
-        ++i;\r
-        if(!ProcessClient(Client, State))\r
-            FinalizeClient(Client, State);\r
-    }\r
-}\r
-\r
-void PInfoServer::GSLiveCheck()\r
-{\r
-    MYSQL_ROW row;\r
-    MYSQL_RES *result;\r
-    char query[256];\r
-    snprintf (query, 256, "SELECT *, (NOW()< (`s_lastupdate` + INTERVAL %d SECOND)) FROM `server_list`", mLivecheckInterval);\r
-\r
-    result = MySQL->ResQuery(query);\r
-    if (result == nullptr)\r
-    {\r
-        Console->Print("Livecheck: %s unable to read server list!", Console->ColorText(RED, BLACK, "[Warning]"));\r
-        MySQL->ShowSQLError();\r
-        return;\r
-    }\r
-    if(mysql_num_rows(result) == 0)\r
-    {\r
-        Console->Print("Livecheck: %s no gameserver found!", Console->ColorText(RED, BLACK, "[Warning]"));\r
-        MySQL->FreeSQLResult(result);\r
-        return;\r
-    }\r
-\r
-    ServerMap::iterator it;\r
-    while((row = mysql_fetch_row(result)))\r
-    {\r
-        it = Serverlist.find(atoi(row[s_id]));\r
-        if(it != Serverlist.end())\r
-        {\r
-            strncpy(it->second.mName, row[s_name], MAX_SERVER_NAME_LENGTH);\r
-            it->second.mLanIp = IPStringToDWord(row[s_lanaddr]);\r
-            it->second.mWanIp = IPStringToDWord(row[s_wanaddr]);\r
-            it->second.mPort = atoi(row[s_port]);\r
-            it->second.mPlayers = atoi(row[s_players]);\r
-            /* Prepared for future addon Servers by Accesslevel */\r
-            // it->second.mMinLv = atoi(row[s_minlv]);\r
-            /* ------------------------------------------------ */\r
-\r
-            // ToDo: If statement correct? Maybe GSLiveCheck() has\r
-            // to be called every mLinvecheckInterval seconds.... We'll\r
-            // see when Gameserver has been rewritten\r
-\r
-            if(row[s_timecheck] && (atoi(row[s_timecheck]) == 1))\r
-            {\r
-                it->second.mLasttimestamp = atol(row[s_lastupdate]);\r
-                it->second.mOnline = true;\r
-            }\r
-            else\r
-            {\r
-                it->second.mOnline = false;\r
-            }\r
-\r
-            it->second.mUpdated = true;\r
-        }\r
-        else\r
-        {\r
-            GameServers tmpServer;\r
-\r
-            strncpy(tmpServer.mName, row[s_name], MAX_SERVER_NAME_LENGTH);\r
-            tmpServer.mLanIp = IPStringToDWord(row[s_lanaddr]);\r
-            tmpServer.mWanIp = IPStringToDWord(row[s_wanaddr]);\r
-            tmpServer.mLasttimestamp = atol(row[s_lastupdate]);\r
-            tmpServer.mPlayers = atoi(row[s_players]);\r
-            tmpServer.mPort = atoi(row[s_port]);\r
-            tmpServer.mOnline = true;\r
-            tmpServer.mUpdated = true;\r
-            Console->Print("Added GameServer %s", tmpServer.mName);\r
-            /* Prepared for future addon Servers by Accesslevel */\r
-            //    tmpServer.mMinLv = atoi(row[s_minlv]);\r
-            /* ------------------------------------------------ */\r
-\r
-            Serverlist.insert(std::make_pair(atoi(row[s_id]), tmpServer));\r
-        }\r
-    }\r
-    MySQL->FreeSQLResult(result);\r
-\r
-    for(ServerMap::iterator it = Serverlist.begin(); it != Serverlist.end(); it++)\r
-    {\r
-        if(it->second.mUpdated == false)\r
-            Serverlist.erase(it);\r
-        else\r
-            it->second.mUpdated = false;\r
-    }\r
-\r
-}\r
-\r
-void PInfoServer::ClientDisconnected(PClient *Client)\r
-{\r
-    InfoStateMap::iterator node = ClientStates.find(Client);\r
-    if(node == ClientStates.end())\r
-        return;\r
-\r
-    PInfoState *State = node->second;\r
-    FinalizeClient(Client, State);\r
-}\r
-\r
-bool PInfoServer::HandleHandshake(PInfoState *State, const uint8_t *Packet, int32_t PacketSize)\r
-{\r
-    //static const uint8_t HANDSHAKE1A[6]={0xfe, 0x03, 0x00, 0x80, 0x03, 0x68};\r
-\r
-    switch(State->mState)\r
-    {\r
-        case PInfoState::IS_HANDSHAKE0 :\r
-        {\r
-            if(PacketSize==6 && *(uint16_t*)&Packet[3]==0x0080 && Packet[5]==0x78)\r
-            {\r
-                //FIXME: this packet seems to be unnecessary, although it appears in traffic dumps\r
-                // (causes clientside "Wrong protocol" errors)\r
-                //Socket->Write(HANDSHAKE1A, 6);\r
-                State->mState = PInfoState::IS_AUTHENTICATE;\r
-            }\r
-            else\r
-            {\r
-                Console->Print(RED, BLACK, "Infoserver protocol error (IS_HANDSHAKE0): invalid packet [%04x]", *(uint16_t*)&Packet[3]);\r
-                return false;\r
-            }\r
-            break;\r
-        }\r
-        default:\r
-            break;\r
-    }\r
-\r
-    return true;\r
-}\r
-\r
-bool PInfoServer::HandleAuthenticate(PClient *Client, PInfoState *State, const uint8_t *Packet, int32_t PacketSize)\r
-{\r
-  int32_t returnval = 0;\r
-    // ReturnValue values:\r
-    // 0: No error\r
-    // -1: Wrong/Unknown username\r
-    // -2: Wrong Password\r
-    // -3: Malformed Auth Data. Please relog\r
-    // -4: Database error, contact admin\r
-    // -5: No such account, Account created. Please relog\r
-    // -6: Could not create autoaccount, PW too short\r
-    // -7: Could not create autoaccount, Name too short\r
-    // -8: Could not create autoaccount, PW and Name too short\r
-    // -9: Duplicate entry for Username! Contact Admin\r
-    // -10: User is banned\r
-    // -11: Insufficient access rights\r
-    // -12: Account is not yet activated (accesslevel = 0)\r
-    // -99: General fault. Contact admin\r
-    ConnectionTCP *Socket = Client->getTCPConn();\r
-    PAccount* currentAccount = NULL;\r
-\r
-    if (PacketSize > 20 && *(uint16_t *)&Packet[3] == 0x8084)\r
-    {\r
-        const uint8_t *Key = &Packet[5];         // password key\r
-        uint16_t ULen = *(uint16_t *)&Packet[16];      // username length\r
-        uint16_t PLen = *(uint16_t *)&Packet[18];      // password length\r
-        char *UserName = (char *)&Packet[20];    // account name\r
-        const uint8_t *PW = &Packet[20 + ULen];    // encoded password\r
-\r
-    if (UserName[ULen-1]) // Check that string is well terminated\r
-    {\r
-      Console->Print("Infoserver: Client [%d]: Username was not NULL-terminated !", Client->GetIndex());\r
-      returnval = -1;\r
-    }\r
-    else\r
-    {\r
-      currentAccount = new PAccount(UserName);\r
-      if(!currentAccount->GetID())\r
-      {\r
-        if(Config->GetOptionInt("auto_accounts")) // Autoaccount\r
-        {\r
-          delete currentAccount;\r
-          currentAccount = new PAccount();\r
-\r
-          if(!currentAccount->SetName(UserName)) // !!! len\r
-          {\r
-              returnval = -7;\r
-          }\r
-          if(!currentAccount->SetPasswordEncoded(PW, PLen, Key))\r
-          {\r
-              returnval = returnval ? -8 : -6;\r
-          }\r
-\r
-          if(!returnval)\r
-          {\r
-            if(currentAccount->Create())\r
-            {\r
-              returnval = -5;\r
-            }\r
-            else\r
-            {\r
-              returnval = -4;\r
-            }\r
-          }\r
-        }\r
-        else\r
-        {\r
-          returnval = -1;\r
-        }\r
-      }\r
-      else\r
-      {\r
-        if(currentAccount->Authenticate(PW, PLen, Key))\r
-        { // Username & Password correct\r
-          if(currentAccount->IsBanned())\r
-          {\r
-              returnval = -10;\r
-          }\r
-          else if(currentAccount->GetLevel() < Config->GetOptionInt("minlevel")) // insufficient access rights\r
-          {\r
-              returnval = -11;\r
-          }\r
-          else if(Config->GetOptionInt("require_validation") == 1 && currentAccount->GetLevel() == PAL_UNREGPLAYER)\r
-          {\r
-              returnval = -12;\r
-          }\r
-          else\r
-          {\r
-              Client->setAccountID(currentAccount->GetID());\r
-              returnval = 0;\r
-          }\r
-\r
-        }\r
-        else\r
-        {\r
-          returnval = -2;\r
-        }\r
-      }\r
-    }\r
-\r
-        bool Failed = false;\r
-        if(returnval == 0)\r
-        {\r
-            uint8_t AUTHOK[28]={0xfe, 0x19, 0x00, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\r
-                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
-                            0x00, 0x00, 0x00, 0x00, 0x00 };\r
-            *(uint32_t *)&AUTHOK[5] = currentAccount->GetID();\r
-            Socket->write(AUTHOK, 28);\r
-            State->mState = PInfoState::IS_SERVERLIST;\r
-        }\r
-        else\r
-        {\r
-            Console->Print("Infoserver: User '%s': authentication failed. Errorcode %d", UserName, returnval);\r
-            Failed = true;  // auth failed\r
-        }\r
-        if(Failed == true)\r
-        {\r
-            std::string errorReason;\r
-            switch(returnval)\r
-            {\r
-                // It seems that the client cuts the line off after 40 chars...\r
-//                                 |1       |10       |20       |30       |40       |50       |60       |70       |80\r
-                case -99:\r
-                {\r
-                    //errorReason = "General fault in processing your login request";\r
-                    errorReason = "General fault while login request";\r
-                    break;\r
-                }\r
-                case -12:\r
-                {\r
-                    //errorReason = "Account not activated. Please check your EMails";\r
-                    errorReason = "Error: Your account is not activated";\r
-                    break;\r
-                }\r
-                case -11:\r
-                {\r
-                    //errorReason = "Login rejected. You have to be " + GetAccessString(Config->GetOptionInt("minlevel")) + " or higher";\r
-                    errorReason = "Level " + GetAccessString(Config->GetOptionInt("minlevel")) + " or higher required";\r
-                    break;\r
-                }\r
-                case -10:\r
-                {\r
-                    errorReason = "You are banned for " + currentAccount->GetBannedTime();\r
-                    break;\r
-                }\r
-                case -9:\r
-                {\r
-                    //errorReason = "Duplicate entry for this login. Contact Admin";\r
-                    errorReason = "Duplicate entry found. Contact Admin";\r
-                    break;\r
-                }\r
-                case -8:\r
-                {\r
-                    //errorReason = "Autoaccount failed, name and password too short";\r
-                    errorReason = "AutoAcc failed, name and pwd too short";\r
-                    break;\r
-                }\r
-                case -7:\r
-                {\r
-                    errorReason = "Autoaccount failed, name is too short";\r
-                    break;\r
-                }\r
-                case -6:\r
-                {\r
-                    //errorReason = "Autoaccount failed, password is too short";\r
-                    errorReason = "Autoaccount failed, pwd is too short";\r
-                    break;\r
-                }\r
-                case -5:\r
-                {\r
-                    errorReason = "New Account created, please login again";\r
-                    break;\r
-                }\r
-                case -4:\r
-                {\r
-                    errorReason = "Database error, contact Administrator";\r
-                    break;\r
-                }\r
-                case -3:\r
-                {\r
-                    errorReason = "Malformed AuthData. Please login again";\r
-                    break;\r
-                }\r
-                case -2:\r
-                {\r
-                    errorReason = "Wrong password";\r
-                    break;\r
-                }\r
-                case -1:\r
-                {\r
-                    errorReason = "Unknown username";\r
-                    break;\r
-                }\r
-            }\r
-            uint8_t AUTHFAILED_HEADER[] = {0xfe, 0x0c, 0x00, 0x83, 0x86, 0x05, 0x00, 0x06, 0x00};\r
-            uint8_t AUTHFAILED_FOOTER[] = {0x00, 0x40};\r
-            *(uint16_t *)&AUTHFAILED_HEADER[1] = errorReason.size() + 8;\r
-            *(uint16_t *)&AUTHFAILED_HEADER[7] = errorReason.size() + 1;\r
-            //*(uint8_t*)&AUTHFAILED_FOOTER[1] = {0x40};\r
-\r
-            Socket->write(AUTHFAILED_HEADER, sizeof(AUTHFAILED_HEADER));\r
-            Socket->write(errorReason.c_str(), errorReason.size());\r
-            Socket->write(AUTHFAILED_FOOTER, sizeof(AUTHFAILED_FOOTER));\r
-            FinalizeClientDelayed(Client, State);\r
-            State->mState=PInfoState::IS_UNKNOWN;\r
-        }\r
-    }\r
-    else\r
-    {\r
-        Console->Print(RED, BLACK, "Infoserver protocol error (IS_AUTHENTICATE): invalid packet [%04x]",\r
-                       *(uint16_t *)&Packet[3]);\r
-        return false;\r
-    }\r
-\r
-    return true;\r
-}\r
-\r
-bool PInfoServer::HandleServerList(PClient *Client, const uint8_t *Packet, int32_t PacketSize)\r
-{\r
-    uint8_t SERVERLIST_HEAD[] = {0xfe, 0x00, 0x00, 0x83, 0x83, 0x01, 0x00, 0x0d, 0x00};\r
-    uint8_t SERVERLIST[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
-    uint8_t SERVERLIST_FOOTER[] = {0x00};\r
-\r
-    ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-    uint32_t tID = *(uint32_t *)&Packet[5];\r
-    PAccount* currentAccount = new PAccount(Client->getAccountID());\r
-    uint32_t aID = currentAccount->GetID();\r
-\r
-    if(!aID || (aID != tID))\r
-    {\r
-        Console->Print("%s invalid userID %d (auth with id %d)", Console->ColorText(YELLOW, BLACK, "Warning:"), tID, aID);\r
-        delete currentAccount;\r
-        return false;\r
-    }\r
-\r
-    if(currentAccount->GetLevel() < Config->GetOptionInt("minlevel"))\r
-    {\r
-        Console->Print("%s someone tried to bypass the login process! UserID %d", Console->ColorText(RED, BLACK, "Warning:"), aID);\r
-        delete currentAccount;\r
-        return false;\r
-    }\r
-\r
-  if(PacketSize == 31 && *(uint16_t *)&Packet[3]==0x8284)\r
-    {\r
-    GSLiveCheck(); // Perform livecheck to have up-to-date data\r
-\r
-    int32_t len = 0;\r
-    int32_t num = 0;\r
-    for(ServerMap::iterator it = Serverlist.begin(); it != Serverlist.end(); it++)\r
-    {\r
-        num++;\r
-        len += 14 + strlen(it->second.mName);\r
-    }\r
-\r
-    *(uint16_t *)&SERVERLIST_HEAD[1] = len;\r
-    *(uint8_t *)&SERVERLIST_HEAD[5] = num;\r
-    Socket->write(SERVERLIST_HEAD, sizeof(SERVERLIST_HEAD));\r
-\r
-    for(ServerMap::iterator it = Serverlist.begin(); it != Serverlist.end(); it++)\r
-    {\r
-            /* Prepared for future addon Servers by Accesslevel */\r
-//            if(accesslevel >= it->second.mMinLv)\r
-//            {\r
-            /* ------------------------------------------------ */\r
-            // Todo: Set correct lan/wan IP here!\r
-      *(uint32_t *)&SERVERLIST[0] = it->second.mLanIp;\r
-      *(uint16_t *)&SERVERLIST[4] = it->second.mPort;\r
-      *(uint8_t *)&SERVERLIST[8] = strlen(it->second.mName) + 1;\r
-      *(uint16_t *)&SERVERLIST[9] = it->second.mPlayers;\r
-      if(it->second.mOnline == true)\r
-      {\r
-          Console->Print("Sending server name: %s ip: %s player: %d port: %d online: yes", it->second.mName,\r
-                         IPlongToString(it->second.mLanIp), it->second.mPlayers, it->second.mPort);\r
-          *(uint16_t *)&SERVERLIST[11] = 1;\r
-      }\r
-      else if(it->second.mOnline == false)\r
-      {\r
-          Console->Print("Sending server name: %s ip: %s player: %d port: %d online: no", it->second.mName,\r
-                         IPlongToString(it->second.mLanIp), it->second.mPlayers, it->second.mPort);\r
-          *(uint16_t *)&SERVERLIST[11] = 0;\r
-      }\r
-      Socket->write(SERVERLIST, sizeof(SERVERLIST));\r
-      Socket->write(it->second.mName, strlen(it->second.mName));\r
-      Socket->write(SERVERLIST_FOOTER, sizeof(SERVERLIST_FOOTER));\r
-            /* Prepared for future addon Servers by Accesslevel */\r
-//            }\r
-            /* ------------------------------------------------ */\r
-    }\r
-    }\r
-    else\r
-    {\r
-        Console->Print(RED, BLACK, "Infoserver protocol error (IS_SERVERLIST): invalid packet [%04x]",\r
-                       *(uint16_t *)&Packet[3]);\r
-        delete currentAccount;\r
-        return false;\r
-    }\r
-    delete currentAccount;\r
-    return true;\r
-}\r
-\r
-bool PInfoServer::ProcessClient(PClient *Client, PInfoState *State)\r
-{\r
-    static const uint8_t HANDSHAKE0A[6]={0xfe, 0x03, 0x00, 0x80, 0x01, 0x66};\r
-\r
-    if(!State)\r
-    {\r
-        InfoStateMap::iterator node = ClientStates.find(Client);\r
-        if(node == ClientStates.end())\r
-            return false;\r
-\r
-        State = node->second;\r
-    }\r
-\r
-    ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-    if(State->mWaitSend && Socket->getSendBufferSize()==0)\r
-        return false;\r
-\r
-    if(State->mState==PInfoState::IS_CONNECTED)\r
-    {\r
-        Socket->write(HANDSHAKE0A, 6);\r
-        State->mState = PInfoState::IS_HANDSHAKE0;\r
-    }\r
-\r
-    int32_t PacketSize=0;\r
-    const uint8_t *Packet = Socket->read(&PacketSize);\r
-    if(PacketSize > 0)\r
-    {\r
-        switch(State->mState)\r
-        {\r
-            case PInfoState::IS_HANDSHAKE0:\r
-                return HandleHandshake(State, Packet, PacketSize);\r
-\r
-            case PInfoState::IS_AUTHENTICATE:\r
-                return HandleAuthenticate(Client, State, Packet, PacketSize);\r
-\r
-            case PInfoState::IS_SERVERLIST:\r
-                return HandleServerList(Client, Packet, PacketSize);\r
-            default:\r
-                break;\r
-        }\r
-    }\r
-    return true;\r
-}\r
-\r
-void PInfoServer::FinalizeClient(PClient *Client, PInfoState *State)\r
-{\r
-    Console->Print(RED, BLACK, "Infoserver: client %s disconnected", Client->GetAddress());\r
-    Client->InfoDisconnect();\r
-    ClientStates.erase(Client);\r
-    delete State;\r
-}\r
-\r
-void PInfoServer::FinalizeClientDelayed(PClient *Client, PInfoState *State)\r
-{\r
-    Console->Print("Infoserver: client %i is about to be disconnected", Client->GetIndex());\r
-    State->mWaitSend = true;\r
-}\r
+#include <cstring>
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+struct PInfoState
+{
+    enum State
+    {
+        IS_UNKNOWN,
+        IS_CONNECTED,
+        IS_HANDSHAKE0,
+        IS_AUTHENTICATE,
+        IS_SERVERLIST
+    } mState;
+
+    bool mWaitSend; // wait-for-completition flag
+    PInfoState()
+    {
+        mState = IS_UNKNOWN;
+        mWaitSend = false;
+    };
+};
+
+PInfoServer::PInfoServer()
+{
+    //mNumClients = 1;
+    mLivecheckInterval = Config->GetOptionInt("gameserver_livecheck");
+}
+
+PInfoServer::~PInfoServer()
+{
+    Console->Print("Closing Infoserver...");
+
+    ServerSock->closeServer();
+
+    for(InfoStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end(); i++)
+        delete i->second;
+}
+
+void PInfoServer::Start()
+{
+    uint16_t Port = Config->GetOptionInt("infoserver_port");
+    Console->LPrint("Starting Infoserver on port %i...", Port);
+
+    if(ServerSock->open(Port))
+    {
+        Console->LPrint(GREEN, BLACK, "Success");
+        Console->LClose();
+    }
+    else
+    {
+        Console->LPrint(RED, BLACK, "Failed");
+        Console->LClose();
+    }
+    ServerSock->settimeout(0, 10000);
+    GSLiveCheck();
+}
+
+void PInfoServer::Update()
+{
+    if(ServerSock->newConnection())
+    {
+        int32_t clid = Server->NewClient();
+        if(clid!=-1)
+        {
+            Console->Print(GREEN, BLACK, "Infoserver: client [%i] connected", clid);
+            PClient *Client = Server->GetClient(clid);
+
+            ConnectionTCP* tcpConn = ServerSock->getTCPConnection();
+            Client->setTCPConnection(tcpConn);
+
+            Console->Print("Client address: %s", Client->GetAddress());
+            //++mNumClients;
+
+            PInfoState *state = new PInfoState();
+            ClientStates.insert(std::make_pair(Client, state));
+            state->mState = PInfoState::IS_CONNECTED;
+        } else
+        {
+            Console->Print("Infoserver: Client connection refused (server full?)");
+        }
+    }
+
+    for(InfoStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end();)
+    {
+        PClient *Client = i->first;
+        PInfoState *State = i->second;
+        // node gets erased in FinalizeClient, increment iterator now
+        ++i;
+        if(!ProcessClient(Client, State))
+            FinalizeClient(Client, State);
+    }
+}
+
+void PInfoServer::GSLiveCheck()
+{
+    MYSQL_ROW row;
+    MYSQL_RES *result;
+    char query[256];
+    snprintf (query, 256, "SELECT *, (NOW()< (`s_lastupdate` + INTERVAL %d SECOND)) FROM `server_list`", mLivecheckInterval);
+
+    result = MySQL->ResQuery(query);
+    if (result == nullptr)
+    {
+        Console->Print("Livecheck: %s unable to read server list!", Console->ColorText(RED, BLACK, "[Warning]"));
+        MySQL->ShowSQLError();
+        return;
+    }
+    if(mysql_num_rows(result) == 0)
+    {
+        Console->Print("Livecheck: %s no gameserver found!", Console->ColorText(RED, BLACK, "[Warning]"));
+        MySQL->FreeSQLResult(result);
+        return;
+    }
+
+    ServerMap::iterator it;
+    while((row = mysql_fetch_row(result)))
+    {
+        it = Serverlist.find(atoi(row[s_id]));
+        if(it != Serverlist.end())
+        {
+            strncpy(it->second.mName, row[s_name], MAX_SERVER_NAME_LENGTH);
+            it->second.mLanIp = IPStringToDWord(row[s_lanaddr]);
+            it->second.mWanIp = IPStringToDWord(row[s_wanaddr]);
+            it->second.mPort = atoi(row[s_port]);
+            it->second.mPlayers = atoi(row[s_players]);
+            /* Prepared for future addon Servers by Accesslevel */
+            // it->second.mMinLv = atoi(row[s_minlv]);
+            /* ------------------------------------------------ */
+
+            // ToDo: If statement correct? Maybe GSLiveCheck() has
+            // to be called every mLinvecheckInterval seconds.... We'll
+            // see when Gameserver has been rewritten
+
+            if(row[s_timecheck] && (atoi(row[s_timecheck]) == 1))
+            {
+                it->second.mLasttimestamp = atol(row[s_lastupdate]);
+                it->second.mOnline = true;
+            }
+            else
+            {
+                it->second.mOnline = false;
+            }
+
+            it->second.mUpdated = true;
+        }
+        else
+        {
+            GameServers tmpServer;
+
+            strncpy(tmpServer.mName, row[s_name], MAX_SERVER_NAME_LENGTH);
+            tmpServer.mLanIp = IPStringToDWord(row[s_lanaddr]);
+            tmpServer.mWanIp = IPStringToDWord(row[s_wanaddr]);
+            tmpServer.mLasttimestamp = atol(row[s_lastupdate]);
+            tmpServer.mPlayers = atoi(row[s_players]);
+            tmpServer.mPort = atoi(row[s_port]);
+            tmpServer.mOnline = true;
+            tmpServer.mUpdated = true;
+            Console->Print("Added GameServer %s", tmpServer.mName);
+            /* Prepared for future addon Servers by Accesslevel */
+            //    tmpServer.mMinLv = atoi(row[s_minlv]);
+            /* ------------------------------------------------ */
+
+            Serverlist.insert(std::make_pair(atoi(row[s_id]), tmpServer));
+        }
+    }
+    MySQL->FreeSQLResult(result);
+
+    for(ServerMap::iterator it = Serverlist.begin(); it != Serverlist.end(); it++)
+    {
+        if(it->second.mUpdated == false)
+            Serverlist.erase(it);
+        else
+            it->second.mUpdated = false;
+    }
+
+}
+
+void PInfoServer::ClientDisconnected(PClient *Client)
+{
+    InfoStateMap::iterator node = ClientStates.find(Client);
+    if(node == ClientStates.end())
+        return;
+
+    PInfoState *State = node->second;
+    FinalizeClient(Client, State);
+}
+
+bool PInfoServer::HandleHandshake(PInfoState *State, const uint8_t *Packet, int32_t PacketSize)
+{
+    //static const uint8_t HANDSHAKE1A[6]={0xfe, 0x03, 0x00, 0x80, 0x03, 0x68};
+
+    switch(State->mState)
+    {
+        case PInfoState::IS_HANDSHAKE0 :
+        {
+            if(PacketSize==6 && *(uint16_t*)&Packet[3]==0x0080 && Packet[5]==0x78)
+            {
+                //FIXME: this packet seems to be unnecessary, although it appears in traffic dumps
+                // (causes clientside "Wrong protocol" errors)
+                //Socket->Write(HANDSHAKE1A, 6);
+                State->mState = PInfoState::IS_AUTHENTICATE;
+            }
+            else
+            {
+                Console->Print(RED, BLACK, "Infoserver protocol error (IS_HANDSHAKE0): invalid packet [%04x]", *(uint16_t*)&Packet[3]);
+                return false;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+
+    return true;
+}
+
+bool PInfoServer::HandleAuthenticate(PClient *Client, PInfoState *State, const uint8_t *Packet, int32_t PacketSize)
+{
+  int32_t returnval = 0;
+    // ReturnValue values:
+    // 0: No error
+    // -1: Wrong/Unknown username
+    // -2: Wrong Password
+    // -3: Malformed Auth Data. Please relog
+    // -4: Database error, contact admin
+    // -5: No such account, Account created. Please relog
+    // -6: Could not create autoaccount, PW too short
+    // -7: Could not create autoaccount, Name too short
+    // -8: Could not create autoaccount, PW and Name too short
+    // -9: Duplicate entry for Username! Contact Admin
+    // -10: User is banned
+    // -11: Insufficient access rights
+    // -12: Account is not yet activated (accesslevel = 0)
+    // -99: General fault. Contact admin
+    ConnectionTCP *Socket = Client->getTCPConn();
+    PAccount* currentAccount = NULL;
+
+    if (PacketSize > 20 && *(uint16_t *)&Packet[3] == 0x8084)
+    {
+        const uint8_t *Key = &Packet[5];         // password key
+        uint16_t ULen = *(uint16_t *)&Packet[16];      // username length
+        uint16_t PLen = *(uint16_t *)&Packet[18];      // password length
+        char *UserName = (char *)&Packet[20];    // account name
+        const uint8_t *PW = &Packet[20 + ULen];    // encoded password
+
+    if (UserName[ULen-1]) // Check that string is well terminated
+    {
+      Console->Print("Infoserver: Client [%d]: Username was not NULL-terminated !", Client->GetIndex());
+      returnval = -1;
+    }
+    else
+    {
+      currentAccount = new PAccount(UserName);
+      if(!currentAccount->GetID())
+      {
+        if(Config->GetOptionInt("auto_accounts")) // Autoaccount
+        {
+          delete currentAccount;
+          currentAccount = new PAccount();
+
+          if(!currentAccount->SetName(UserName)) // !!! len
+          {
+              returnval = -7;
+          }
+          if(!currentAccount->SetPasswordEncoded(PW, PLen, Key))
+          {
+              returnval = returnval ? -8 : -6;
+          }
+
+          if(!returnval)
+          {
+            if(currentAccount->Create())
+            {
+              returnval = -5;
+            }
+            else
+            {
+              returnval = -4;
+            }
+          }
+        }
+        else
+        {
+          returnval = -1;
+        }
+      }
+      else
+      {
+        if(currentAccount->Authenticate(PW, PLen, Key))
+        { // Username & Password correct
+          if(currentAccount->IsBanned())
+          {
+              returnval = -10;
+          }
+          else if(currentAccount->GetLevel() < Config->GetOptionInt("minlevel")) // insufficient access rights
+          {
+              returnval = -11;
+          }
+          else if(Config->GetOptionInt("require_validation") == 1 && currentAccount->GetLevel() == PAL_UNREGPLAYER)
+          {
+              returnval = -12;
+          }
+          else
+          {
+              Client->setAccountID(currentAccount->GetID());
+              returnval = 0;
+          }
+
+        }
+        else
+        {
+          returnval = -2;
+        }
+      }
+    }
+
+        bool Failed = false;
+        if(returnval == 0)
+        {
+            uint8_t AUTHOK[28]={0xfe, 0x19, 0x00, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00, 0x00 };
+            *(uint32_t *)&AUTHOK[5] = currentAccount->GetID();
+            Socket->write(AUTHOK, 28);
+            State->mState = PInfoState::IS_SERVERLIST;
+        }
+        else
+        {
+            Console->Print("Infoserver: User '%s': authentication failed. Errorcode %d", UserName, returnval);
+            Failed = true;  // auth failed
+        }
+        if(Failed == true)
+        {
+            std::string errorReason;
+            switch(returnval)
+            {
+                // It seems that the client cuts the line off after 40 chars...
+//                                 |1       |10       |20       |30       |40       |50       |60       |70       |80
+                case -99:
+                {
+                    //errorReason = "General fault in processing your login request";
+                    errorReason = "General fault while login request";
+                    break;
+                }
+                case -12:
+                {
+                    //errorReason = "Account not activated. Please check your EMails";
+                    errorReason = "Error: Your account is not activated";
+                    break;
+                }
+                case -11:
+                {
+                    //errorReason = "Login rejected. You have to be " + GetAccessString(Config->GetOptionInt("minlevel")) + " or higher";
+                    errorReason = "Level " + GetAccessString(Config->GetOptionInt("minlevel")) + " or higher required";
+                    break;
+                }
+                case -10:
+                {
+                    errorReason = "You are banned for " + currentAccount->GetBannedTime();
+                    break;
+                }
+                case -9:
+                {
+                    //errorReason = "Duplicate entry for this login. Contact Admin";
+                    errorReason = "Duplicate entry found. Contact Admin";
+                    break;
+                }
+                case -8:
+                {
+                    //errorReason = "Autoaccount failed, name and password too short";
+                    errorReason = "AutoAcc failed, name and pwd too short";
+                    break;
+                }
+                case -7:
+                {
+                    errorReason = "Autoaccount failed, name is too short";
+                    break;
+                }
+                case -6:
+                {
+                    //errorReason = "Autoaccount failed, password is too short";
+                    errorReason = "Autoaccount failed, pwd is too short";
+                    break;
+                }
+                case -5:
+                {
+                    errorReason = "New Account created, please login again";
+                    break;
+                }
+                case -4:
+                {
+                    errorReason = "Database error, contact Administrator";
+                    break;
+                }
+                case -3:
+                {
+                    errorReason = "Malformed AuthData. Please login again";
+                    break;
+                }
+                case -2:
+                {
+                    errorReason = "Wrong password";
+                    break;
+                }
+                case -1:
+                {
+                    errorReason = "Unknown username";
+                    break;
+                }
+            }
+            uint8_t AUTHFAILED_HEADER[] = {0xfe, 0x0c, 0x00, 0x83, 0x86, 0x05, 0x00, 0x06, 0x00};
+            uint8_t AUTHFAILED_FOOTER[] = {0x00, 0x40};
+            *(uint16_t *)&AUTHFAILED_HEADER[1] = errorReason.size() + 8;
+            *(uint16_t *)&AUTHFAILED_HEADER[7] = errorReason.size() + 1;
+            //*(uint8_t*)&AUTHFAILED_FOOTER[1] = {0x40};
+
+            Socket->write(AUTHFAILED_HEADER, sizeof(AUTHFAILED_HEADER));
+            Socket->write(errorReason.c_str(), errorReason.size());
+            Socket->write(AUTHFAILED_FOOTER, sizeof(AUTHFAILED_FOOTER));
+            FinalizeClientDelayed(Client, State);
+            State->mState=PInfoState::IS_UNKNOWN;
+        }
+    }
+    else
+    {
+        Console->Print(RED, BLACK, "Infoserver protocol error (IS_AUTHENTICATE): invalid packet [%04x]",
+                       *(uint16_t *)&Packet[3]);
+        return false;
+    }
+
+    return true;
+}
+
+bool PInfoServer::HandleServerList(PClient *Client, const uint8_t *Packet, int32_t PacketSize)
+{
+    uint8_t SERVERLIST_HEAD[] = {0xfe, 0x00, 0x00, 0x83, 0x83, 0x01, 0x00, 0x0d, 0x00};
+    uint8_t SERVERLIST[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    uint8_t SERVERLIST_FOOTER[] = {0x00};
+
+    ConnectionTCP *Socket = Client->getTCPConn();
+
+    uint32_t tID = *(uint32_t *)&Packet[5];
+    PAccount* currentAccount = new PAccount(Client->getAccountID());
+    uint32_t aID = currentAccount->GetID();
+
+    if(!aID || (aID != tID))
+    {
+        Console->Print("%s invalid userID %d (auth with id %d)", Console->ColorText(YELLOW, BLACK, "Warning:"), tID, aID);
+        delete currentAccount;
+        return false;
+    }
+
+    if(currentAccount->GetLevel() < Config->GetOptionInt("minlevel"))
+    {
+        Console->Print("%s someone tried to bypass the login process! UserID %d", Console->ColorText(RED, BLACK, "Warning:"), aID);
+        delete currentAccount;
+        return false;
+    }
+
+  if(PacketSize == 31 && *(uint16_t *)&Packet[3]==0x8284)
+    {
+    GSLiveCheck(); // Perform livecheck to have up-to-date data
+
+    int32_t len = 0;
+    int32_t num = 0;
+    for(ServerMap::iterator it = Serverlist.begin(); it != Serverlist.end(); it++)
+    {
+        num++;
+        len += 14 + strlen(it->second.mName);
+    }
+
+    *(uint16_t *)&SERVERLIST_HEAD[1] = len;
+    *(uint8_t *)&SERVERLIST_HEAD[5] = num;
+    Socket->write(SERVERLIST_HEAD, sizeof(SERVERLIST_HEAD));
+
+    for(ServerMap::iterator it = Serverlist.begin(); it != Serverlist.end(); it++)
+    {
+            /* Prepared for future addon Servers by Accesslevel */
+//            if(accesslevel >= it->second.mMinLv)
+//            {
+            /* ------------------------------------------------ */
+            // Todo: Set correct lan/wan IP here!
+      *(uint32_t *)&SERVERLIST[0] = it->second.mLanIp;
+      *(uint16_t *)&SERVERLIST[4] = it->second.mPort;
+      *(uint8_t *)&SERVERLIST[8] = strlen(it->second.mName) + 1;
+      *(uint16_t *)&SERVERLIST[9] = it->second.mPlayers;
+      if(it->second.mOnline == true)
+      {
+          Console->Print("Sending server name: %s ip: %s player: %d port: %d online: yes", it->second.mName,
+                         IPlongToString(it->second.mLanIp), it->second.mPlayers, it->second.mPort);
+          *(uint16_t *)&SERVERLIST[11] = 1;
+      }
+      else if(it->second.mOnline == false)
+      {
+          Console->Print("Sending server name: %s ip: %s player: %d port: %d online: no", it->second.mName,
+                         IPlongToString(it->second.mLanIp), it->second.mPlayers, it->second.mPort);
+          *(uint16_t *)&SERVERLIST[11] = 0;
+      }
+      Socket->write(SERVERLIST, sizeof(SERVERLIST));
+      Socket->write(it->second.mName, strlen(it->second.mName));
+      Socket->write(SERVERLIST_FOOTER, sizeof(SERVERLIST_FOOTER));
+            /* Prepared for future addon Servers by Accesslevel */
+//            }
+            /* ------------------------------------------------ */
+    }
+    }
+    else
+    {
+        Console->Print(RED, BLACK, "Infoserver protocol error (IS_SERVERLIST): invalid packet [%04x]",
+                       *(uint16_t *)&Packet[3]);
+        delete currentAccount;
+        return false;
+    }
+    delete currentAccount;
+    return true;
+}
+
+bool PInfoServer::ProcessClient(PClient *Client, PInfoState *State)
+{
+    static const uint8_t HANDSHAKE0A[6]={0xfe, 0x03, 0x00, 0x80, 0x01, 0x66};
+
+    if(!State)
+    {
+        InfoStateMap::iterator node = ClientStates.find(Client);
+        if(node == ClientStates.end())
+            return false;
+
+        State = node->second;
+    }
+
+    ConnectionTCP *Socket = Client->getTCPConn();
+
+    if(State->mWaitSend && Socket->getSendBufferSize()==0)
+        return false;
+
+    if(State->mState==PInfoState::IS_CONNECTED)
+    {
+        Socket->write(HANDSHAKE0A, 6);
+        State->mState = PInfoState::IS_HANDSHAKE0;
+    }
+
+    int32_t PacketSize=0;
+    const uint8_t *Packet = Socket->read(&PacketSize);
+    if(PacketSize > 0)
+    {
+        switch(State->mState)
+        {
+            case PInfoState::IS_HANDSHAKE0:
+                return HandleHandshake(State, Packet, PacketSize);
+
+            case PInfoState::IS_AUTHENTICATE:
+                return HandleAuthenticate(Client, State, Packet, PacketSize);
+
+            case PInfoState::IS_SERVERLIST:
+                return HandleServerList(Client, Packet, PacketSize);
+            default:
+                break;
+        }
+    }
+    return true;
+}
+
+void PInfoServer::FinalizeClient(PClient *Client, PInfoState *State)
+{
+    Console->Print(RED, BLACK, "Infoserver: client %s disconnected", Client->GetAddress());
+    Client->InfoDisconnect();
+    ClientStates.erase(Client);
+    delete State;
+}
+
+void PInfoServer::FinalizeClientDelayed(PClient *Client, PInfoState *State)
+{
+    Console->Print("Infoserver: client %i is about to be disconnected", Client->GetIndex());
+    State->mWaitSend = true;
+}
index 350391b..3295d7b 100644 (file)
@@ -1,64 +1,64 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-\r
-class PClient;\r
-struct PInfoState;\r
-\r
-#define MAX_SERVER_NAME_LENGTH 45\r
-struct GameServers {\r
-    char  mName[MAX_SERVER_NAME_LENGTH];\r
-    uint32_t mLanIp;\r
-    uint32_t mWanIp;\r
-    int16_t mPort;\r
-    int32_t mPlayers;\r
-    bool mOnline;\r
-    bool mUpdated;\r
-    time_t mLasttimestamp;\r
-/* Prepared for future addon Servers by Accesslevel */\r
-//    int             mMinLv;\r
-/* ------------------------------------------------ */\r
-};\r
-\r
-class PInfoServer {\r
-private:\r
-    // SQL layout\r
-    enum {\r
-        s_id,\r
-        s_name,\r
-        s_wanaddr,\r
-        s_port,\r
-        s_players,\r
-        s_lastupdate,\r
-        s_lanaddr,\r
-        s_timecheck // computed field, not in table !\r
-    };\r
-    //int mNumClients;\r
-    typedef std::map<PClient *, struct PInfoState *> InfoStateMap;\r
-    InfoStateMap ClientStates;\r
-\r
-    typedef std::map<int32_t, GameServers> ServerMap;\r
-    ServerMap Serverlist;\r
-\r
-    //time_t mLastLivecheck;\r
-    int mLivecheckInterval;\r
-    void GSLiveCheck();\r
-\r
-protected:\r
-    bool ProcessClient(PClient *Client, PInfoState *State = nullptr);\r
-    void FinalizeClient(PClient *Client, PInfoState *State);\r
-    void FinalizeClientDelayed(PClient *Client, PInfoState *State);\r
-\r
-    bool HandleHandshake(PInfoState *State, const uint8_t *Packet, int32_t PacketSize);\r
-    bool HandleAuthenticate(PClient *Client, PInfoState *State, const uint8_t *Packet, int32_t PacketSize);\r
-    bool HandleServerList(PClient *Client, const uint8_t *Packet, int32_t PacketSize);\r
-\r
-public:\r
-    PInfoServer();\r
-    ~PInfoServer();\r
-\r
-    void Start();\r
-    void Update();\r
-    void ClientDisconnected(PClient *Client);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+class PClient;
+struct PInfoState;
+
+#define MAX_SERVER_NAME_LENGTH 45
+struct GameServers {
+    char  mName[MAX_SERVER_NAME_LENGTH];
+    uint32_t mLanIp;
+    uint32_t mWanIp;
+    int16_t mPort;
+    int32_t mPlayers;
+    bool mOnline;
+    bool mUpdated;
+    time_t mLasttimestamp;
+/* Prepared for future addon Servers by Accesslevel */
+//    int             mMinLv;
+/* ------------------------------------------------ */
+};
+
+class PInfoServer {
+private:
+    // SQL layout
+    enum {
+        s_id,
+        s_name,
+        s_wanaddr,
+        s_port,
+        s_players,
+        s_lastupdate,
+        s_lanaddr,
+        s_timecheck // computed field, not in table !
+    };
+    //int mNumClients;
+    typedef std::map<PClient *, struct PInfoState *> InfoStateMap;
+    InfoStateMap ClientStates;
+
+    typedef std::map<int32_t, GameServers> ServerMap;
+    ServerMap Serverlist;
+
+    //time_t mLastLivecheck;
+    int mLivecheckInterval;
+    void GSLiveCheck();
+
+protected:
+    bool ProcessClient(PClient *Client, PInfoState *State = nullptr);
+    void FinalizeClient(PClient *Client, PInfoState *State);
+    void FinalizeClientDelayed(PClient *Client, PInfoState *State);
+
+    bool HandleHandshake(PInfoState *State, const uint8_t *Packet, int32_t PacketSize);
+    bool HandleAuthenticate(PClient *Client, PInfoState *State, const uint8_t *Packet, int32_t PacketSize);
+    bool HandleServerList(PClient *Client, const uint8_t *Packet, int32_t PacketSize);
+
+public:
+    PInfoServer();
+    ~PInfoServer();
+
+    void Start();
+    void Update();
+    void ClientDisconnected(PClient *Client);
+};
index 0c87d5e..1f79e9a 100644 (file)
@@ -1,35 +1,35 @@
-#include <csignal>\r
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void signal_handler(int signal)\r
-{\r
-    if (signal == SIGINT)\r
-        Shutdown();\r
-}\r
-\r
-int main()\r
-{\r
-    signal(SIGINT, signal_handler);\r
-\r
-    if (!Init())\r
-    {\r
-        if(Console)\r
-            Console->Print("%s Aborting startup.", Console->ColorText(RED, BLACK, "[Fatal]"));\r
-        Shutdown(); // exits with 0 ...\r
-    }\r
-\r
-    InfoServer->Start();\r
-    Console->Print("Infoserver is now %s. Waiting for clients...", Console->ColorText(GREEN, BLACK, "Online"));\r
-\r
-    while (true)\r
-    {\r
-        ServerSock->update();\r
-        Server->Update();\r
-        InfoServer->Update();\r
-        MySQL->Update(); // MySQL keepalive\r
-        Console->Update();\r
-    }\r
-\r
-    return 0;\r
-}\r
+#include <csignal>
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void signal_handler(int signal)
+{
+    if (signal == SIGINT)
+        Shutdown();
+}
+
+int main()
+{
+    signal(SIGINT, signal_handler);
+
+    if (!Init())
+    {
+        if(Console)
+            Console->Print("%s Aborting startup.", Console->ColorText(RED, BLACK, "[Fatal]"));
+        Shutdown(); // exits with 0 ...
+    }
+
+    InfoServer->Start();
+    Console->Print("Infoserver is now %s. Waiting for clients...", Console->ColorText(GREEN, BLACK, "Online"));
+
+    while (true)
+    {
+        ServerSock->update();
+        Server->Update();
+        InfoServer->Update();
+        MySQL->Update(); // MySQL keepalive
+        Console->Update();
+    }
+
+    return 0;
+}
index 370063f..0c9d3e0 100644 (file)
@@ -1,80 +1,80 @@
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PServer::PServer()\r
-{\r
-  mMaxClients = Config->GetOptionInt("maxclients");\r
-\r
-    mClients.reserve(mMaxClients);\r
-    mNumClients = 0;\r
-    for (int32_t i=0; i<mMaxClients; i++)\r
-        mClients[i]=0;\r
-}\r
-\r
-PServer::~PServer()\r
-{\r
-    for (int32_t i=0; i<mMaxClients; i++)\r
-        delete mClients[i];\r
-}\r
-\r
-int32_t PServer::GetNumClients() const\r
-{\r
-    return mNumClients;\r
-}\r
-\r
-int PServer::NewClient()\r
-{\r
-    if(mNumClients==mMaxClients)\r
-        return -1;\r
-\r
-    for (int32_t i=0; i<mMaxClients; i++)\r
-    {\r
-        if(!mClients[i])\r
-        {\r
-            mClients[i]=new PClient(i);\r
-            ++mNumClients;\r
-            return i;\r
-        }\r
-    }\r
-    return -1;\r
-}\r
-\r
-PClient *PServer::GetClient(int32_t Client) const\r
-{\r
-    if (Client < 0 || Client >= mMaxClients)\r
-        return 0;\r
-\r
-    return mClients[Client];\r
-}\r
-\r
-void PServer::Update()\r
-{\r
-    for (int32_t i=0; i<mMaxClients; i++)\r
-    {\r
-        if(mClients[i])\r
-        {\r
-            mClients[i]->Update();\r
-            if(mClients[i]->GetConnection()==PCC_NONE && mClients[i]->getTCPConn() == 0)\r
-            {\r
-                Console->Print("Removing client ...");\r
-                delete mClients[i];\r
-                mClients[i]=0;\r
-                --mNumClients;\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PServer::Shutdown()\r
-{\r
-    Console->Print("======================");\r
-    Console->Print("Shutting down Infoserver...");\r
-    for (int32_t i=0; i<mMaxClients; i++)\r
-    {\r
-        if(mClients[i])\r
-        {\r
-            delete mClients[i];\r
-            mClients[i]=0;\r
-        }\r
-    }\r
-}\r
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PServer::PServer()
+{
+  mMaxClients = Config->GetOptionInt("maxclients");
+
+    mClients.reserve(mMaxClients);
+    mNumClients = 0;
+    for (int32_t i=0; i<mMaxClients; i++)
+        mClients[i]=0;
+}
+
+PServer::~PServer()
+{
+    for (int32_t i=0; i<mMaxClients; i++)
+        delete mClients[i];
+}
+
+int32_t PServer::GetNumClients() const
+{
+    return mNumClients;
+}
+
+int PServer::NewClient()
+{
+    if(mNumClients==mMaxClients)
+        return -1;
+
+    for (int32_t i=0; i<mMaxClients; i++)
+    {
+        if(!mClients[i])
+        {
+            mClients[i]=new PClient(i);
+            ++mNumClients;
+            return i;
+        }
+    }
+    return -1;
+}
+
+PClient *PServer::GetClient(int32_t Client) const
+{
+    if (Client < 0 || Client >= mMaxClients)
+        return 0;
+
+    return mClients[Client];
+}
+
+void PServer::Update()
+{
+    for (int32_t i=0; i<mMaxClients; i++)
+    {
+        if(mClients[i])
+        {
+            mClients[i]->Update();
+            if(mClients[i]->GetConnection()==PCC_NONE && mClients[i]->getTCPConn() == 0)
+            {
+                Console->Print("Removing client ...");
+                delete mClients[i];
+                mClients[i]=0;
+                --mNumClients;
+            }
+        }
+    }
+}
+
+void PServer::Shutdown()
+{
+    Console->Print("======================");
+    Console->Print("Shutting down Infoserver...");
+    for (int32_t i=0; i<mMaxClients; i++)
+    {
+        if(mClients[i])
+        {
+            delete mClients[i];
+            mClients[i]=0;
+        }
+    }
+}
index c027fbb..8d261b6 100644 (file)
@@ -1,23 +1,23 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <vector>\r
-\r
-class PClient;\r
-\r
-class PServer {\r
-private:\r
-    int32_t mMaxClients;\r
-    int32_t mNumClients;\r
-    std::vector<PClient *> mClients;\r
-\r
-public:\r
-    PServer();\r
-    ~PServer();\r
-\r
-    int32_t GetNumClients() const;\r
-    int32_t NewClient();\r
-    PClient *GetClient(int32_t Client) const;\r
-    void Update();\r
-    void Shutdown();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+class PClient;
+
+class PServer {
+private:
+    int32_t mMaxClients;
+    int32_t mNumClients;
+    std::vector<PClient *> mClients;
+
+public:
+    PServer();
+    ~PServer();
+
+    int32_t GetNumClients() const;
+    int32_t NewClient();
+    PClient *GetClient(int32_t Client) const;
+    void Update();
+    void Shutdown();
+};
index 6dbdf96..d43c4e4 100644 (file)
-#include <cstring>\r
-#include "InfoServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PMySQL::PMySQL()\r
-{\r
-    port = Config->GetOptionInt("sql_port");\r
-    strncpy(host, Config->GetOption("sql_host").c_str(), 100);\r
-    strncpy(userName, Config->GetOption("sql_username").c_str(), 100);\r
-    strncpy(password, Config->GetOption("sql_password").c_str(), 100);\r
-    strncpy(database, Config->GetOption("global_sql_database").c_str(), 100);\r
-\r
-    mKeepaliveDelay = (time_t) (Config->GetOptionInt("mysql_wait_timeout") * 0.9) ; // we take 90% of the wait_timeout to trigger keepalive\r
-    if (mKeepaliveDelay == 0)\r
-    {\r
-      Console->Print("%s MySQL keepalive disabled by config", Console->ColorText(GREEN, BLACK, "[Info]"));\r
-    }\r
-    else if (mKeepaliveDelay < 60)\r
-    {\r
-      Console->Print("%s Configuration option 'mysql_wait_timeout' is too low (%d sec). Reset to 60 sec.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mKeepaliveDelay);\r
-      mKeepaliveDelay = 60;\r
-    }\r
-    mLastKeepaliveSent = 0;\r
-}\r
-\r
-PMySQL::~PMySQL()\r
-{\r
-    Console->Print("Closing MySQL connection...");\r
-    mysql_close(dbHandle);\r
-}\r
-\r
-void PMySQL::Update()\r
-{\r
-    // MySQL keepalive\r
-    time_t t = std::time(NULL);\r
-    if ((mKeepaliveDelay > 0) && ((t - mLastKeepaliveSent) > mKeepaliveDelay))\r
-    {\r
-      MYSQL_RES *result;\r
-      char query[24];\r
-      snprintf (query, 24, "SELECT NOW()");\r
-\r
-      result = ResQuery(query);\r
-      if(!result)\r
-      {\r
-          Console->Print("%s Can't send InfoDB keepalive; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));\r
-          ShowSQLError();\r
-          return;\r
-      }\r
-      else\r
-        FreeSQLResult(result);\r
-\r
-      mLastKeepaliveSent = std::time(NULL);\r
-//Console->Print("%s MySQL keepalive sent", Console->ColorText(GREEN, BLACK, "[Debug]"));\r
-    }\r
-}\r
-\r
-MYSQL *PMySQL::GetHandle()\r
-{\r
-    return dbHandle;\r
-}\r
-\r
-bool PMySQL::Connect()\r
-{\r
-    Console->LPrint("Establishing link to MySQL Database...");\r
-\r
-    dbHandle = mysql_init(NULL);\r
-\r
-    if(dbHandle)\r
-    {\r
-        //Console->Print("MySQL-Handle successfully initialized.");\r
-    }\r
-    else\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LClose();\r
-        Console->Print(" MySQL-Handle couldn't be created!");\r
-        exit(0);\r
-    }\r
-\r
-    if(!mysql_real_connect(dbHandle, host, userName, password, database, port, NULL, 0))\r
-    {\r
-        Console->LPrint(RED, BLACK, "[ERROR]");\r
-        Console->LClose();\r
-        Console->Print("Unable to connect to MySQL Database. MySQL returned: %s", mysql_error(dbHandle));\r
-        return false;\r
-    }\r
-    else\r
-    {\r
-        Console->LPrint(GREEN, BLACK, "Success");\r
-        Console->LClose();\r
-        return true;\r
-    }\r
-}\r
-\r
-MYSQL_RES *PMySQL::ResQuery(const char *query)\r
-{\r
-    int32_t sql_result = 0;\r
-    MYSQL_RES *result;\r
-\r
-    sql_result = mysql_real_query(dbHandle, query, strlen(query));\r
-    if(sql_result)\r
-    {\r
-        return NULL;\r
-    }\r
-    result = mysql_store_result(dbHandle);\r
-    if(!result)\r
-    {\r
-        return NULL;\r
-    }\r
-\r
-    return result;\r
-}\r
-\r
-int32_t PMySQL::Query(const char *query)\r
-{\r
-    int32_t sql_result = 0;\r
-    sql_result = mysql_real_query(dbHandle, query, strlen(query));\r
-\r
-    return sql_result;\r
-}\r
-\r
-void PMySQL::ShowSQLError()\r
-{\r
-    Console->Print(RED, BLACK, "MySQL Error: %s", mysql_error(dbHandle));\r
-}\r
-\r
-void PMySQL::FreeSQLResult(MYSQL_RES *res)\r
-{\r
-  mysql_free_result(res);\r
-}\r
-\r
-uint32_t PMySQL::GetLastInsertId()\r
-{\r
-    return mysql_insert_id(dbHandle);\r
-}\r
-\r
-uint32_t PMySQL::EscapeString(const char *nText, char *dText, uint32_t dMaxLength)\r
-{\r
-  uint32_t nLength = strlen(nText);\r
-  uint32_t tMax = (dMaxLength - 1)/2;\r
-  if(nLength > tMax)\r
-  {\r
-    nLength = tMax;\r
-  }\r
-\r
-  return mysql_real_escape_string(dbHandle, dText, nText, nLength);\r
-}\r
+#include <cstring>
+#include "InfoServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PMySQL::PMySQL()
+{
+    port = Config->GetOptionInt("sql_port");
+    strncpy(host, Config->GetOption("sql_host").c_str(), 100);
+    strncpy(userName, Config->GetOption("sql_username").c_str(), 100);
+    strncpy(password, Config->GetOption("sql_password").c_str(), 100);
+    strncpy(database, Config->GetOption("global_sql_database").c_str(), 100);
+
+    mKeepaliveDelay = (time_t) (Config->GetOptionInt("mysql_wait_timeout") * 0.9) ; // we take 90% of the wait_timeout to trigger keepalive
+    if (mKeepaliveDelay == 0)
+    {
+      Console->Print("%s MySQL keepalive disabled by config", Console->ColorText(GREEN, BLACK, "[Info]"));
+    }
+    else if (mKeepaliveDelay < 60)
+    {
+      Console->Print("%s Configuration option 'mysql_wait_timeout' is too low (%d sec). Reset to 60 sec.", Console->ColorText(YELLOW, BLACK, "[Notice]"), mKeepaliveDelay);
+      mKeepaliveDelay = 60;
+    }
+    mLastKeepaliveSent = 0;
+}
+
+PMySQL::~PMySQL()
+{
+    Console->Print("Closing MySQL connection...");
+    mysql_close(dbHandle);
+}
+
+void PMySQL::Update()
+{
+    // MySQL keepalive
+    time_t t = std::time(NULL);
+    if ((mKeepaliveDelay > 0) && ((t - mLastKeepaliveSent) > mKeepaliveDelay))
+    {
+      MYSQL_RES *result;
+      char query[24];
+      snprintf (query, 24, "SELECT NOW()");
+
+      result = ResQuery(query);
+      if(!result)
+      {
+          Console->Print("%s Can't send InfoDB keepalive; MySQL returned", Console->ColorText(RED, BLACK, "[Error]"));
+          ShowSQLError();
+          return;
+      }
+      else
+        FreeSQLResult(result);
+
+      mLastKeepaliveSent = std::time(NULL);
+//Console->Print("%s MySQL keepalive sent", Console->ColorText(GREEN, BLACK, "[Debug]"));
+    }
+}
+
+MYSQL *PMySQL::GetHandle()
+{
+    return dbHandle;
+}
+
+bool PMySQL::Connect()
+{
+    Console->LPrint("Establishing link to MySQL Database...");
+
+    dbHandle = mysql_init(NULL);
+
+    if(dbHandle)
+    {
+        //Console->Print("MySQL-Handle successfully initialized.");
+    }
+    else
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LClose();
+        Console->Print(" MySQL-Handle couldn't be created!");
+        exit(0);
+    }
+
+    if(!mysql_real_connect(dbHandle, host, userName, password, database, port, NULL, 0))
+    {
+        Console->LPrint(RED, BLACK, "[ERROR]");
+        Console->LClose();
+        Console->Print("Unable to connect to MySQL Database. MySQL returned: %s", mysql_error(dbHandle));
+        return false;
+    }
+    else
+    {
+        Console->LPrint(GREEN, BLACK, "Success");
+        Console->LClose();
+        return true;
+    }
+}
+
+MYSQL_RES *PMySQL::ResQuery(const char *query)
+{
+    int32_t sql_result = 0;
+    MYSQL_RES *result;
+
+    sql_result = mysql_real_query(dbHandle, query, strlen(query));
+    if(sql_result)
+    {
+        return NULL;
+    }
+    result = mysql_store_result(dbHandle);
+    if(!result)
+    {
+        return NULL;
+    }
+
+    return result;
+}
+
+int32_t PMySQL::Query(const char *query)
+{
+    int32_t sql_result = 0;
+    sql_result = mysql_real_query(dbHandle, query, strlen(query));
+
+    return sql_result;
+}
+
+void PMySQL::ShowSQLError()
+{
+    Console->Print(RED, BLACK, "MySQL Error: %s", mysql_error(dbHandle));
+}
+
+void PMySQL::FreeSQLResult(MYSQL_RES *res)
+{
+  mysql_free_result(res);
+}
+
+uint32_t PMySQL::GetLastInsertId()
+{
+    return mysql_insert_id(dbHandle);
+}
+
+uint32_t PMySQL::EscapeString(const char *nText, char *dText, uint32_t dMaxLength)
+{
+  uint32_t nLength = strlen(nText);
+  uint32_t tMax = (dMaxLength - 1)/2;
+  if(nLength > tMax)
+  {
+    nLength = tMax;
+  }
+
+  return mysql_real_escape_string(dbHandle, dText, nText, nLength);
+}
index c58dc27..9a83d61 100644 (file)
@@ -1,35 +1,35 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#ifdef MYSQL_INC_DIR\r
-#include <mysql/mysql.h>\r
-#else\r
-#include <mysql.h>\r
-#endif\r
-\r
-class PMySQL {\r
-private:\r
-    int32_t port;\r
-    char host[100];\r
-    char userName[100];\r
-    char password[100];\r
-    char database[100];\r
-    MYSQL *dbHandle;\r
-    time_t mKeepaliveDelay;\r
-    time_t mLastKeepaliveSent;\r
-\r
-public:\r
-    PMySQL();\r
-    ~PMySQL();\r
-\r
-    void Update();\r
-    MYSQL *GetHandle();\r
-\r
-    bool Connect();\r
-    int32_t Query(const char *query);\r
-    MYSQL_RES *ResQuery(const char *query);\r
-    void ShowSQLError();\r
-    void FreeSQLResult(MYSQL_RES *res);\r
-    uint32_t GetLastInsertId();\r
-    uint32_t EscapeString(const char *nText, char *dText, uint32_t dMaxLength);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#ifdef MYSQL_INC_DIR
+#include <mysql/mysql.h>
+#else
+#include <mysql.h>
+#endif
+
+class PMySQL {
+private:
+    int32_t port;
+    char host[100];
+    char userName[100];
+    char password[100];
+    char database[100];
+    MYSQL *dbHandle;
+    time_t mKeepaliveDelay;
+    time_t mLastKeepaliveSent;
+
+public:
+    PMySQL();
+    ~PMySQL();
+
+    void Update();
+    MYSQL *GetHandle();
+
+    bool Connect();
+    int32_t Query(const char *query);
+    MYSQL_RES *ResQuery(const char *query);
+    void ShowSQLError();
+    void FreeSQLResult(MYSQL_RES *res);
+    uint32_t GetLastInsertId();
+    uint32_t EscapeString(const char *nText, char *dText, uint32_t dMaxLength);
+};
index e4b5036..1af7a18 100644 (file)
@@ -1,71 +1,71 @@
-#include "PatchServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PClient::PClient(int32_t Index)\r
-{\r
-       mIndex = Index;\r
-       mConnection = PCC_NONE;\r
-}\r
-\r
-PClient::~PClient()\r
-{\r
-    if(m_TCPConnection)\r
-    {\r
-        delete m_TCPConnection;\r
-    }\r
-}\r
-\r
-int32_t PClient::GetIndex() const\r
-{\r
-    return mIndex;\r
-}\r
-\r
-int32_t PClient::GetConnection() const\r
-{\r
-    return mConnection;\r
-}\r
-\r
-const char *PClient::GetAddress() const\r
-{\r
-    return m_TCPConnection->getRemoteAddress();\r
-}\r
-\r
-void PClient::setTCPConnection(ConnectionTCP *conn)\r
-{\r
-    m_TCPConnection = conn;\r
-    mConnection = PCC_PATCH;\r
-}\r
-\r
-ConnectionTCP *PClient::getTCPConn()\r
-{\r
-    return m_TCPConnection;\r
-}\r
-\r
-void PClient::Update()\r
-{\r
-    if(m_TCPConnection)\r
-    {\r
-        if(m_TCPConnection->timeOut())\r
-        {\r
-            Console->Print("Patchsocket: Client %i: timeout", mIndex);\r
-            PatchServer->ClientDisconnected(this);\r
-        }\r
-        else\r
-        {\r
-            if(!m_TCPConnection->update())\r
-            {\r
-                PatchServer->ClientDisconnected(this);\r
-            }\r
-        }\r
-       }\r
-}\r
-\r
-void PClient::PatchDisconnect()\r
-{\r
-    if(m_TCPConnection)\r
-    {\r
-        delete m_TCPConnection;\r
-    }\r
-    mConnection = PCC_NONE;\r
-    m_TCPConnection = 0;\r
-}\r
+#include "PatchServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PClient::PClient(int32_t Index)
+{
+       mIndex = Index;
+       mConnection = PCC_NONE;
+}
+
+PClient::~PClient()
+{
+    if(m_TCPConnection)
+    {
+        delete m_TCPConnection;
+    }
+}
+
+int32_t PClient::GetIndex() const
+{
+    return mIndex;
+}
+
+int32_t PClient::GetConnection() const
+{
+    return mConnection;
+}
+
+const char *PClient::GetAddress() const
+{
+    return m_TCPConnection->getRemoteAddress();
+}
+
+void PClient::setTCPConnection(ConnectionTCP *conn)
+{
+    m_TCPConnection = conn;
+    mConnection = PCC_PATCH;
+}
+
+ConnectionTCP *PClient::getTCPConn()
+{
+    return m_TCPConnection;
+}
+
+void PClient::Update()
+{
+    if(m_TCPConnection)
+    {
+        if(m_TCPConnection->timeOut())
+        {
+            Console->Print("Patchsocket: Client %i: timeout", mIndex);
+            PatchServer->ClientDisconnected(this);
+        }
+        else
+        {
+            if(!m_TCPConnection->update())
+            {
+                PatchServer->ClientDisconnected(this);
+            }
+        }
+       }
+}
+
+void PClient::PatchDisconnect()
+{
+    if(m_TCPConnection)
+    {
+        delete m_TCPConnection;
+    }
+    mConnection = PCC_NONE;
+    m_TCPConnection = 0;
+}
index c0abe39..03c68c9 100644 (file)
@@ -1,29 +1,29 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-\r
-class ConnectionTCP;\r
-\r
-enum PClientConnection {\r
-    PCC_NONE = 0,\r
-    PCC_PATCH = 1\r
-};\r
-\r
-class PClient {\r
-private:\r
-    ConnectionTCP *m_TCPConnection;\r
-    int32_t mIndex;\r
-    int32_t mConnection;\r
-\r
-public:\r
-    PClient(int32_t Index);\r
-    ~PClient();\r
-\r
-    int32_t GetIndex() const;\r
-    int32_t GetConnection() const;\r
-    const char *GetAddress() const;\r
-    void setTCPConnection(ConnectionTCP *conn);\r
-    ConnectionTCP *getTCPConn();\r
-    void Update();\r
-    void PatchDisconnect();\r
-};\r
+#pragma once
+
+#include <cstdint>
+
+class ConnectionTCP;
+
+enum PClientConnection {
+    PCC_NONE = 0,
+    PCC_PATCH = 1
+};
+
+class PClient {
+private:
+    ConnectionTCP *m_TCPConnection;
+    int32_t mIndex;
+    int32_t mConnection;
+
+public:
+    PClient(int32_t Index);
+    ~PClient();
+
+    int32_t GetIndex() const;
+    int32_t GetConnection() const;
+    const char *GetAddress() const;
+    void setTCPConnection(ConnectionTCP *conn);
+    ConnectionTCP *getTCPConn();
+    void Update();
+    void PatchDisconnect();
+};
index 4b58417..080faef 100644 (file)
@@ -1,16 +1,16 @@
-#pragma once\r
-\r
-static const char *PatchConfigTemplate[][2] = {\r
-  // {option_name, default_value} if default_value is empty string, it means option is mandatory\r
-  // List ends with empty string for option_name\r
-  {"server_version", "200"},\r
-  {"patchserver_port", "8040"},\r
-  {"patches_path", "./patches"},\r
-  {"file_path", "./files"},\r
-  {"max_file_xfers", "5"},\r
-  {"patch_packet_size", "512"},\r
-  {"maxclients", "5"},\r
-  {"gm_slots", "2"},\r
-\r
-  {"", ""} // do not change this line (end mark)\r
-};\r
+#pragma once
+
+static const char *PatchConfigTemplate[][2] = {
+  // {option_name, default_value} if default_value is empty string, it means option is mandatory
+  // List ends with empty string for option_name
+  {"server_version", "200"},
+  {"patchserver_port", "8040"},
+  {"patches_path", "./patches"},
+  {"file_path", "./files"},
+  {"max_file_xfers", "5"},
+  {"patch_packet_size", "512"},
+  {"maxclients", "5"},
+  {"gm_slots", "2"},
+
+  {"", ""} // do not change this line (end mark)
+};
index b6551de..b691713 100644 (file)
@@ -1,61 +1,61 @@
-#include "PatchServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-const char ServerVersion[] = TINNS_PATCH_VERSION;\r
-const char SVNRevision[] = TINNS_SVN_REVISION;\r
-\r
-ServerSocket* ServerSock = 0;\r
-PConsole *Console = 0;\r
-PServer *Server = 0;\r
-PConfig *Config = 0;\r
-PFileSystem *Filesystem = 0;\r
-PPatchServer *PatchServer = 0;\r
-\r
-bool InitTinNS()\r
-{\r
-    Console = new PConsole("log/patchserver.log");  // Make that from config file !!!\r
-    Console->Print("Starting TinNS Patchserver...");\r
-    Console->Print(WHITE, BLUE, "/-------------------------------------------------------------------\\");\r
-    Console->Print(WHITE, BLUE, "|               TinNS (TinNS is not a Neocron Server)               |");\r
-    Console->Print(WHITE, BLUE, "|            Copyright (C) 2005 Linux Addicted Community            |");\r
-    Console->Print(WHITE, BLUE, "|                  maintainer Akiko <akiko@gmx.org>                 |");\r
-    Console->Print(WHITE, BLUE, "|             ==========================================            |");\r
-    Console->Print(WHITE, BLUE, "|      Head coders:                   The packet analyzing team:    |");\r
-    Console->Print(WHITE, BLUE, "|      - Akiko                         - MaxxJag                    |");\r
-    Console->Print(WHITE, BLUE, "|      - bakkdoor                      - Sting                      |");\r
-    Console->Print(WHITE, BLUE, "|      - Namikon                       - Balm                       |");\r
-    Console->Print(WHITE, BLUE, "|      - Hammag                                                     |");\r
-    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");\r
-    Console->Print(WHITE, BLUE, "|  This project would'nt be at its current stage without the help   |");\r
-    Console->Print(WHITE, BLUE, "|        from the NeoPolis team, special thanks to you guys!        |");\r
-    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");\r
-    Console->Print(WHITE, BLUE, "|  This project is under GPL, see any source file for more details  |");\r
-    Console->Print(WHITE, BLUE, "\\-------------------------------------------------------------------/");\r
-\r
-    //char svnrev[10];\r
-    //GetSVNRev(svnrev);\r
-    Console->LPrint("You are running TinNS Patchserver version");\r
-    Console->LPrint(GREEN, BLACK, " %s", ServerVersion);\r
-    Console->LPrint(WHITE, BLACK, " - SVN Rev");\r
-    Console->LPrint(GREEN, BLACK, " %s", SVNRevision);\r
-    Console->LClose();\r
-\r
-    Config = new PConfig();\r
-    if(!Config->LoadOptions(PatchConfigTemplate ,"./conf/patchserver.conf"))\r
-    Shutdown();\r
-\r
-    ServerSock = new ServerSocket();\r
-    Server = new PServer();\r
-    PatchServer = new PPatchServer();\r
-\r
-    return true;\r
-}\r
-\r
-void Shutdown()\r
-{\r
-    if(PatchServer) delete PatchServer;\r
-    if(Config) delete Config;\r
-    if(Console) delete Console;\r
-    if(ServerSock) delete ServerSock;\r
-    exit(0);\r
-}\r
+#include "PatchServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+const char ServerVersion[] = TINNS_PATCH_VERSION;
+const char SVNRevision[] = TINNS_SVN_REVISION;
+
+ServerSocket* ServerSock = 0;
+PConsole *Console = 0;
+PServer *Server = 0;
+PConfig *Config = 0;
+PFileSystem *Filesystem = 0;
+PPatchServer *PatchServer = 0;
+
+bool InitTinNS()
+{
+    Console = new PConsole("log/patchserver.log");  // Make that from config file !!!
+    Console->Print("Starting TinNS Patchserver...");
+    Console->Print(WHITE, BLUE, "/-------------------------------------------------------------------\\");
+    Console->Print(WHITE, BLUE, "|               TinNS (TinNS is not a Neocron Server)               |");
+    Console->Print(WHITE, BLUE, "|            Copyright (C) 2005 Linux Addicted Community            |");
+    Console->Print(WHITE, BLUE, "|                  maintainer Akiko <akiko@gmx.org>                 |");
+    Console->Print(WHITE, BLUE, "|             ==========================================            |");
+    Console->Print(WHITE, BLUE, "|      Head coders:                   The packet analyzing team:    |");
+    Console->Print(WHITE, BLUE, "|      - Akiko                         - MaxxJag                    |");
+    Console->Print(WHITE, BLUE, "|      - bakkdoor                      - Sting                      |");
+    Console->Print(WHITE, BLUE, "|      - Namikon                       - Balm                       |");
+    Console->Print(WHITE, BLUE, "|      - Hammag                                                     |");
+    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");
+    Console->Print(WHITE, BLUE, "|  This project would'nt be at its current stage without the help   |");
+    Console->Print(WHITE, BLUE, "|        from the NeoPolis team, special thanks to you guys!        |");
+    Console->Print(WHITE, BLUE, "|-------------------------------------------------------------------|");
+    Console->Print(WHITE, BLUE, "|  This project is under GPL, see any source file for more details  |");
+    Console->Print(WHITE, BLUE, "\\-------------------------------------------------------------------/");
+
+    //char svnrev[10];
+    //GetSVNRev(svnrev);
+    Console->LPrint("You are running TinNS Patchserver version");
+    Console->LPrint(GREEN, BLACK, " %s", ServerVersion);
+    Console->LPrint(WHITE, BLACK, " - SVN Rev");
+    Console->LPrint(GREEN, BLACK, " %s", SVNRevision);
+    Console->LClose();
+
+    Config = new PConfig();
+    if(!Config->LoadOptions(PatchConfigTemplate ,"./conf/patchserver.conf"))
+    Shutdown();
+
+    ServerSock = new ServerSocket();
+    Server = new PServer();
+    PatchServer = new PPatchServer();
+
+    return true;
+}
+
+void Shutdown()
+{
+    if(PatchServer) delete PatchServer;
+    if(Config) delete Config;
+    if(Console) delete Console;
+    if(ServerSock) delete ServerSock;
+    exit(0);
+}
index b6fd386..16cf78d 100644 (file)
@@ -1,19 +1,19 @@
-#pragma once\r
-\r
-#include "PatchServer/Client.hxx"\r
-#include "PatchServer/ConfigTemplate.hxx"\r
-#include "PatchServer/PatchServer.hxx"\r
-#include "PatchServer/Server.hxx"\r
-\r
-extern class ServerSocket* ServerSock;\r
-extern class PConsole *Console;\r
-extern class PConfig *Config;\r
-extern class PFileSystem *Filesystem;\r
-extern class PServer *Server;\r
-extern class PPatchServer *PatchServer;\r
-\r
-extern const char ServerVersion[];\r
-extern const char SVNRevision[];\r
-\r
-bool InitTinNS();\r
-void Shutdown();\r
+#pragma once
+
+#include "PatchServer/Client.hxx"
+#include "PatchServer/ConfigTemplate.hxx"
+#include "PatchServer/PatchServer.hxx"
+#include "PatchServer/Server.hxx"
+
+extern class ServerSocket* ServerSock;
+extern class PConsole *Console;
+extern class PConfig *Config;
+extern class PFileSystem *Filesystem;
+extern class PServer *Server;
+extern class PPatchServer *PatchServer;
+
+extern const char ServerVersion[];
+extern const char SVNRevision[];
+
+bool InitTinNS();
+void Shutdown();
index c2d4d83..0a5dba1 100644 (file)
@@ -1,36 +1,36 @@
-#include <chrono>\r
-#include <csignal>\r
-#include <thread>\r
-#include "PatchServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-void signal_handler(int signal)\r
-{\r
-    if (signal == SIGINT)\r
-        Shutdown();\r
-    else\r
-        psignal(signal, "Unkown signal: ");\r
-}\r
-\r
-int main()\r
-{\r
-    signal(SIGINT, signal_handler);\r
-\r
-\r
-    if (!InitTinNS())\r
-        while (true)\r
-            std::this_thread::sleep_for(std::chrono::seconds(1));\r
-\r
-    PatchServer->Start();\r
-    Console->Print("Patchserver is now %s. Waiting for clients...", Console->ColorText(GREEN, BLACK, "Online"));\r
-\r
-    while (true)\r
-    {\r
-        ServerSock->update();\r
-        Server->Update();\r
-        PatchServer->Update();\r
-        // sched_yield();\r
-    }\r
-\r
-    return 0;\r
-}\r
+#include <chrono>
+#include <csignal>
+#include <thread>
+#include "PatchServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+void signal_handler(int signal)
+{
+    if (signal == SIGINT)
+        Shutdown();
+    else
+        psignal(signal, "Unkown signal: ");
+}
+
+int main()
+{
+    signal(SIGINT, signal_handler);
+
+
+    if (!InitTinNS())
+        while (true)
+            std::this_thread::sleep_for(std::chrono::seconds(1));
+
+    PatchServer->Start();
+    Console->Print("Patchserver is now %s. Waiting for clients...", Console->ColorText(GREEN, BLACK, "Online"));
+
+    while (true)
+    {
+        ServerSock->update();
+        Server->Update();
+        PatchServer->Update();
+        // sched_yield();
+    }
+
+    return 0;
+}
index ae4c1e7..8326dcc 100644 (file)
-#include <cstring>\r
-#include <sstream>\r
-#include "PatchServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-const uint16_t PATCH_PORT = 7000;\r
-\r
-struct PPatchState {\r
-       enum State\r
-       {\r
-               PS_UNKNOWN,\r
-               PS_CONNECTED,\r
-               PS_HANDSHAKE0,\r
-               PS_HANDSHAKE1,\r
-               PS_VERSIONREQUEST,\r
-               PS_GETPATCHORFILE,\r
-               PS_SENDPATCH,\r
-               PS_SENDFILE\r
-       } mState;\r
-\r
-       uint16_t mSerial;\r
-\r
-       uint32_t mCurrentPatch;\r
-       uint32_t mPatchOffset;\r
-       uint32_t mPatchSize;\r
-       std::FILE *mPatchFile;\r
-\r
-       std::string mCurrentFile;\r
-       uint32_t mFileOffset;\r
-       uint32_t mFileSize;\r
-       PFile *mSendFile;\r
-\r
-       bool mWaitSend; // wait-for-completition flag\r
-       PPatchState()\r
-       {\r
-               mState = PS_UNKNOWN;\r
-               mSerial = 0;\r
-               mCurrentPatch = 0;\r
-               mPatchOffset = 0;\r
-               mPatchFile = 0;\r
-\r
-               mCurrentFile = "";\r
-               mFileOffset = 0;\r
-               mFileSize = 0;\r
-               mSendFile = 0;\r
-\r
-               mWaitSend = false;\r
-       };\r
-\r
-       ~PPatchState()\r
-       {\r
-               if(mPatchFile)\r
-                       std::fclose(mPatchFile);\r
-               if(mSendFile)\r
-                       Filesystem->Close(mSendFile);\r
-       }\r
-};\r
-\r
-// -------------------------------------------------------\r
-\r
-PPatchServer::PPatchServer()\r
-{\r
-       //mNumClients = 1;\r
-       mNumFileTransfers = 0;\r
-}\r
-\r
-PPatchServer::~PPatchServer()\r
-{\r
-    ServerSock->closeServer();\r
-\r
-       for(PatchStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end(); i++)\r
-               delete i->second;\r
-}\r
-\r
-void PPatchServer::Start()\r
-{\r
-       uint16_t Port = Config->GetOptionInt("patchserver_port");\r
-       if(Port==0)\r
-               Port=PATCH_PORT;\r
-\r
-       Console->LPrint("Starting Patchserver on port %i...", Port);\r
-       if(ServerSock->open(Port))\r
-       {\r
-           Console->LPrint(GREEN, BLACK, "Success");\r
-       }\r
-       else\r
-       {\r
-               Console->LPrint(RED, BLACK, "ERROR");\r
-       }\r
-       Console->LClose();\r
-       ServerSock->settimeout(0, 10000);\r
-}\r
-\r
-void PPatchServer::Update()\r
-{\r
-    //ServerSock->update();\r
-\r
-       if(ServerSock->newConnection())\r
-       {\r
-               int32_t clid = Server->NewClient();\r
-               if(clid!=-1)\r
-               {\r
-                       Console->Print(GREEN, BLACK, "Patchserver: client [%i] connected", clid);\r
-                       PClient *Client = Server->GetClient(clid);\r
-\r
-                       ConnectionTCP* tcpConn = ServerSock->getTCPConnection();\r
-                       Client->setTCPConnection(tcpConn);\r
-\r
-                       Console->Print("Client address: %s", Client->GetAddress());\r
-                       //++mNumClients;\r
-\r
-                       PPatchState *state = new PPatchState();\r
-                       ClientStates.insert(std::make_pair(Client, state));\r
-                       state->mState = PPatchState::PS_CONNECTED;\r
-               } else\r
-               {\r
-                       Console->Print("Patchserver: Client connection refused (server full?)");\r
-               }\r
-       }\r
-\r
-       for(PatchStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end();)\r
-       {\r
-               PClient *Client = i->first;\r
-               PPatchState *State = i->second;\r
-               // node gets erased in FinalizeClient, increment iterator now\r
-               ++i;\r
-               if(!ProcessClient(Client, State))\r
-               {\r
-                       FinalizeClient(Client, State);\r
-               }\r
-       }\r
-}\r
-\r
-void PPatchServer::FinalizeClient(PClient *Client, PPatchState *State)\r
-{\r
-       Console->Print(RED, BLACK, "Patchserver: client %s disconnected", Client->GetAddress());\r
-       Client->PatchDisconnect();\r
-       ClientStates.erase(Client);\r
-       if(State->mPatchFile)\r
-               --mNumFileTransfers;\r
-       if(State->mSendFile)\r
-               --mNumFileTransfers;\r
-       delete State;\r
-}\r
-\r
-// completes pending packets before disconnect\r
-void PPatchServer::FinalizeClientDelayed(PClient *Client, PPatchState *State)\r
-{\r
-       Console->Print("Patchserver: client %i is about to be disconnected", Client->GetIndex());\r
-       State->mWaitSend = true;\r
-}\r
-\r
-void PPatchServer::ClientDisconnected(PClient *Client)\r
-{\r
-       PatchStateMap::iterator node = ClientStates.find(Client);\r
-       if(node == ClientStates.end())\r
-               return;\r
-\r
-       PPatchState *State = node->second;\r
-       FinalizeClient(Client, State);\r
-}\r
-\r
-bool PPatchServer::HandleHandshake(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize)\r
-{\r
-       static const uint8_t HANDSHAKE1A[6]={0xfe, 0x03, 0x00, 0x80, 0x01, 0x73};\r
-\r
-       ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-       switch(State->mState)\r
-       {\r
-               case PPatchState::PS_HANDSHAKE0 :\r
-               {\r
-                       if(PacketSize==6 && *(uint16_t*)&Packet[3]==0x0280 && Packet[5]==0x64)\r
-                       {\r
-                               Socket->write(HANDSHAKE1A, sizeof(HANDSHAKE1A));\r
-                               State->mState = PPatchState::PS_HANDSHAKE1;\r
-                       } else\r
-                       {\r
-                               Console->Print("Patchserver protocol error (PS_HANDSHAKE0): invalid packet [%04x]", *(uint16_t*)&Packet[3]);\r
-                               return false;\r
-                       }\r
-\r
-                       break;\r
-               }\r
-\r
-               case PPatchState::PS_HANDSHAKE1 :\r
-               {\r
-                       if(PacketSize==6 && *(uint16_t*)&Packet[3]==0x0080 && Packet[5]==0x6c)\r
-                               State->mState = PPatchState::PS_VERSIONREQUEST;\r
-                       else\r
-                       {\r
-                               Console->Print("Patchserver protocol error (PS_HANDSHAKE1): invalid packet [%04x]", *(uint16_t*)&Packet[3]);\r
-                               return false;\r
-                       }\r
-                       break;\r
-               }\r
-               default:\r
-                       break;\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-bool PPatchServer::HandleVersionRequest(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize)\r
-{\r
-       static uint8_t VERSIONPACKET[13]={0xfe, 0x0a, 0x00, 0x37, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
-\r
-       ConnectionTCP *Socket = Client->getTCPConn();\r
-       if(PacketSize==9 && *(uint16_t*)&Packet[3]==0x007b)\r
-       {\r
-               State->mSerial = *(uint16_t*)&Packet[7];\r
-               *(uint16_t*)&VERSIONPACKET[7]=State->mSerial;\r
-               uint32_t ver = Config->GetOptionInt("server_version");\r
-               *(uint32_t*)&VERSIONPACKET[9]=ver;\r
-               Socket->write(VERSIONPACKET, 13);\r
-               State->mState = PPatchState::PS_GETPATCHORFILE;\r
-       } else\r
-       {\r
-               Console->Print("Patchserver protocol error (PS_VERSIONREQUEST): invalid packet [%04x]", *(uint16_t*)&Packet[3]);\r
-               return false;\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-bool PPatchServer::HandleFileRequests(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize)\r
-{\r
-       static uint8_t STARTPATCH[13]={0xfe, 0x0a, 0x00, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
-       static uint8_t STARTFILE[13]={0xfe, 0x0a, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
-       static uint8_t FILEERROR[9]={0xfe, 0x06, 0x00, 0x3d, 0x02, 0x00, 0x00, 0x00, 0x00};\r
-\r
-       ConnectionTCP *Socket = Client->getTCPConn();\r
-       // request patch\r
-       if(PacketSize==13 && *(uint16_t*)&Packet[3]==0x007c)\r
-       {\r
-               int32_t nmax = Config->GetOptionInt("max_file_xfers");\r
-               if(mNumFileTransfers>=nmax)\r
-               {\r
-                       Console->Print("Patchserver: max file xfers exceed, killing client %i", Client->GetIndex());\r
-                       return false;\r
-               }\r
-               if(State->mPatchFile)\r
-               {\r
-                       std::fclose(State->mPatchFile);\r
-                       State->mPatchFile=0;\r
-                       --mNumFileTransfers;\r
-               }\r
-               if(State->mSendFile)\r
-               {\r
-                       Filesystem->Close(State->mSendFile);\r
-                       State->mSendFile=0;\r
-                       --mNumFileTransfers;\r
-               }\r
-               State->mSerial = *(uint16_t*)&Packet[7];\r
-               State->mCurrentPatch = *(uint32_t*)&Packet[9];\r
-               Console->Print("Patchserver: Patch request from client %i (v%i)", Client->GetIndex(), State->mCurrentPatch);\r
-               if((bool)(State->mPatchSize = StartPatch(State)))\r
-               {\r
-                       Console->Print("Patchserver: Patch is available, %d bytes", State->mPatchSize);\r
-                       *(uint16_t*)&STARTPATCH[7]=State->mSerial;\r
-                       *(uint32_t*)&STARTPATCH[9]=State->mPatchSize;\r
-                       Socket->write(STARTPATCH, 13);\r
-                       State->mState = PPatchState::PS_SENDPATCH;\r
-               } else\r
-               {\r
-                       Console->Print("Patchserver: Patch not available");\r
-                       *(uint16_t*)&FILEERROR[7]=State->mSerial;\r
-                       Socket->write(FILEERROR, 9);\r
-                       FinalizeClientDelayed(Client, State);\r
-                       State->mState=PPatchState::PS_UNKNOWN;\r
-                       return true;\r
-               }\r
-       } else\r
-       // request file\r
-       if(PacketSize > 9 && *(uint16_t*)&Packet[3]==0x004d)\r
-       {\r
-               int32_t nmax = Config->GetOptionInt("max_file_xfers");\r
-               if(mNumFileTransfers>=nmax)\r
-               {\r
-                       Console->Print("Patchserver: max file xfers exceed, killing client %i", Client->GetIndex());\r
-                       return false;\r
-               }\r
-               if(State->mPatchFile)\r
-               {\r
-                       std::fclose(State->mPatchFile);\r
-                       State->mPatchFile=0;\r
-                       --mNumFileTransfers;\r
-               }\r
-               if(State->mSendFile)\r
-               {\r
-                       Filesystem->Close(State->mSendFile);\r
-                       State->mSendFile=0;\r
-                       --mNumFileTransfers;\r
-               }\r
-               // request file\r
-               State->mSerial = *(uint16_t*)&Packet[7];\r
-               char fn[256];\r
-               strncpy(fn, (const char*)&Packet[10], Packet[9]);\r
-               fn[Packet[9]]=0;\r
-               State->mCurrentFile = fn;\r
-\r
-               Console->Print("Patchserver: File request from client %i (%s)", Client->GetIndex(), fn);\r
-               if((bool)(State->mFileSize = StartFile(State)))\r
-               {\r
-                       Console->Print("Patchserver: File %s is available, %d bytes", State->mCurrentFile.c_str(), State->mFileSize);\r
-                       *(uint16_t*)&STARTFILE[7]=State->mSerial;\r
-                       *(uint32_t*)&STARTFILE[9]=State->mFileSize;\r
-                       Socket->write(STARTFILE, 13);\r
-                       State->mState = PPatchState::PS_SENDFILE;\r
-               } else\r
-               {\r
-                       Console->Print("Patchserver: Requested file %s not available", State->mCurrentFile.c_str());\r
-                       *(uint16_t*)&FILEERROR[7]=State->mSerial;\r
-                       Socket->write(FILEERROR, 9);\r
-                       FinalizeClientDelayed(Client, State);\r
-                       State->mState=PPatchState::PS_UNKNOWN;\r
-                       return true;\r
-               }\r
-       } else\r
-       // send patch data\r
-       if(PacketSize==17 && *(uint16_t*)&Packet[3]==0x007d)\r
-       {\r
-               State->mSerial = *(uint16_t*)&Packet[7];\r
-               State->mCurrentPatch = *(uint32_t*)&Packet[9];\r
-               State->mPatchOffset = *(uint32_t*)&Packet[13];\r
-               if(!SendPatchData(Client, State))\r
-               {\r
-                       Console->Print("Patchserver: SendPatchData failed on client %i", Client->GetIndex());\r
-                       Console->Print("Patchserver: (probably due to garbage packets)");\r
-                       // state is undefined now, kill this client\r
-                       return false;\r
-               }\r
-       } else\r
-       // send file data\r
-       if(PacketSize > 13 && *(uint16_t*)&Packet[3]==0x00037)\r
-       {\r
-               State->mSerial = *(uint16_t*)&Packet[7];\r
-               State->mFileOffset = *(uint32_t*)&Packet[9];\r
-               if(!SendFileData(Client, State))\r
-               {\r
-                       Console->Print("Patchserver: SendFileData failed on client %i", Client->GetIndex());\r
-                       Console->Print("Patchserver: (probably due to garbage packets)");\r
-                       // state is undefined now, kill this client\r
-                       return false;\r
-               }\r
-       } else\r
-       {\r
-               Console->Print("Patchserver protocol error (PS_GETPATCHORFILE): unknown packet");\r
-               return false;\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-uint32_t PPatchServer::StartPatch(PPatchState *State)\r
-{\r
-       std::stringstream path;\r
-       char patchname[13];\r
-       snprintf(patchname, 13, "sp%06d.pat", State->mCurrentPatch);\r
-       path << Config->GetOption("patches_path") << "/" << patchname << '\0';\r
-       State->mPatchFile = std::fopen(path.str().c_str(), "rb");\r
-       if(State->mPatchFile)\r
-       {\r
-               ++mNumFileTransfers;\r
-               fseek(State->mPatchFile, 0, SEEK_END);\r
-               uint32_t size = ftell(State->mPatchFile);\r
-               fseek(State->mPatchFile, 0, SEEK_SET);\r
-               return size;\r
-       }\r
-       return 0;\r
-}\r
-\r
-bool PPatchServer::SendPatchData(PClient *Client, PPatchState *State) const\r
-{\r
-       if(!State->mPatchFile)\r
-               return false;\r
-\r
-       uint16_t size = Config->GetOptionInt("patch_packet_size");\r
-\r
-       const int32_t BUFFERSIZE = 4082;\r
-\r
-       size = std::min(BUFFERSIZE, std::max((int32_t)size, 64));\r
-       static uint8_t Buffer[BUFFERSIZE+13];\r
-\r
-       if(fseek(State->mPatchFile, State->mPatchOffset, SEEK_SET)!=0)\r
-               return false;\r
-\r
-       size = fread(&Buffer[13], 1, size, State->mPatchFile);\r
-       Buffer[0]=0xfe;\r
-       *(uint16_t*)&Buffer[1]=size+10;\r
-       Buffer[3]=0x39;\r
-       Buffer[4]=0x02;\r
-       Buffer[5]=0x00;\r
-       Buffer[6]=0x00;\r
-       *(uint16_t*)&Buffer[7]=State->mSerial;\r
-       *(uint32_t*)&Buffer[9]=size;\r
-       return Client->getTCPConn()->write(Buffer, size+13)==size+13;\r
-}\r
-\r
-uint32_t PPatchServer::StartFile(PPatchState *State)\r
-{\r
-       // security checks: reject file paths containing ':', '..' or slashes/backslashes at the beginning\r
-       if((State->mCurrentFile.find(':') != std::string::npos)\r
-               || (State->mCurrentFile.find("..") != std::string::npos)\r
-               || (State->mCurrentFile.find('/') == 0)\r
-               || (State->mCurrentFile.find('\\') == 0))\r
-       {\r
-               return 0;\r
-       }\r
-\r
-       //std::stringstream path;\r
-       //path << Config->GetOption("file_path") << "/" << State->mCurrentFile << '\0';\r
-       State->mSendFile = Filesystem->Open("", State->mCurrentFile.c_str(), Config->GetOption("file_path"));\r
-       if(State->mSendFile)\r
-       {\r
-               ++mNumFileTransfers;\r
-               uint32_t size = State->mSendFile->GetSize();\r
-               return size;\r
-       }\r
-       return 0;\r
-}\r
-\r
-bool PPatchServer::SendFileData(PClient *Client, PPatchState *State) const\r
-{\r
-       if(!State->mSendFile)\r
-               return false;\r
-\r
-       uint16_t size = Config->GetOptionInt("patch_packet_size");\r
-\r
-       const int32_t BUFFERSIZE = 4082;\r
-\r
-       size = std::min(BUFFERSIZE, std::max((int32_t)size, 1));\r
-       static uint8_t Buffer[BUFFERSIZE+13];\r
-\r
-       State->mSendFile->Seek(State->mFileOffset);\r
-\r
-       size = State->mSendFile->Read(&Buffer[13], size);\r
-       Buffer[0]=0xfe;\r
-       *(uint16_t*)&Buffer[1]=size+10;\r
-       Buffer[3]=0x3c;\r
-       Buffer[4]=0x02;\r
-       Buffer[5]=0x00;\r
-       Buffer[6]=0x00;\r
-       *(uint16_t*)&Buffer[7]=State->mSerial;\r
-       *(uint32_t*)&Buffer[9]=size;\r
-       return Client->getTCPConn()->write(Buffer, size+13)==size+13;\r
-}\r
-\r
-bool PPatchServer::ProcessClient(PClient *Client, PPatchState *State)\r
-{\r
-       static const uint8_t HANDSHAKE0A[6]={0xfe, 0x03, 0x00, 0x80, 0x03, 0x6b};\r
-\r
-       if(!State)\r
-       {\r
-               PatchStateMap::iterator node = ClientStates.find(Client);\r
-               if(node == ClientStates.end())\r
-                       return false;\r
-\r
-               State = node->second;\r
-       }\r
-\r
-       ConnectionTCP *Socket = Client->getTCPConn();\r
-\r
-       if(State->mWaitSend && Socket->getSendBufferSize()==0)\r
-               return false;\r
-\r
-       if(State->mState==PPatchState::PS_CONNECTED)\r
-       {\r
-           Console->Print("Sending Handshake 0A");\r
-               Socket->write(HANDSHAKE0A, sizeof(HANDSHAKE0A));\r
-               //short unsigned int packet = (short unsigned int) HANDSHAKE0A;\r
-               //Socket->write(htons(packet));\r
-               State->mState = PPatchState::PS_HANDSHAKE0;\r
-               Socket->flushSendBuffer();\r
-       }\r
-\r
-       int32_t PacketSize = 0;\r
-       const uint8_t *Packet = Socket->read(&PacketSize);\r
-       if(PacketSize > 0)\r
-       {\r
-               switch(State->mState)\r
-               {\r
-                       case PPatchState::PS_HANDSHAKE1 :\r
-                       case PPatchState::PS_HANDSHAKE0 :\r
-                Console->Print("Handling Handshake 0 and 1");\r
-                               return HandleHandshake(Client, State, Packet, PacketSize);\r
-\r
-                       case PPatchState::PS_VERSIONREQUEST :\r
-                Console->Print("Handling Client Versionsrequest");\r
-                               return HandleVersionRequest(Client, State, Packet, PacketSize);\r
-\r
-                       case PPatchState::PS_GETPATCHORFILE :\r
-                       case PPatchState::PS_SENDPATCH :\r
-                       case PPatchState::PS_SENDFILE :\r
-                Console->Print("Getpatchforfile, sendpatch, sendfile");\r
-                               return HandleFileRequests(Client, State, Packet, PacketSize);\r
-                       default:\r
-                               break;\r
-               }\r
-       }\r
-       return true;\r
-}\r
+#include <cstring>
+#include <sstream>
+#include "PatchServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+const uint16_t PATCH_PORT = 7000;
+
+struct PPatchState {
+       enum State
+       {
+               PS_UNKNOWN,
+               PS_CONNECTED,
+               PS_HANDSHAKE0,
+               PS_HANDSHAKE1,
+               PS_VERSIONREQUEST,
+               PS_GETPATCHORFILE,
+               PS_SENDPATCH,
+               PS_SENDFILE
+       } mState;
+
+       uint16_t mSerial;
+
+       uint32_t mCurrentPatch;
+       uint32_t mPatchOffset;
+       uint32_t mPatchSize;
+       std::FILE *mPatchFile;
+
+       std::string mCurrentFile;
+       uint32_t mFileOffset;
+       uint32_t mFileSize;
+       PFile *mSendFile;
+
+       bool mWaitSend; // wait-for-completition flag
+       PPatchState()
+       {
+               mState = PS_UNKNOWN;
+               mSerial = 0;
+               mCurrentPatch = 0;
+               mPatchOffset = 0;
+               mPatchFile = 0;
+
+               mCurrentFile = "";
+               mFileOffset = 0;
+               mFileSize = 0;
+               mSendFile = 0;
+
+               mWaitSend = false;
+       };
+
+       ~PPatchState()
+       {
+               if(mPatchFile)
+                       std::fclose(mPatchFile);
+               if(mSendFile)
+                       Filesystem->Close(mSendFile);
+       }
+};
+
+// -------------------------------------------------------
+
+PPatchServer::PPatchServer()
+{
+       //mNumClients = 1;
+       mNumFileTransfers = 0;
+}
+
+PPatchServer::~PPatchServer()
+{
+    ServerSock->closeServer();
+
+       for(PatchStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end(); i++)
+               delete i->second;
+}
+
+void PPatchServer::Start()
+{
+       uint16_t Port = Config->GetOptionInt("patchserver_port");
+       if(Port==0)
+               Port=PATCH_PORT;
+
+       Console->LPrint("Starting Patchserver on port %i...", Port);
+       if(ServerSock->open(Port))
+       {
+           Console->LPrint(GREEN, BLACK, "Success");
+       }
+       else
+       {
+               Console->LPrint(RED, BLACK, "ERROR");
+       }
+       Console->LClose();
+       ServerSock->settimeout(0, 10000);
+}
+
+void PPatchServer::Update()
+{
+    //ServerSock->update();
+
+       if(ServerSock->newConnection())
+       {
+               int32_t clid = Server->NewClient();
+               if(clid!=-1)
+               {
+                       Console->Print(GREEN, BLACK, "Patchserver: client [%i] connected", clid);
+                       PClient *Client = Server->GetClient(clid);
+
+                       ConnectionTCP* tcpConn = ServerSock->getTCPConnection();
+                       Client->setTCPConnection(tcpConn);
+
+                       Console->Print("Client address: %s", Client->GetAddress());
+                       //++mNumClients;
+
+                       PPatchState *state = new PPatchState();
+                       ClientStates.insert(std::make_pair(Client, state));
+                       state->mState = PPatchState::PS_CONNECTED;
+               } else
+               {
+                       Console->Print("Patchserver: Client connection refused (server full?)");
+               }
+       }
+
+       for(PatchStateMap::iterator i=ClientStates.begin(); i!=ClientStates.end();)
+       {
+               PClient *Client = i->first;
+               PPatchState *State = i->second;
+               // node gets erased in FinalizeClient, increment iterator now
+               ++i;
+               if(!ProcessClient(Client, State))
+               {
+                       FinalizeClient(Client, State);
+               }
+       }
+}
+
+void PPatchServer::FinalizeClient(PClient *Client, PPatchState *State)
+{
+       Console->Print(RED, BLACK, "Patchserver: client %s disconnected", Client->GetAddress());
+       Client->PatchDisconnect();
+       ClientStates.erase(Client);
+       if(State->mPatchFile)
+               --mNumFileTransfers;
+       if(State->mSendFile)
+               --mNumFileTransfers;
+       delete State;
+}
+
+// completes pending packets before disconnect
+void PPatchServer::FinalizeClientDelayed(PClient *Client, PPatchState *State)
+{
+       Console->Print("Patchserver: client %i is about to be disconnected", Client->GetIndex());
+       State->mWaitSend = true;
+}
+
+void PPatchServer::ClientDisconnected(PClient *Client)
+{
+       PatchStateMap::iterator node = ClientStates.find(Client);
+       if(node == ClientStates.end())
+               return;
+
+       PPatchState *State = node->second;
+       FinalizeClient(Client, State);
+}
+
+bool PPatchServer::HandleHandshake(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize)
+{
+       static const uint8_t HANDSHAKE1A[6]={0xfe, 0x03, 0x00, 0x80, 0x01, 0x73};
+
+       ConnectionTCP *Socket = Client->getTCPConn();
+
+       switch(State->mState)
+       {
+               case PPatchState::PS_HANDSHAKE0 :
+               {
+                       if(PacketSize==6 && *(uint16_t*)&Packet[3]==0x0280 && Packet[5]==0x64)
+                       {
+                               Socket->write(HANDSHAKE1A, sizeof(HANDSHAKE1A));
+                               State->mState = PPatchState::PS_HANDSHAKE1;
+                       } else
+                       {
+                               Console->Print("Patchserver protocol error (PS_HANDSHAKE0): invalid packet [%04x]", *(uint16_t*)&Packet[3]);
+                               return false;
+                       }
+
+                       break;
+               }
+
+               case PPatchState::PS_HANDSHAKE1 :
+               {
+                       if(PacketSize==6 && *(uint16_t*)&Packet[3]==0x0080 && Packet[5]==0x6c)
+                               State->mState = PPatchState::PS_VERSIONREQUEST;
+                       else
+                       {
+                               Console->Print("Patchserver protocol error (PS_HANDSHAKE1): invalid packet [%04x]", *(uint16_t*)&Packet[3]);
+                               return false;
+                       }
+                       break;
+               }
+               default:
+                       break;
+       }
+
+       return true;
+}
+
+bool PPatchServer::HandleVersionRequest(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize)
+{
+       static uint8_t VERSIONPACKET[13]={0xfe, 0x0a, 0x00, 0x37, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+       ConnectionTCP *Socket = Client->getTCPConn();
+       if(PacketSize==9 && *(uint16_t*)&Packet[3]==0x007b)
+       {
+               State->mSerial = *(uint16_t*)&Packet[7];
+               *(uint16_t*)&VERSIONPACKET[7]=State->mSerial;
+               uint32_t ver = Config->GetOptionInt("server_version");
+               *(uint32_t*)&VERSIONPACKET[9]=ver;
+               Socket->write(VERSIONPACKET, 13);
+               State->mState = PPatchState::PS_GETPATCHORFILE;
+       } else
+       {
+               Console->Print("Patchserver protocol error (PS_VERSIONREQUEST): invalid packet [%04x]", *(uint16_t*)&Packet[3]);
+               return false;
+       }
+
+       return true;
+}
+
+bool PPatchServer::HandleFileRequests(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize)
+{
+       static uint8_t STARTPATCH[13]={0xfe, 0x0a, 0x00, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       static uint8_t STARTFILE[13]={0xfe, 0x0a, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       static uint8_t FILEERROR[9]={0xfe, 0x06, 0x00, 0x3d, 0x02, 0x00, 0x00, 0x00, 0x00};
+
+       ConnectionTCP *Socket = Client->getTCPConn();
+       // request patch
+       if(PacketSize==13 && *(uint16_t*)&Packet[3]==0x007c)
+       {
+               int32_t nmax = Config->GetOptionInt("max_file_xfers");
+               if(mNumFileTransfers>=nmax)
+               {
+                       Console->Print("Patchserver: max file xfers exceed, killing client %i", Client->GetIndex());
+                       return false;
+               }
+               if(State->mPatchFile)
+               {
+                       std::fclose(State->mPatchFile);
+                       State->mPatchFile=0;
+                       --mNumFileTransfers;
+               }
+               if(State->mSendFile)
+               {
+                       Filesystem->Close(State->mSendFile);
+                       State->mSendFile=0;
+                       --mNumFileTransfers;
+               }
+               State->mSerial = *(uint16_t*)&Packet[7];
+               State->mCurrentPatch = *(uint32_t*)&Packet[9];
+               Console->Print("Patchserver: Patch request from client %i (v%i)", Client->GetIndex(), State->mCurrentPatch);
+               if((bool)(State->mPatchSize = StartPatch(State)))
+               {
+                       Console->Print("Patchserver: Patch is available, %d bytes", State->mPatchSize);
+                       *(uint16_t*)&STARTPATCH[7]=State->mSerial;
+                       *(uint32_t*)&STARTPATCH[9]=State->mPatchSize;
+                       Socket->write(STARTPATCH, 13);
+                       State->mState = PPatchState::PS_SENDPATCH;
+               } else
+               {
+                       Console->Print("Patchserver: Patch not available");
+                       *(uint16_t*)&FILEERROR[7]=State->mSerial;
+                       Socket->write(FILEERROR, 9);
+                       FinalizeClientDelayed(Client, State);
+                       State->mState=PPatchState::PS_UNKNOWN;
+                       return true;
+               }
+       } else
+       // request file
+       if(PacketSize > 9 && *(uint16_t*)&Packet[3]==0x004d)
+       {
+               int32_t nmax = Config->GetOptionInt("max_file_xfers");
+               if(mNumFileTransfers>=nmax)
+               {
+                       Console->Print("Patchserver: max file xfers exceed, killing client %i", Client->GetIndex());
+                       return false;
+               }
+               if(State->mPatchFile)
+               {
+                       std::fclose(State->mPatchFile);
+                       State->mPatchFile=0;
+                       --mNumFileTransfers;
+               }
+               if(State->mSendFile)
+               {
+                       Filesystem->Close(State->mSendFile);
+                       State->mSendFile=0;
+                       --mNumFileTransfers;
+               }
+               // request file
+               State->mSerial = *(uint16_t*)&Packet[7];
+               char fn[256];
+               strncpy(fn, (const char*)&Packet[10], Packet[9]);
+               fn[Packet[9]]=0;
+               State->mCurrentFile = fn;
+
+               Console->Print("Patchserver: File request from client %i (%s)", Client->GetIndex(), fn);
+               if((bool)(State->mFileSize = StartFile(State)))
+               {
+                       Console->Print("Patchserver: File %s is available, %d bytes", State->mCurrentFile.c_str(), State->mFileSize);
+                       *(uint16_t*)&STARTFILE[7]=State->mSerial;
+                       *(uint32_t*)&STARTFILE[9]=State->mFileSize;
+                       Socket->write(STARTFILE, 13);
+                       State->mState = PPatchState::PS_SENDFILE;
+               } else
+               {
+                       Console->Print("Patchserver: Requested file %s not available", State->mCurrentFile.c_str());
+                       *(uint16_t*)&FILEERROR[7]=State->mSerial;
+                       Socket->write(FILEERROR, 9);
+                       FinalizeClientDelayed(Client, State);
+                       State->mState=PPatchState::PS_UNKNOWN;
+                       return true;
+               }
+       } else
+       // send patch data
+       if(PacketSize==17 && *(uint16_t*)&Packet[3]==0x007d)
+       {
+               State->mSerial = *(uint16_t*)&Packet[7];
+               State->mCurrentPatch = *(uint32_t*)&Packet[9];
+               State->mPatchOffset = *(uint32_t*)&Packet[13];
+               if(!SendPatchData(Client, State))
+               {
+                       Console->Print("Patchserver: SendPatchData failed on client %i", Client->GetIndex());
+                       Console->Print("Patchserver: (probably due to garbage packets)");
+                       // state is undefined now, kill this client
+                       return false;
+               }
+       } else
+       // send file data
+       if(PacketSize > 13 && *(uint16_t*)&Packet[3]==0x00037)
+       {
+               State->mSerial = *(uint16_t*)&Packet[7];
+               State->mFileOffset = *(uint32_t*)&Packet[9];
+               if(!SendFileData(Client, State))
+               {
+                       Console->Print("Patchserver: SendFileData failed on client %i", Client->GetIndex());
+                       Console->Print("Patchserver: (probably due to garbage packets)");
+                       // state is undefined now, kill this client
+                       return false;
+               }
+       } else
+       {
+               Console->Print("Patchserver protocol error (PS_GETPATCHORFILE): unknown packet");
+               return false;
+       }
+
+       return true;
+}
+
+uint32_t PPatchServer::StartPatch(PPatchState *State)
+{
+       std::stringstream path;
+       char patchname[13];
+       snprintf(patchname, 13, "sp%06d.pat", State->mCurrentPatch);
+       path << Config->GetOption("patches_path") << "/" << patchname << '\0';
+       State->mPatchFile = std::fopen(path.str().c_str(), "rb");
+       if(State->mPatchFile)
+       {
+               ++mNumFileTransfers;
+               fseek(State->mPatchFile, 0, SEEK_END);
+               uint32_t size = ftell(State->mPatchFile);
+               fseek(State->mPatchFile, 0, SEEK_SET);
+               return size;
+       }
+       return 0;
+}
+
+bool PPatchServer::SendPatchData(PClient *Client, PPatchState *State) const
+{
+       if(!State->mPatchFile)
+               return false;
+
+       uint16_t size = Config->GetOptionInt("patch_packet_size");
+
+       const int32_t BUFFERSIZE = 4082;
+
+       size = std::min(BUFFERSIZE, std::max((int32_t)size, 64));
+       static uint8_t Buffer[BUFFERSIZE+13];
+
+       if(fseek(State->mPatchFile, State->mPatchOffset, SEEK_SET)!=0)
+               return false;
+
+       size = fread(&Buffer[13], 1, size, State->mPatchFile);
+       Buffer[0]=0xfe;
+       *(uint16_t*)&Buffer[1]=size+10;
+       Buffer[3]=0x39;
+       Buffer[4]=0x02;
+       Buffer[5]=0x00;
+       Buffer[6]=0x00;
+       *(uint16_t*)&Buffer[7]=State->mSerial;
+       *(uint32_t*)&Buffer[9]=size;
+       return Client->getTCPConn()->write(Buffer, size+13)==size+13;
+}
+
+uint32_t PPatchServer::StartFile(PPatchState *State)
+{
+       // security checks: reject file paths containing ':', '..' or slashes/backslashes at the beginning
+       if((State->mCurrentFile.find(':') != std::string::npos)
+               || (State->mCurrentFile.find("..") != std::string::npos)
+               || (State->mCurrentFile.find('/') == 0)
+               || (State->mCurrentFile.find('\\') == 0))
+       {
+               return 0;
+       }
+
+       //std::stringstream path;
+       //path << Config->GetOption("file_path") << "/" << State->mCurrentFile << '\0';
+       State->mSendFile = Filesystem->Open("", State->mCurrentFile.c_str(), Config->GetOption("file_path"));
+       if(State->mSendFile)
+       {
+               ++mNumFileTransfers;
+               uint32_t size = State->mSendFile->GetSize();
+               return size;
+       }
+       return 0;
+}
+
+bool PPatchServer::SendFileData(PClient *Client, PPatchState *State) const
+{
+       if(!State->mSendFile)
+               return false;
+
+       uint16_t size = Config->GetOptionInt("patch_packet_size");
+
+       const int32_t BUFFERSIZE = 4082;
+
+       size = std::min(BUFFERSIZE, std::max((int32_t)size, 1));
+       static uint8_t Buffer[BUFFERSIZE+13];
+
+       State->mSendFile->Seek(State->mFileOffset);
+
+       size = State->mSendFile->Read(&Buffer[13], size);
+       Buffer[0]=0xfe;
+       *(uint16_t*)&Buffer[1]=size+10;
+       Buffer[3]=0x3c;
+       Buffer[4]=0x02;
+       Buffer[5]=0x00;
+       Buffer[6]=0x00;
+       *(uint16_t*)&Buffer[7]=State->mSerial;
+       *(uint32_t*)&Buffer[9]=size;
+       return Client->getTCPConn()->write(Buffer, size+13)==size+13;
+}
+
+bool PPatchServer::ProcessClient(PClient *Client, PPatchState *State)
+{
+       static const uint8_t HANDSHAKE0A[6]={0xfe, 0x03, 0x00, 0x80, 0x03, 0x6b};
+
+       if(!State)
+       {
+               PatchStateMap::iterator node = ClientStates.find(Client);
+               if(node == ClientStates.end())
+                       return false;
+
+               State = node->second;
+       }
+
+       ConnectionTCP *Socket = Client->getTCPConn();
+
+       if(State->mWaitSend && Socket->getSendBufferSize()==0)
+               return false;
+
+       if(State->mState==PPatchState::PS_CONNECTED)
+       {
+           Console->Print("Sending Handshake 0A");
+               Socket->write(HANDSHAKE0A, sizeof(HANDSHAKE0A));
+               //short unsigned int packet = (short unsigned int) HANDSHAKE0A;
+               //Socket->write(htons(packet));
+               State->mState = PPatchState::PS_HANDSHAKE0;
+               Socket->flushSendBuffer();
+       }
+
+       int32_t PacketSize = 0;
+       const uint8_t *Packet = Socket->read(&PacketSize);
+       if(PacketSize > 0)
+       {
+               switch(State->mState)
+               {
+                       case PPatchState::PS_HANDSHAKE1 :
+                       case PPatchState::PS_HANDSHAKE0 :
+                Console->Print("Handling Handshake 0 and 1");
+                               return HandleHandshake(Client, State, Packet, PacketSize);
+
+                       case PPatchState::PS_VERSIONREQUEST :
+                Console->Print("Handling Client Versionsrequest");
+                               return HandleVersionRequest(Client, State, Packet, PacketSize);
+
+                       case PPatchState::PS_GETPATCHORFILE :
+                       case PPatchState::PS_SENDPATCH :
+                       case PPatchState::PS_SENDFILE :
+                Console->Print("Getpatchforfile, sendpatch, sendfile");
+                               return HandleFileRequests(Client, State, Packet, PacketSize);
+                       default:
+                               break;
+               }
+       }
+       return true;
+}
index 9d517b2..ae2c041 100644 (file)
@@ -1,38 +1,38 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <map>\r
-\r
-class PClient;\r
-struct PPatchState;\r
-\r
-class PPatchServer {\r
-private:\r
-    int mNumClients;\r
-    int mNumFileTransfers;\r
-    typedef std::map<PClient *, PPatchState *> PatchStateMap;\r
-    PatchStateMap ClientStates;\r
-\r
-protected:\r
-    bool ProcessClient(PClient *Client, PPatchState *State = nullptr);\r
-//    uint32_t StartPatch(PClient *Client, PPatchState *State);\r
-    uint32_t StartPatch(PPatchState *State);\r
-    bool SendPatchData(PClient *Client, PPatchState *State) const;\r
-//    u32 StartFile(PClient *Client, PPatchState *State);\r
-    uint32_t StartFile(PPatchState *State);\r
-    bool SendFileData(PClient *Client, PPatchState *State) const;\r
-    void FinalizeClient(PClient *Client, PPatchState *State);\r
-    void FinalizeClientDelayed(PClient *Client, PPatchState *State);\r
-\r
-    bool HandleHandshake(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize);\r
-    bool HandleVersionRequest(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize);\r
-    bool HandleFileRequests(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize);\r
-\r
-public:\r
-    PPatchServer();\r
-    ~PPatchServer();\r
-\r
-    void Start();\r
-    void Update();\r
-    void ClientDisconnected(PClient *Client);\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <map>
+
+class PClient;
+struct PPatchState;
+
+class PPatchServer {
+private:
+    int mNumClients;
+    int mNumFileTransfers;
+    typedef std::map<PClient *, PPatchState *> PatchStateMap;
+    PatchStateMap ClientStates;
+
+protected:
+    bool ProcessClient(PClient *Client, PPatchState *State = nullptr);
+//    uint32_t StartPatch(PClient *Client, PPatchState *State);
+    uint32_t StartPatch(PPatchState *State);
+    bool SendPatchData(PClient *Client, PPatchState *State) const;
+//    u32 StartFile(PClient *Client, PPatchState *State);
+    uint32_t StartFile(PPatchState *State);
+    bool SendFileData(PClient *Client, PPatchState *State) const;
+    void FinalizeClient(PClient *Client, PPatchState *State);
+    void FinalizeClientDelayed(PClient *Client, PPatchState *State);
+
+    bool HandleHandshake(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize);
+    bool HandleVersionRequest(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize);
+    bool HandleFileRequests(PClient *Client, PPatchState *State, const uint8_t *Packet, int32_t PacketSize);
+
+public:
+    PPatchServer();
+    ~PPatchServer();
+
+    void Start();
+    void Update();
+    void ClientDisconnected(PClient *Client);
+};
index 0ee9260..6eefaac 100644 (file)
@@ -1,95 +1,95 @@
-#include "PatchServer/Includes.hxx"\r
-#include "Common/Includes.hxx"\r
-\r
-PServer::PServer()\r
-{\r
-    mNumClients = 0;\r
-    mMaxClients = Config->GetOptionInt("maxclients");\r
-    mGMSlots = Config->GetOptionInt("gm_slots");\r
-\r
-    if (mMaxClients==0)\r
-        mMaxClients=1;\r
-    if (mGMSlots==0)\r
-        mGMSlots=1;\r
-    mClients.reserve(mMaxClients + mGMSlots);\r
-    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)\r
-        mClients[i]=0;\r
-}\r
-\r
-PServer::~PServer()\r
-{\r
-    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)\r
-        delete mClients[i];\r
-}\r
-\r
-int32_t PServer::GetMaxClients() const\r
-{\r
-    return mMaxClients;\r
-}\r
-\r
-int32_t PServer::GetGMSlots() const\r
-{\r
-    return mGMSlots;\r
-}\r
-\r
-int32_t PServer::GetNumClients() const\r
-{\r
-    return mNumClients;\r
-}\r
-\r
-int PServer::NewClient()\r
-{\r
-//Console->Print("%d %d", mMaxClients, mGMSlots);\r
-    if (mNumClients==mMaxClients+mGMSlots)\r
-        return -1;\r
-    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)\r
-    {\r
-        if(!mClients[i])\r
-        {\r
-            mClients[i]=new PClient(i);\r
-            ++mNumClients;\r
-            return i;\r
-        }\r
-    }\r
-    return -1;\r
-}\r
-\r
-PClient *PServer::GetClient(int32_t Client) const\r
-{\r
-    if (Client < 0 || Client >= mMaxClients+mGMSlots)\r
-        return 0;\r
-\r
-    return mClients[Client];\r
-}\r
-\r
-void PServer::Update()\r
-{\r
-    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)\r
-    {\r
-        if (mClients[i])\r
-        {\r
-            mClients[i]->Update();\r
-            if (mClients[i]->GetConnection()==PCC_NONE && mClients[i]->getTCPConn() == 0)\r
-            {\r
-                Console->Print("Removing client ...");\r
-                delete mClients[i];\r
-                mClients[i]=0;\r
-                --mNumClients;\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-void PServer::Shutdown()\r
-{\r
-    Console->Print("======================");\r
-    Console->Print("Shutting down Patchserver...");\r
-    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)\r
-    {\r
-        if(mClients[i])\r
-        {\r
-            delete mClients[i];\r
-            mClients[i]=0;\r
-        }\r
-    }\r
-}\r
+#include "PatchServer/Includes.hxx"
+#include "Common/Includes.hxx"
+
+PServer::PServer()
+{
+    mNumClients = 0;
+    mMaxClients = Config->GetOptionInt("maxclients");
+    mGMSlots = Config->GetOptionInt("gm_slots");
+
+    if (mMaxClients==0)
+        mMaxClients=1;
+    if (mGMSlots==0)
+        mGMSlots=1;
+    mClients.reserve(mMaxClients + mGMSlots);
+    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)
+        mClients[i]=0;
+}
+
+PServer::~PServer()
+{
+    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)
+        delete mClients[i];
+}
+
+int32_t PServer::GetMaxClients() const
+{
+    return mMaxClients;
+}
+
+int32_t PServer::GetGMSlots() const
+{
+    return mGMSlots;
+}
+
+int32_t PServer::GetNumClients() const
+{
+    return mNumClients;
+}
+
+int PServer::NewClient()
+{
+//Console->Print("%d %d", mMaxClients, mGMSlots);
+    if (mNumClients==mMaxClients+mGMSlots)
+        return -1;
+    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)
+    {
+        if(!mClients[i])
+        {
+            mClients[i]=new PClient(i);
+            ++mNumClients;
+            return i;
+        }
+    }
+    return -1;
+}
+
+PClient *PServer::GetClient(int32_t Client) const
+{
+    if (Client < 0 || Client >= mMaxClients+mGMSlots)
+        return 0;
+
+    return mClients[Client];
+}
+
+void PServer::Update()
+{
+    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)
+    {
+        if (mClients[i])
+        {
+            mClients[i]->Update();
+            if (mClients[i]->GetConnection()==PCC_NONE && mClients[i]->getTCPConn() == 0)
+            {
+                Console->Print("Removing client ...");
+                delete mClients[i];
+                mClients[i]=0;
+                --mNumClients;
+            }
+        }
+    }
+}
+
+void PServer::Shutdown()
+{
+    Console->Print("======================");
+    Console->Print("Shutting down Patchserver...");
+    for (int32_t i=0; i<mMaxClients+mGMSlots; i++)
+    {
+        if(mClients[i])
+        {
+            delete mClients[i];
+            mClients[i]=0;
+        }
+    }
+}
index efb1dad..f452ca4 100644 (file)
@@ -1,26 +1,26 @@
-#pragma once\r
-\r
-#include <cstdint>\r
-#include <vector>\r
-\r
-class PClient;\r
-\r
-class PServer {\r
-private:\r
-    int32_t mMaxClients;\r
-    int32_t mGMSlots;\r
-    int32_t mNumClients;\r
-    std::vector<PClient *> mClients;\r
-\r
-public:\r
-    PServer();\r
-    ~PServer();\r
-\r
-    int32_t GetMaxClients() const;\r
-    int32_t GetGMSlots() const;\r
-    int32_t GetNumClients() const;\r
-    int32_t NewClient();\r
-    PClient *GetClient(int32_t Client) const;\r
-    void Update();\r
-    void Shutdown();\r
-};\r
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+class PClient;
+
+class PServer {
+private:
+    int32_t mMaxClients;
+    int32_t mGMSlots;
+    int32_t mNumClients;
+    std::vector<PClient *> mClients;
+
+public:
+    PServer();
+    ~PServer();
+
+    int32_t GetMaxClients() const;
+    int32_t GetGMSlots() const;
+    int32_t GetNumClients() const;
+    int32_t NewClient();
+    PClient *GetClient(int32_t Client) const;
+    void Update();
+    void Shutdown();
+};