FF7NameLookup.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. -----------------------------------------------------------------------------
  3. Copyright (c) 15.10.2013 Tobias Peters <tobias.peters@kreativeffekt.at>
  4. This file is part of Q-Gears
  5. Q-Gears is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, version 2.0 (GPLv2) of the License.
  8. Q-Gears is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. -----------------------------------------------------------------------------
  13. */
  14. #ifndef __FF7NameLookup_H__
  15. #define __FF7NameLookup_H__
  16. #include "common/TypeDefine.h"
  17. #include "common/QGearsStringUtil.h"
  18. #include "core/XmlFile.h"
  19. namespace QGears
  20. {
  21. namespace FF7
  22. {
  23. class FF7Metadata : public XmlFile
  24. {
  25. public:
  26. FF7Metadata(Ogre::String file)
  27. : XmlFile(file)
  28. {
  29. TiXmlNode* node = m_File.RootElement();
  30. if (node == nullptr || node->ValueStr() != "metadata")
  31. {
  32. throw std::runtime_error("FF7Metadata: " + m_File.ValueStr() + " is not a valid metadata file! No <metadata> in root.");
  33. }
  34. node = node->FirstChild();
  35. while (node)
  36. {
  37. if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "models")
  38. {
  39. ReadModels(node->FirstChild());
  40. }
  41. else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "animations")
  42. {
  43. ReadAnimations(node->FirstChild());
  44. }
  45. else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "scripts")
  46. {
  47. ReadScripts(node->FirstChild());
  48. }
  49. node = node->NextSibling();
  50. }
  51. }
  52. const String& Animation(const String &key) const
  53. {
  54. auto it = mAnimations.find(key);
  55. if (it != std::end(mAnimations))
  56. {
  57. return it->second;
  58. }
  59. String base_name;
  60. StringUtil::splitBase(key, base_name);
  61. it = mAnimations.find(base_name);
  62. if (it != std::end(mAnimations))
  63. {
  64. return it->second;
  65. }
  66. return key;
  67. }
  68. const String& Model(const String &key) const
  69. {
  70. auto it = mModels.find(key);
  71. if (it != std::end(mModels))
  72. {
  73. return it->second;
  74. }
  75. String base_name;
  76. StringUtil::splitBase(key, base_name);
  77. it = mModels.find(base_name);
  78. if (it != std::end(mModels))
  79. {
  80. return it->second;
  81. }
  82. return key;
  83. }
  84. private:
  85. void ReadModels(TiXmlNode* node)
  86. {
  87. while (node)
  88. {
  89. const auto src = GetString(node, "name");
  90. const auto dst = GetString(node, "target");
  91. mModels[src] = dst;
  92. node = node->NextSibling();
  93. }
  94. }
  95. void ReadAnimations(TiXmlNode* node)
  96. {
  97. while (node)
  98. {
  99. const auto src = GetString(node, "name");
  100. const auto dst = GetString(node, "target");
  101. mAnimations[src] = dst;
  102. node = node->NextSibling();
  103. }
  104. }
  105. void ReadScripts(TiXmlNode* node)
  106. {
  107. while (node)
  108. {
  109. if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "CharacterIds")
  110. {
  111. ReadCharacterIds(node->FirstChild());
  112. }
  113. else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "var_names")
  114. {
  115. ReadVarNames(node->FirstChild());
  116. }
  117. else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "entity_names")
  118. {
  119. ReadEntityNames(node->FirstChild());
  120. }
  121. else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "field")
  122. {
  123. const auto name = GetString(node, "name");
  124. ReadField(node->FirstChild(), name);
  125. }
  126. node = node->NextSibling();
  127. }
  128. }
  129. void ReadField(TiXmlNode* node, const std::string& name)
  130. {
  131. while (node)
  132. {
  133. if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "function")
  134. {
  135. ReadFunction(node, name);
  136. }
  137. else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "entity")
  138. {
  139. const auto oldName = GetString(node, "name");
  140. const auto newName = GetString(node, "new");
  141. mFieldData[name].mEntityNameMap[oldName] = newName;
  142. }
  143. node = node->NextSibling();
  144. }
  145. }
  146. void ReadFunction(TiXmlNode* node, const std::string& fieldName)
  147. {
  148. const auto entityName = GetString(node, "entity_name");
  149. const auto oldFuncName = GetString(node, "name");
  150. const auto newFuncName = GetString(node, "new");
  151. const auto funcComment = GetString(node, "Comment");
  152. mFieldData[fieldName].mFunctionMap[entityName][oldFuncName] = std::make_pair(newFuncName, funcComment);
  153. }
  154. void ReadEntityNames(TiXmlNode* node)
  155. {
  156. while (node)
  157. {
  158. if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "entity")
  159. {
  160. const auto oldName = GetString(node, "name");
  161. const auto newName = GetString(node, "new");
  162. mEntityNameMap[oldName] = newName;
  163. }
  164. node = node->NextSibling();
  165. }
  166. }
  167. void ReadVarNames(TiXmlNode* node)
  168. {
  169. while (node)
  170. {
  171. if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "var")
  172. {
  173. const auto bank = GetInt(node, "Bank");
  174. const auto address = GetInt(node, "Address");
  175. const auto name = GetString(node, "Name");
  176. mVarMap[bank][address] = name;
  177. }
  178. node = node->NextSibling();
  179. }
  180. }
  181. void ReadCharacterIds(TiXmlNode* node)
  182. {
  183. while (node)
  184. {
  185. if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "char")
  186. {
  187. const auto id = GetInt(node, "Id");
  188. const auto name = GetString(node, "Name");
  189. mCharacterIds[id] = name;
  190. node = node->NextSibling();
  191. }
  192. node = node->NextSibling();
  193. }
  194. }
  195. std::pair<String,String> FieldScriptFunctionData(const String& fieldName, const String& entityName, const String& oldFunctionName)
  196. {
  197. // Find a collection of field data for this field
  198. auto fieldIt = mFieldData.find(fieldName);
  199. if (fieldIt != std::end(mFieldData))
  200. {
  201. // See if there is any info for this entity
  202. auto entityIt = fieldIt->second.mFunctionMap.find(entityName);
  203. if (entityIt != std::end(fieldIt->second.mFunctionMap))
  204. {
  205. // See if there is any info for this function in this entity
  206. auto functionIt = entityIt->second.find(oldFunctionName);
  207. if (functionIt != std::end(entityIt->second))
  208. {
  209. return functionIt->second;
  210. }
  211. }
  212. }
  213. return std::make_pair("", "");
  214. }
  215. typedef std::map<String, String> LookupMap;
  216. LookupMap mModels;
  217. LookupMap mAnimations;
  218. std::map<int, String> mCharacterIds;
  219. std::map<int, std::map<int, String>> mVarMap;
  220. LookupMap mEntityNameMap;
  221. struct FieldMetaData
  222. {
  223. std::map<String, std::map<String, std::pair<String,String>>> mFunctionMap; // entity name to old function name finds new function name and comment
  224. LookupMap mEntityNameMap; // old name finds new name
  225. };
  226. std::map<String, FieldMetaData> mFieldData;
  227. friend class NameLookup;
  228. };
  229. class NameLookup
  230. {
  231. public:
  232. NameLookup() = delete;
  233. static String CharName(int charId)
  234. {
  235. auto it = Data().mCharacterIds.find(charId);
  236. if (it != std::end(Data().mCharacterIds))
  237. {
  238. return it->second;
  239. }
  240. if (charId == 254)
  241. {
  242. // Empty becomes lua "nil" value for this special case
  243. return "";
  244. }
  245. return std::to_string(charId);
  246. }
  247. static const String& animation(const String &key)
  248. {
  249. return Data().Animation(key);
  250. }
  251. static const String& model(const String &key)
  252. {
  253. return Data().Model(key);
  254. }
  255. static String FieldScriptVarName(int bank, int addr)
  256. {
  257. auto bankIt = Data().mVarMap.find(bank);
  258. if (bankIt != std::end(Data().mVarMap))
  259. {
  260. auto addrIt = bankIt->second.find(addr);
  261. if (addrIt != std::end(bankIt->second))
  262. {
  263. if (addrIt->second.empty() == false)
  264. {
  265. return addrIt->second;
  266. }
  267. }
  268. }
  269. return "";
  270. }
  271. static String FieldScriptEntityName(const String& oldEntityName)
  272. {
  273. auto it = Data().mEntityNameMap.find(oldEntityName);
  274. if (it != std::end(Data().mEntityNameMap))
  275. {
  276. return it->second;
  277. }
  278. return oldEntityName;
  279. }
  280. static String FieldScriptFunctionComment(const String& fieldName, const String& entityName, const String& oldFunctionName)
  281. {
  282. return Data().FieldScriptFunctionData(fieldName, entityName, oldFunctionName).second;
  283. }
  284. static String FieldScriptFunctionName(const String& fieldName, const String& entityName, const String& oldFunctionName)
  285. {
  286. auto name = Data().FieldScriptFunctionData(fieldName, entityName, oldFunctionName).first;
  287. if (name.empty())
  288. {
  289. return oldFunctionName;
  290. }
  291. return name;
  292. }
  293. static FF7Metadata& Data()
  294. {
  295. static FF7Metadata data("field_models_and_animation_metadata.xml");
  296. return data;
  297. }
  298. };
  299. }
  300. }
  301. #endif // __FF7NameLookup_H__