Advertisement
Guest User

Monster Level

a guest
Sep 28th, 2017
506
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 32.36 KB | None | 0 0
  1. From 4b9c27ae90ec635d55b48a27a5b9f1a7bf618070 Mon Sep 17 00:00:00 2001
  2. From: eduardovicente <dudugt500@gmail.com>
  3. Date: Sat, 23 Sep 2017 12:38:28 -0300
  4. Subject: [PATCH] Monster System 1.0, Monster Level System.
  5.  
  6. ---
  7. .../data/actions/scripts/tools/pokeball.lua        |  32 ++--
  8.  forgottenserver-1.2/data/events/events.xml         |   3 +
  9.  .../data/events/scripts/monster.lua                |  15 ++
  10.  forgottenserver-1.2/data/events/scripts/player.lua | 108 ++++++------
  11.  .../data/monster/Amazons/amazon.xml                |  12 +-
  12.  .../data/monster/Serpents/sea_serpent.xml          |   5 +
  13.  forgottenserver-1.2/src/enums.h                    |  32 +++-
  14.  forgottenserver-1.2/src/events.cpp                 |  75 +++++++++
  15.  forgottenserver-1.2/src/events.h                   |   7 +
  16.  forgottenserver-1.2/src/luascript.cpp              |  89 ++++++++++
  17.  forgottenserver-1.2/src/luascript.h                |   7 +
  18.  forgottenserver-1.2/src/monster.cpp                | 182 +++++++++++++++++++++
  19.  forgottenserver-1.2/src/monster.h                  |  33 +++-
  20.  forgottenserver-1.2/src/monsters.cpp               |  92 +++++++++++
  21.  forgottenserver-1.2/src/monsters.h                 |  10 ++
  22.  15 files changed, 619 insertions(+), 83 deletions(-)
  23.  create mode 100644 forgottenserver-1.2/data/events/scripts/monster.lua
  24.  
  25. diff --git a/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua b/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua
  26. index de6d6f2..328e78f 100644
  27. --- a/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua
  28. +++ b/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua
  29. @@ -1,28 +1,20 @@
  30. -function table.dump(t, depth)
  31. -  if not depth then depth = 0 end
  32. -  for k,v in pairs(t) do
  33. -    str = (' '):rep(depth * 2) .. k .. ': '
  34. -    if type(v) ~= "table" then
  35. -      print(str .. tostring(v))
  36. -    else
  37. -      print(str)
  38. -      table.dump(v, depth+1)
  39. -    end
  40. -  end
  41. -end
  42. + function onUse(player, pokeball, fromPosition, target, toPosition, isHotkey)
  43. +    if (#player:getSummons() > 0) then
  44. +        local pokemon = player:getSummons()[1]
  45. +        pokeball:setPokemonName(pokemon:getName())
  46. +        pokeball:setLevel(pokemon:getLevel())
  47. +        pokeball:setExperience(pokemon:getExperience())
  48. +        pokeball:setMaxHealth(pokemon:getMaxHealth())
  49. +        pokeball:setHealth(pokemon:getHealth())
  50.  
  51. -function onUse(player, pokeball, fromPosition, target, toPosition, isHotkey)
  52. -    local nameList = {"Amazon", "Troll", "Orc", "Fire Devil", "Dragon", "Frost Dragon"}
  53. -
  54. -    if (pokeball:getPokemonName() == "") then
  55. -        pokeball:setPokemonName(nameList[math.random(1, 6)])
  56. -        pokeball:setLevel(math.random(1,100))
  57. -        pokeball:setMaxHealth(100 * pokeball:getLevel())
  58. -        pokeball:setHealth(pokeball:getMaxHealth())
  59. +        pokemon:remove()
  60.      else
  61.          local pokemon = Game.createMonster(pokeball:getPokemonName(), player:getPosition())
  62.          pokemon:setMaster(player)
  63.  
  64. +        pokemon:setLevel(pokeball:getLevel())
  65. +        pokemon:setExperience(pokeball:getExperience())
  66. +
  67.          pokemon:setMaxHealth(pokeball:getMaxHealth())
  68.          local currentHealth = -(pokemon:getHealth() - 1)
  69.          pokemon:addHealth(currentHealth)
  70. diff --git a/forgottenserver-1.2/data/events/events.xml b/forgottenserver-1.2/data/events/events.xml
  71. index 77ba759..4e4af11 100644
  72. --- a/forgottenserver-1.2/data/events/events.xml
  73. +++ b/forgottenserver-1.2/data/events/events.xml
  74. @@ -24,4 +24,7 @@
  75.     <event class="Player" method="onGainExperience" enabled="1" />
  76.     <event class="Player" method="onLoseExperience" enabled="0" />
  77.     <event class="Player" method="onGainSkillTries" enabled="1" />
  78. +
  79. +   <event class="Monster" method="onDeath" enabled="1" />
  80. +   <event class="Monster" method="onGainExperience" enabled="1" />
  81.  </events>
  82. diff --git a/forgottenserver-1.2/data/events/scripts/monster.lua b/forgottenserver-1.2/data/events/scripts/monster.lua
  83. new file mode 100644
  84. index 0000000..0117f6c
  85. --- /dev/null
  86. +++ b/forgottenserver-1.2/data/events/scripts/monster.lua
  87. @@ -0,0 +1,15 @@
  88. +function Monster:onDeath()
  89. +    local player = self:getMaster()
  90. +    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your pokemon fainted!")
  91. +    return true
  92. +end
  93. +
  94. +function Monster:onGainExperience(source, exp, rawExp)
  95. +    if not source or source:isPlayer() then
  96. +        return exp
  97. +    end
  98. +    
  99. +    -- Apply experience stage multiplier
  100. +    --exp = exp * Game.getExperienceStage(self:getLevel())
  101. +    return exp
  102. +end
  103. \ No newline at end of file
  104. diff --git a/forgottenserver-1.2/data/events/scripts/player.lua b/forgottenserver-1.2/data/events/scripts/player.lua
  105. index 40d1694..ff3bf3d 100644
  106. --- a/forgottenserver-1.2/data/events/scripts/player.lua
  107. +++ b/forgottenserver-1.2/data/events/scripts/player.lua
  108. @@ -3,63 +3,69 @@ function Player:onBrowseField(position)
  109.  end
  110.  
  111.  function Player:onLook(thing, position, distance)
  112. -   local description = ""
  113. -  
  114. -   if thing:isPokeball() then
  115. -       description = "You see an ".. thing:getPokemonName()
  116. -       description = description.. ", Level: ".. thing:getLevel().. ", [Hp: ".. thing:getHealth().. " / Max.Hp: ".. thing:getMaxHealth().. "]."
  117. -   else
  118. -       description = "You see " .. thing:getDescription(distance)
  119. -       if self:getGroup():getAccess() then
  120. -           if thing:isItem() then
  121. -               description = string.format("%s\nItem ID: %d", description, thing:getId())
  122. -
  123. -               local actionId = thing:getActionId()
  124. -               if actionId ~= 0 then
  125. -                   description = string.format("%s, Action ID: %d", description, actionId)
  126. -               end
  127. -
  128. -               local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
  129. -               if uniqueId > 0 and uniqueId < 65536 then
  130. -                   description = string.format("%s, Unique ID: %d", description, uniqueId)
  131. -               end
  132. -
  133. -               local itemType = thing:getType()
  134. -
  135. -               local transformEquipId = itemType:getTransformEquipId()
  136. -               local transformDeEquipId = itemType:getTransformDeEquipId()
  137. -               if transformEquipId ~= 0 then
  138. -                   description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
  139. -               elseif transformDeEquipId ~= 0 then
  140. -                   description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
  141. -               end
  142. -
  143. -               local decayId = itemType:getDecayId()
  144. -               if decayId ~= -1 then
  145. -                   description = string.format("%s\nDecays to: %d", description, decayId)
  146. -               end
  147. -           elseif thing:isCreature() then
  148. -               local str = "%s\nHealth: %d / %d"
  149. -               if thing:getMaxMana() > 0 then
  150. -                   str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
  151. -               end
  152. -               description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
  153. +   local description = "You see " .. thing:getDescription(distance)
  154. +   if self:getGroup():getAccess() then
  155. +       if thing:isItem() then
  156. +           if thing:isPokeball() then
  157. +               description = "You see an ".. thing:getPokemonName()
  158. +               description = description.. ", Level: ".. thing:getLevel().. ", [Hp: ".. thing:getHealth().. " / Max.Hp: ".. thing:getMaxHealth().. "]."
  159. +           end
  160. +           description = string.format("%s\nItem ID: %d", description, thing:getId())
  161. +
  162. +           local actionId = thing:getActionId()
  163. +           if actionId ~= 0 then
  164. +               description = string.format("%s, Action ID: %d", description, actionId)
  165. +           end
  166. +
  167. +           local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
  168. +           if uniqueId > 0 and uniqueId < 65536 then
  169. +               description = string.format("%s, Unique ID: %d", description, uniqueId)
  170.             end
  171.  
  172. -           local position = thing:getPosition()
  173. -           description = string.format(
  174. -               "%s\nPosition: %d, %d, %d",
  175. -               description, position.x, position.y, position.z
  176. -           )
  177. +           local itemType = thing:getType()
  178. +
  179. +           local transformEquipId = itemType:getTransformEquipId()
  180. +           local transformDeEquipId = itemType:getTransformDeEquipId()
  181. +           if transformEquipId ~= 0 then
  182. +               description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
  183. +           elseif transformDeEquipId ~= 0 then
  184. +               description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
  185. +           end
  186.  
  187. -           if thing:isCreature() then
  188. -               if thing:isPlayer() then
  189. -                   description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
  190. -               end
  191. +           local decayId = itemType:getDecayId()
  192. +           if decayId ~= -1 then
  193. +               description = string.format("%s\nDecays to: %d", description, decayId)
  194. +           end
  195. +       elseif thing:isCreature() then
  196. +           if thing:isMonster() then
  197. +               local level = thing:getLevel()
  198. +               local currentExp = thing:getExperience()
  199. +               local expForNextLevel = thing:getExpForLevel(level + 1) - currentExp
  200. +              
  201. +               description = description.. "\nLevel: ".. level
  202. +               description = description.. "\nExp: ".. thing:getExperience()
  203. +               description = description.. " / Exp for next level: ".. expForNextLevel
  204. +           end
  205. +          
  206. +           local str = "%s\nHealth: %d / %d"
  207. +           if thing:getMaxMana() > 0 then
  208. +               str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
  209.             end
  210. +           description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
  211.         end
  212. -   end
  213.  
  214. +       local position = thing:getPosition()
  215. +       description = string.format(
  216. +           "%s\nPosition: %d, %d, %d",
  217. +           description, position.x, position.y, position.z
  218. +       )
  219. +
  220. +       if thing:isCreature() then
  221. +           if thing:isPlayer() then
  222. +               description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
  223. +           end
  224. +       end
  225. +   end
  226.     self:sendTextMessage(MESSAGE_INFO_DESCR, description)
  227.  end
  228.  
  229. diff --git a/forgottenserver-1.2/data/monster/Amazons/amazon.xml b/forgottenserver-1.2/data/monster/Amazons/amazon.xml
  230. index d2d5490..3e08f61 100644
  231. --- a/forgottenserver-1.2/data/monster/Amazons/amazon.xml
  232. +++ b/forgottenserver-1.2/data/monster/Amazons/amazon.xml
  233. @@ -2,7 +2,11 @@
  234.  <monster name="Amazon" nameDescription="an amazon" race="blood" experience="60" speed="180" manacost="390">
  235.     <health now="110" max="110" />
  236.     <look type="137" head="113" body="120" legs="114" feet="132" corpse="20323" />
  237. -   <targetchange interval="4000" chance="10" />
  238. +
  239. +   <level min="10" max="10" />
  240. +   <basestatus hp="150" attack="50" defense="20" specialattack="10" specialdefense="10" speed="25"  />
  241. +   <statusperlevel hp="2" attack="5" defense="1" specialattack="1.5" specialdefense="0.5" speed="3" />
  242. +
  243.     <flags>
  244.         <flag summonable="1" />
  245.         <flag attackable="1" />
  246. @@ -16,9 +20,11 @@
  247.         <flag staticattack="90" />
  248.         <flag runonhealth="10" />
  249.     </flags>
  250. +
  251. +   <targetchange interval="1000" chance="0" />
  252.     <attacks>
  253. -       <attack name="melee" interval="2000" min="0" max="-45" />
  254. -       <attack name="physical" interval="2000" chance="15" range="7" min="0" max="-40">
  255. +       <attack name="melee" interval="2000" min="-0" max="-45" />
  256. +       <attack name="physical" interval="2000" chance="80" range="7" min="-0" max="-40">
  257.             <attribute key="shootEffect" value="throwingknife" />
  258.         </attack>
  259.     </attacks>
  260. diff --git a/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml b/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml
  261. index dc77198..e60fdca 100644
  262. --- a/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml
  263. +++ b/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml
  264. @@ -2,6 +2,11 @@
  265.  <monster name="Sea Serpent" nameDescription="a sea serpent" race="blood" experience="2300" speed="350" manacost="390">
  266.     <health now="1950" max="1950" />
  267.     <look type="275" corpse="8307" />
  268. +
  269. +   <level min="50" max="75" />
  270. +   <basestatus hp="150" attack="50" defense="30" specialattack="25" specialdefense="10" speed="55"  />
  271. +   <statusperlevel hp="5" attack="10" defense="3" specialattack="25.5" specialdefense="5.5" speed="10" />
  272. +
  273.     <targetchange interval="4000" chance="10" />
  274.     <flags>
  275.         <flag summonable="0" />
  276. diff --git a/forgottenserver-1.2/src/enums.h b/forgottenserver-1.2/src/enums.h
  277. index f927825..8b459f6 100644
  278. --- a/forgottenserver-1.2/src/enums.h
  279. +++ b/forgottenserver-1.2/src/enums.h
  280. @@ -548,12 +548,32 @@ struct CombatDamage
  281.  
  282.  struct PokemonStatus
  283.  {
  284. -   double attack = 0;
  285. -   double defense = 0;
  286. -   double hp = 0;
  287. -   double specialAttack = 0;
  288. -   double specialDefense = 0;
  289. -   double speed = 0;
  290. +   void multiplier(int multiplier)
  291. +   {
  292. +       attack *= multiplier;
  293. +       defense *= multiplier;
  294. +       hp *= multiplier;
  295. +       specialAttack *= multiplier;
  296. +       specialDefense *= multiplier;
  297. +       speed *= multiplier;
  298. +   }
  299. +
  300. +   void addition(int addition)
  301. +   {
  302. +       attack += addition;
  303. +       defense += addition;
  304. +       hp += addition;
  305. +       specialAttack += addition;
  306. +       specialDefense += addition;
  307. +       speed += addition;
  308. +   }
  309. +
  310. +   double attack = 1;
  311. +   double defense = 1;
  312. +   double hp = 1;
  313. +   double specialAttack = 1;
  314. +   double specialDefense = 1;
  315. +   double speed = 1;
  316.  };
  317.  
  318.  typedef std::list<MarketOffer> MarketOfferList;
  319. diff --git a/forgottenserver-1.2/src/events.cpp b/forgottenserver-1.2/src/events.cpp
  320. index b1a3758..c986fe9 100644
  321. --- a/forgottenserver-1.2/src/events.cpp
  322. +++ b/forgottenserver-1.2/src/events.cpp
  323. @@ -111,6 +111,14 @@ bool Events::load()
  324.             } else {
  325.                 std::cout << "[Warning - Events::load] Unknown player method: " << methodName << std::endl;
  326.             }
  327. +       } else if (className == "Monster") {
  328. +           if (methodName == "onDeath") {
  329. +               info.monsterOnDeath = event;
  330. +           } else if (methodName == "onGainExperience") {
  331. +               info.monsterOnGainExperience = event;
  332. +           } else {
  333. +               std::cout << "[Warning - Events::load] Unknown monster method: " << methodName << std::endl;
  334. +           }
  335.         } else {
  336.             std::cout << "[Warning - Events::load] Unknown class: " << className << std::endl;
  337.         }
  338. @@ -723,3 +731,70 @@ void Events::eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_
  339.  
  340.     scriptInterface.resetScriptEnv();
  341.  }
  342. +
  343. +void Events::eventMonsterOnDeath(Monster* monster) {
  344. +   // Monster:onDeath(monster)
  345. +   if (info.monsterOnDeath == -1) {
  346. +       return;
  347. +   }
  348. +
  349. +   if (!scriptInterface.reserveScriptEnv()) {
  350. +       std::cout << "[Error - Events::eventMonsterOnDeath] Call stack overflow" << std::endl;
  351. +       return;
  352. +   }
  353. +
  354. +   ScriptEnvironment* env = scriptInterface.getScriptEnv();
  355. +   env->setScriptId(info.monsterOnDeath, &scriptInterface);
  356. +
  357. +   lua_State* L = scriptInterface.getLuaState();
  358. +   scriptInterface.pushFunction(info.monsterOnDeath);
  359. +
  360. +   LuaScriptInterface::pushUserdata<Monster>(L, monster);
  361. +   LuaScriptInterface::setMetatable(L, -1, "Monster");
  362. +
  363. +   scriptInterface.callVoidFunction(1);
  364. +}
  365. +
  366. +void Events::eventMonsterOnGainExperience(Monster* monster, Creature* source, uint64_t& exp, uint64_t rawExp)
  367. +{
  368. +   // Monster:onGainExperience(source, exp, rawExp)
  369. +   // rawExp gives the original exp which is not multiplied
  370. +   if (info.monsterOnGainExperience == -1) {
  371. +       return;
  372. +   }
  373. +
  374. +   if (!scriptInterface.reserveScriptEnv()) {
  375. +       std::cout << "[Error - Events::eventPlayerOnGainExperience] Call stack overflow" << std::endl;
  376. +       return;
  377. +   }
  378. +
  379. +   ScriptEnvironment* env = scriptInterface.getScriptEnv();
  380. +   env->setScriptId(info.monsterOnGainExperience, &scriptInterface);
  381. +
  382. +   lua_State* L = scriptInterface.getLuaState();
  383. +   scriptInterface.pushFunction(info.monsterOnGainExperience);
  384. +
  385. +   LuaScriptInterface::pushUserdata<Monster>(L, monster);
  386. +   LuaScriptInterface::setMetatable(L, -1, "Monster");
  387. +
  388. +   if (source) {
  389. +       LuaScriptInterface::pushUserdata<Creature>(L, source);
  390. +       LuaScriptInterface::setCreatureMetatable(L, -1, source);
  391. +   }
  392. +   else {
  393. +       lua_pushnil(L);
  394. +   }
  395. +
  396. +   lua_pushnumber(L, exp);
  397. +   lua_pushnumber(L, rawExp);
  398. +
  399. +   if (scriptInterface.protectedCall(L, 4, 1) != 0) {
  400. +       LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
  401. +   }
  402. +   else {
  403. +       exp = LuaScriptInterface::getNumber<uint64_t>(L, -1);
  404. +       lua_pop(L, 1);
  405. +   }
  406. +
  407. +   scriptInterface.resetScriptEnv();
  408. +}
  409. \ No newline at end of file
  410. diff --git a/forgottenserver-1.2/src/events.h b/forgottenserver-1.2/src/events.h
  411. index 03a58cc..ef22bb3 100644
  412. --- a/forgottenserver-1.2/src/events.h
  413. +++ b/forgottenserver-1.2/src/events.h
  414. @@ -53,6 +53,10 @@ class Events
  415.         int32_t playerOnGainExperience = -1;
  416.         int32_t playerOnLoseExperience = -1;
  417.         int32_t playerOnGainSkillTries = -1;
  418. +
  419. +       // Pokemon
  420. +       int32_t monsterOnDeath = -1;
  421. +       int32_t monsterOnGainExperience = -1;
  422.     };
  423.  
  424.     public:
  425. @@ -85,6 +89,9 @@ class Events
  426.         void eventPlayerOnLoseExperience(Player* player, uint64_t& exp);
  427.         void eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_t& tries);
  428.  
  429. +       // Pokemon
  430. +       void eventMonsterOnDeath(Monster* monster);
  431. +       void eventMonsterOnGainExperience(Monster* monster, Creature* source, uint64_t& exp, uint64_t rawExp);
  432.     private:
  433.         LuaScriptInterface scriptInterface;
  434.         EventsInfo info;
  435. diff --git a/forgottenserver-1.2/src/luascript.cpp b/forgottenserver-1.2/src/luascript.cpp
  436. index 6c975d6..ea3556e 100644
  437. --- a/forgottenserver-1.2/src/luascript.cpp
  438. +++ b/forgottenserver-1.2/src/luascript.cpp
  439. @@ -2306,6 +2306,14 @@ void LuaScriptInterface::registerFunctions()
  440.     registerMethod("Monster", "selectTarget", LuaScriptInterface::luaMonsterSelectTarget);
  441.     registerMethod("Monster", "searchTarget", LuaScriptInterface::luaMonsterSearchTarget);
  442.  
  443. +   registerMethod("Monster", "getLevel", LuaScriptInterface::luaMonsterGetLevel);
  444. +   registerMethod("Monster", "setLevel", LuaScriptInterface::luaMonsterSetLevel);
  445. +
  446. +   registerMethod("Monster", "getExperience", LuaScriptInterface::luaMonsterGetExperience);
  447. +   registerMethod("Monster", "setExperience", LuaScriptInterface::luaMonsterSetExperience);
  448. +   registerMethod("Monster", "addExperience", LuaScriptInterface::luaMonsterAddExperience);
  449. +   registerMethod("Monster", "getExpForLevel", LuaScriptInterface::luaMonsterGetExpForLevel);
  450. +
  451.     // Npc
  452.     registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate);
  453.     registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare);
  454. @@ -9759,6 +9767,87 @@ int LuaScriptInterface::luaMonsterSearchTarget(lua_State* L)
  455.     return 1;
  456.  }
  457.  
  458. +int LuaScriptInterface::luaMonsterGetLevel(lua_State* L)
  459. +{
  460. +   // monster:getLevel()
  461. +   Monster* monster = getUserdata<Monster>(L, 1);
  462. +   if (monster) {
  463. +       lua_pushnumber(L, monster->getLevel());
  464. +   }
  465. +   else {
  466. +       lua_pushnumber(L, 0);
  467. +   }
  468. +
  469. +   return 1;
  470. +}
  471. +
  472. +int LuaScriptInterface::luaMonsterSetLevel(lua_State *L)
  473. +{
  474. +   // monster:setLevel(level)
  475. +   Monster* monster = getUserdata<Monster>(L, 1);
  476. +   if (monster) {
  477. +       uint32_t level = getNumber<uint32_t>(L, 2);
  478. +       monster->setLevel(level);
  479. +       pushBoolean(L, true);
  480. +   }
  481. +
  482. +   return 1;
  483. +}
  484. +
  485. +int LuaScriptInterface::luaMonsterGetExperience(lua_State* L)
  486. +{
  487. +   // monster:getExperience()
  488. +   Monster* monster = getUserdata<Monster>(L, 1);
  489. +   if (monster) {
  490. +       lua_pushnumber(L, monster->getExperience());
  491. +   }
  492. +   else {
  493. +       lua_pushnumber(L, 0);
  494. +   }
  495. +
  496. +   return 1;
  497. +}
  498. +
  499. +int LuaScriptInterface::luaMonsterSetExperience(lua_State* L)
  500. +{
  501. +   // monster:setExperience(exp)
  502. +   Monster* monster = getUserdata<Monster>(L, 1);
  503. +   if (monster) {
  504. +       uint64_t exp = getNumber<uint64_t>(L, 2);
  505. +       monster->setExperience(exp);
  506. +   }
  507. +   return 1;
  508. +}
  509. +
  510. +int LuaScriptInterface::luaMonsterAddExperience(lua_State* L)
  511. +{
  512. +   // monster:addExperience(experience[, sendText = false])
  513. +   Monster* monster = getUserdata<Monster>(L, 1);
  514. +   if (monster) {
  515. +       int64_t experience = getNumber<int64_t>(L, 2);
  516. +       bool sendText = getBoolean(L, 3, false);
  517. +       monster->addExperience(nullptr, experience, sendText);
  518. +       pushBoolean(L, true);
  519. +   }
  520. +
  521. +   return 1;
  522. +}
  523. +
  524. +int LuaScriptInterface::luaMonsterGetExpForLevel(lua_State* L)
  525. +{
  526. +   // monster:getExpForLevel(level)
  527. +   Monster* monster = getUserdata<Monster>(L, 1);
  528. +   if (monster) {
  529. +       uint32_t level = getNumber<uint32_t>(L, 2);
  530. +       lua_pushnumber(L, monster->getExpForLevel(level));
  531. +   }
  532. +   else {
  533. +       lua_pushnumber(L, 0);
  534. +   }
  535. +
  536. +   return 1;
  537. +}
  538. +
  539.  // Npc
  540.  int LuaScriptInterface::luaNpcCreate(lua_State* L)
  541.  {
  542. diff --git a/forgottenserver-1.2/src/luascript.h b/forgottenserver-1.2/src/luascript.h
  543. index 6b3e933..d228a0e 100644
  544. --- a/forgottenserver-1.2/src/luascript.h
  545. +++ b/forgottenserver-1.2/src/luascript.h
  546. @@ -1010,6 +1010,13 @@ class LuaScriptInterface
  547.         static int luaMonsterSelectTarget(lua_State* L);
  548.         static int luaMonsterSearchTarget(lua_State* L);
  549.  
  550. +       static int luaMonsterGetLevel(lua_State* L);
  551. +       static int luaMonsterSetLevel(lua_State* L);
  552. +       static int luaMonsterGetExperience(lua_State* L);
  553. +       static int luaMonsterSetExperience(lua_State* L);
  554. +       static int luaMonsterAddExperience(lua_State* L);
  555. +       static int luaMonsterGetExpForLevel(lua_State* L);
  556. +
  557.         // Npc
  558.         static int luaNpcCreate(lua_State* L);
  559.  
  560. diff --git a/forgottenserver-1.2/src/monster.cpp b/forgottenserver-1.2/src/monster.cpp
  561. index ac0ac12..f9d722b 100644
  562. --- a/forgottenserver-1.2/src/monster.cpp
  563. +++ b/forgottenserver-1.2/src/monster.cpp
  564. @@ -22,9 +22,13 @@
  565.  #include "monster.h"
  566.  #include "game.h"
  567.  #include "spells.h"
  568. +#include "events.h"
  569. +#include "configmanager.h"
  570.  
  571. +extern ConfigManager g_config;
  572.  extern Game g_game;
  573.  extern Monsters g_monsters;
  574. +extern Events* g_events;
  575.  
  576.  int32_t Monster::despawnRange;
  577.  int32_t Monster::despawnRadius;
  578. @@ -45,6 +49,14 @@ Monster::Monster(MonsterType* mtype) :
  579.     strDescription(asLowerCaseString(mtype->nameDescription)),
  580.     mType(mtype)
  581.  {
  582. +
  583. +   uint32_t levelCalc = mType->info.spawnLevel.max - mType->info.spawnLevel.min;
  584. +   level = (rand() % (levelCalc > 0 ? levelCalc : 1)) + mType->info.spawnLevel.min;
  585. +   experience = getExpForLevel(level);
  586. +
  587. +   status = mType->info.statusPerLevel;
  588. +   status.multiplier(level);
  589. +
  590.     defaultOutfit = mType->info.outfit;
  591.     currentOutfit = mType->info.outfit;
  592.     skull = mType->info.skull;
  593. @@ -60,6 +72,8 @@ Monster::Monster(MonsterType* mtype) :
  594.             std::cout << "[Warning - Monster::Monster] Unknown event name: " << scriptName << std::endl;
  595.         }
  596.     }
  597. +
  598. +   updateBaseStatus();
  599.  }
  600.  
  601.  Monster::~Monster()
  602. @@ -2002,3 +2016,171 @@ void Monster::getPathSearchParams(const Creature* creature, FindPathParams& fpp)
  603.         fpp.fullPathSearch = !canUseAttack(getPosition(), creature);
  604.     }
  605.  }
  606. +
  607. +uint64_t Monster::getExperience() {
  608. +   return experience;
  609. +}
  610. +
  611. +void Monster::setExperience(uint64_t exp) {
  612. +   experience = exp;
  613. +}
  614. +
  615. +uint64_t Monster::getExpForLevel(int32_t lv) {
  616. +   lv--;
  617. +   return ((50ULL * lv * lv * lv) - (150ULL * lv * lv) + (400ULL * lv)) / 3ULL;
  618. +}
  619. +
  620. +uint8_t Monster::getPercentLevel(uint64_t count, uint64_t nextLevelCount) {
  621. +   if (nextLevelCount == 0)
  622. +       return 0;
  623. +
  624. +   uint8_t result = (count * 100) / nextLevelCount;
  625. +   if (result > 100)
  626. +       return 0;
  627. +
  628. +   return result;
  629. +}
  630. +
  631. +void Monster::addExperience(Creature* source, uint64_t exp, bool sendText) {
  632. +
  633. +   uint64_t currLevelExp = getExpForLevel(level);
  634. +   uint64_t nextLevelExp = getExpForLevel(level + 1);
  635. +   uint64_t rawExp = exp;
  636. +   if (currLevelExp >= nextLevelExp) {
  637. +       //monster has reached max level
  638. +       levelPercent = 0;
  639. +       return;
  640. +   }
  641. +
  642. +   Player* master = nullptr;
  643. +   if (getMaster()) {
  644. +       master = getMaster()->getPlayer();
  645. +   }
  646. +
  647. +   if (master) {
  648. +       g_events->eventMonsterOnGainExperience(this, source, exp, rawExp);
  649. +       if (exp == 0) {
  650. +           return;
  651. +       }
  652. +   }
  653. +
  654. +   experience += exp;
  655. +
  656. +   if (master && sendText) {
  657. +       std::string expString = std::to_string(exp) + (exp != 1 ? " experience points." : " experience point.");
  658. +
  659. +       TextMessage message(MESSAGE_EXPERIENCE, "Your pokemon gained " + expString);
  660. +       message.position = position;
  661. +       message.primary.value = exp;
  662. +       message.primary.color = TEXTCOLOR_WHITE_EXP;
  663. +       master->sendTextMessage(message);
  664. +   }
  665. +
  666. +   uint32_t prevLevel = level;
  667. +   while (experience >= nextLevelExp) {
  668. +       ++level;
  669. +
  670. +       onAdvancedLevel();
  671. +
  672. +       currLevelExp = nextLevelExp;
  673. +       nextLevelExp = getExpForLevel(level + 1);
  674. +       if (currLevelExp >= nextLevelExp) {
  675. +           //player has reached max level
  676. +           break;
  677. +       }
  678. +   }
  679. +
  680. +   if (prevLevel != level) {
  681. +       health = healthMax;
  682. +
  683. +       setBaseSpeed(getBaseSpeed());
  684. +       g_game.changeSpeed(this, 0);
  685. +       g_game.addCreatureHealth(this);
  686. +
  687. +       if (master != nullptr && sendText) {
  688. +           std::ostringstream ss;
  689. +           ss << "Your pokemon advanced from Level " << prevLevel << " to Level " << level << '.';
  690. +           master->sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str());
  691. +       }
  692. +   }
  693. +
  694. +   if (nextLevelExp > currLevelExp)
  695. +       levelPercent = getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
  696. +   else
  697. +       levelPercent = 0;
  698. +}
  699. +
  700. +void Monster::onGainExperience(uint64_t gainExp, Creature* target)
  701. +{
  702. +   if (gainExp == 0)
  703. +       return;
  704. +
  705. +   if (master)
  706. +       master->onGainExperience(gainExp, target);
  707. +
  708. +   gainExperience(target, gainExp);
  709. +}
  710. +
  711. +void Monster::gainExperience(Creature* source, uint64_t gainExp) {
  712. +   if (gainExp == 0)
  713. +       return;
  714. +
  715. +   addExperience(source, gainExp, true);
  716. +}
  717. +
  718. +uint64_t Monster::getGainedExperience(Creature* attacker) const
  719. +{
  720. +   Monster* attackerMonster = attacker->getMonster();
  721. +   if (attackerMonster && attackerMonster != this) {
  722. +
  723. +       uint64_t expLost = 0;
  724. +       if (getLevel() <= 1)
  725. +           expLost = mType->info.experience;
  726. +       else
  727. +           expLost = getLostExperience();
  728. +
  729. +       return std::max<uint64_t>(0, std::floor(expLost * getDamageRatio(attacker) * 0.75));
  730. +   }
  731. +
  732. +   return 0;
  733. +}
  734. +
  735. +double Monster::getLostPercent() const
  736. +{
  737. +   int32_t deathLosePercent = g_config.getNumber(ConfigManager::DEATH_LOSE_PERCENT);
  738. +   if (deathLosePercent != -1)
  739. +       return std::max<int32_t>(0, deathLosePercent) / 100.;
  740. +
  741. +   double lossPercent;
  742. +   if (level >= 25) {
  743. +       double tmpLevel = level + (levelPercent / 100.);
  744. +       lossPercent = static_cast<double>((tmpLevel + 50) * 50 * ((tmpLevel * tmpLevel) - (5 * tmpLevel) + 8)) / experience;
  745. +   } else
  746. +       lossPercent = 10;
  747. +
  748. +   return lossPercent * pow(0.92, 0) / 100;
  749. +}
  750. +
  751. +const uint32_t Monster::getLevel() const
  752. +{
  753. +   return level;
  754. +}
  755. +
  756. +void Monster::setLevel(uint32_t lvl)
  757. +{
  758. +   level = lvl;
  759. +}
  760. +
  761. +void Monster::onAdvancedLevel()
  762. +{
  763. +   status = mType->info.statusPerLevel;
  764. +   status.addition(1);
  765. +
  766. +   updateBaseStatus();
  767. +}
  768. +
  769. +void Monster::updateBaseStatus()
  770. +{
  771. +   healthMax = mType->info.baseStatus.hp * status.hp;
  772. +   health = healthMax;
  773. +}
  774. \ No newline at end of file
  775. diff --git a/forgottenserver-1.2/src/monster.h b/forgottenserver-1.2/src/monster.h
  776. index c699965..4d8f7ee 100644
  777. --- a/forgottenserver-1.2/src/monster.h
  778. +++ b/forgottenserver-1.2/src/monster.h
  779. @@ -173,6 +173,29 @@ class Monster final : public Creature
  780.         BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
  781.                              bool checkDefense = false, bool checkArmor = false, bool field = false);
  782.  
  783. +       uint64_t getExperience();
  784. +       void setExperience(uint64_t exp);
  785. +
  786. +       static uint64_t getExpForLevel(int32_t lv);
  787. +       static uint8_t getPercentLevel(uint64_t count, uint64_t nextLevelCount);
  788. +
  789. +       void addExperience(Creature* source, uint64_t exp, bool sendText = false);
  790. +       void gainExperience(Creature* source, uint64_t gainExp);
  791. +       void onGainExperience(uint64_t gainExp, Creature* target) final;
  792. +
  793. +       uint64_t getGainedExperience(Creature* attacker) const final;
  794. +       double getLostPercent() const;
  795. +       uint64_t getLostExperience() const final {
  796. +
  797. +           return skillLoss ? static_cast<uint64_t>(experience * getLostPercent()) : 0;
  798. +       }
  799. +
  800. +       const uint32_t getLevel() const;
  801. +       void setLevel(uint32_t lvl);
  802. +       void onAdvancedLevel();
  803. +
  804. +       void updateBaseStatus();
  805. +
  806.         static uint32_t monsterAutoID;
  807.  
  808.     private:
  809. @@ -184,6 +207,13 @@ class Monster final : public Creature
  810.         MonsterType* mType;
  811.         Spawn* spawn = nullptr;
  812.  
  813. +       uint32_t level = 1;
  814. +       uint8_t levelPercent = 0;
  815. +
  816. +       uint64_t experience = 0;   
  817. +
  818. +       PokemonStatus status;
  819. +
  820.         int64_t lastMeleeAttack = 0;
  821.  
  822.         uint32_t attackTicks = 0;
  823. @@ -251,9 +281,6 @@ class Monster final : public Creature
  824.         bool isFriend(const Creature* creature) const;
  825.         bool isOpponent(const Creature* creature) const;
  826.  
  827. -       uint64_t getLostExperience() const final {
  828. -           return skillLoss ? mType->info.experience : 0;
  829. -       }
  830.         uint16_t getLookCorpse() const final {
  831.             return mType->info.lookcorpse;
  832.         }
  833. diff --git a/forgottenserver-1.2/src/monsters.cpp b/forgottenserver-1.2/src/monsters.cpp
  834. index caa1aee..aa28f81 100644
  835. --- a/forgottenserver-1.2/src/monsters.cpp
  836. +++ b/forgottenserver-1.2/src/monsters.cpp
  837. @@ -824,6 +824,98 @@ bool Monsters::loadMonster(const std::string& file, const std::string& monsterNa
  838.             mType->info.lookcorpse = pugi::cast<uint16_t>(attr.value());
  839.         }
  840.     }
  841. +  
  842. +   if ((node = monsterNode.child("level"))) {
  843. +       if ((attr = node.attribute("min"))) {
  844. +           mType->info.spawnLevel.min = pugi::cast<uint32_t>(attr.value());
  845. +       }
  846. +       else {
  847. +           std::cout << "[Error - Monsters::loadMonster] Missing spawn level min. " << file << std::endl;
  848. +       }
  849. +
  850. +       if ((attr = node.attribute("max"))) {
  851. +           mType->info.spawnLevel.max = pugi::cast<uint32_t>(attr.value());
  852. +       }
  853. +       else {
  854. +           std::cout << "[Error - Monsters::loadMonster] Missing spawn level max. " << file << std::endl;
  855. +       }
  856. +   }
  857. +
  858. +   if ((node = monsterNode.child("basestatus"))) {
  859. +       if ((attr = node.attribute("hp"))) {
  860. +           mType->info.baseStatus.hp = pugi::cast<double>(attr.value());
  861. +       } else {
  862. +           std::cout << "[Error - Monsters::loadMonster] Missing base status health. " << file << std::endl;
  863. +       }
  864. +
  865. +       if ((attr = node.attribute("attack"))) {
  866. +           mType->info.baseStatus.attack = pugi::cast<double>(attr.value());
  867. +       } else {
  868. +           std::cout << "[Error - Monsters::loadMonster] Missing base status attack. " << file << std::endl;
  869. +       }
  870. +
  871. +       if ((attr = node.attribute("defense"))) {
  872. +           mType->info.baseStatus.defense = pugi::cast<double>(attr.value());
  873. +       } else {
  874. +           std::cout << "[Error - Monsters::loadMonster] Missing base status defense. " << file << std::endl;
  875. +       }
  876. +
  877. +       if ((attr = node.attribute("specialattack"))) {
  878. +           mType->info.baseStatus.specialAttack = pugi::cast<double>(attr.value());
  879. +       } else {
  880. +           std::cout << "[Error - Monsters::loadMonster] Missing base status special attack. " << file << std::endl;
  881. +       }
  882. +
  883. +       if ((attr = node.attribute("specialdefense"))) {
  884. +           mType->info.baseStatus.specialDefense = pugi::cast<double>(attr.value());
  885. +       } else {
  886. +           std::cout << "[Error - Monsters::loadMonster] Missing base status special defense. " << file << std::endl;
  887. +       }
  888. +
  889. +       if ((attr = node.attribute("speed"))) {
  890. +           mType->info.baseStatus.speed = pugi::cast<double>(attr.value());
  891. +       } else {
  892. +           std::cout << "[Error - Monsters::loadMonster] Missing status speed. " << file << std::endl;
  893. +       }
  894. +   }
  895. +
  896. +   if ((node = monsterNode.child("statusperlevel"))) {
  897. +       if ((attr = node.attribute("hp"))) {
  898. +           mType->info.statusPerLevel.hp = pugi::cast<double>(attr.value());
  899. +       } else {
  900. +           std::cout << "[Error - Monsters::loadMonster] Missing status per level health. " << file << std::endl;
  901. +       }
  902. +
  903. +       if ((attr = node.attribute("attack"))) {
  904. +           mType->info.statusPerLevel.attack = pugi::cast<double>(attr.value());
  905. +       } else {
  906. +           std::cout << "[Error - Monsters::loadMonster] Missing status per level attack. " << file << std::endl;
  907. +       }
  908. +
  909. +       if ((attr = node.attribute("defense"))) {
  910. +           mType->info.statusPerLevel.defense = pugi::cast<double>(attr.value());
  911. +       } else {
  912. +           std::cout << "[Error - Monsters::loadMonster] Missing status per level defense. " << file << std::endl;
  913. +       }
  914. +
  915. +       if ((attr = node.attribute("specialattack"))) {
  916. +           mType->info.statusPerLevel.specialAttack = pugi::cast<double>(attr.value());
  917. +       } else {
  918. +           std::cout << "[Error - Monsters::loadMonster] Missing status per level special attack. " << file << std::endl;
  919. +       }
  920. +
  921. +       if ((attr = node.attribute("specialdefense"))) {
  922. +           mType->info.statusPerLevel.specialDefense = pugi::cast<double>(attr.value());
  923. +       } else {
  924. +           std::cout << "[Error - Monsters::loadMonster] Missing status per level special defense. " << file << std::endl;
  925. +       }
  926. +
  927. +       if ((attr = node.attribute("speed"))) {
  928. +           mType->info.statusPerLevel.speed = pugi::cast<double>(attr.value());
  929. +       } else {
  930. +           std::cout << "[Error - Monsters::loadMonster] Missing status per level speed. " << file << std::endl;
  931. +       }
  932. +   }
  933.  
  934.     if ((node = monsterNode.child("attacks"))) {
  935.         for (auto attackNode : node.children()) {
  936. diff --git a/forgottenserver-1.2/src/monsters.h b/forgottenserver-1.2/src/monsters.h
  937. index e5e2731..43357cf 100644
  938. --- a/forgottenserver-1.2/src/monsters.h
  939. +++ b/forgottenserver-1.2/src/monsters.h
  940. @@ -88,6 +88,11 @@ struct voiceBlock_t {
  941.     bool yellText;
  942.  };
  943.  
  944. +struct spawnLevel_t {
  945. +   uint32_t min = 1;
  946. +   uint32_t max = 1;
  947. +};
  948. +
  949.  class MonsterType
  950.  {
  951.     struct MonsterInfo {
  952. @@ -107,6 +112,11 @@ class MonsterType
  953.         Outfit_t outfit = {};
  954.         RaceType_t race = RACE_BLOOD;
  955.  
  956. +       spawnLevel_t spawnLevel;
  957. +
  958. +       PokemonStatus baseStatus;
  959. +       PokemonStatus statusPerLevel;
  960. +
  961.         LightInfo light = {};
  962.         uint16_t lookcorpse = 0;
  963.  
  964. --
  965. 2.7.4.1.g5468f9e
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement