Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 4b9c27ae90ec635d55b48a27a5b9f1a7bf618070 Mon Sep 17 00:00:00 2001
- From: eduardovicente <dudugt500@gmail.com>
- Date: Sat, 23 Sep 2017 12:38:28 -0300
- Subject: [PATCH] Monster System 1.0, Monster Level System.
- ---
- .../data/actions/scripts/tools/pokeball.lua | 32 ++--
- forgottenserver-1.2/data/events/events.xml | 3 +
- .../data/events/scripts/monster.lua | 15 ++
- forgottenserver-1.2/data/events/scripts/player.lua | 108 ++++++------
- .../data/monster/Amazons/amazon.xml | 12 +-
- .../data/monster/Serpents/sea_serpent.xml | 5 +
- forgottenserver-1.2/src/enums.h | 32 +++-
- forgottenserver-1.2/src/events.cpp | 75 +++++++++
- forgottenserver-1.2/src/events.h | 7 +
- forgottenserver-1.2/src/luascript.cpp | 89 ++++++++++
- forgottenserver-1.2/src/luascript.h | 7 +
- forgottenserver-1.2/src/monster.cpp | 182 +++++++++++++++++++++
- forgottenserver-1.2/src/monster.h | 33 +++-
- forgottenserver-1.2/src/monsters.cpp | 92 +++++++++++
- forgottenserver-1.2/src/monsters.h | 10 ++
- 15 files changed, 619 insertions(+), 83 deletions(-)
- create mode 100644 forgottenserver-1.2/data/events/scripts/monster.lua
- diff --git a/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua b/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua
- index de6d6f2..328e78f 100644
- --- a/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua
- +++ b/forgottenserver-1.2/data/actions/scripts/tools/pokeball.lua
- @@ -1,28 +1,20 @@
- -function table.dump(t, depth)
- - if not depth then depth = 0 end
- - for k,v in pairs(t) do
- - str = (' '):rep(depth * 2) .. k .. ': '
- - if type(v) ~= "table" then
- - print(str .. tostring(v))
- - else
- - print(str)
- - table.dump(v, depth+1)
- - end
- - end
- -end
- + function onUse(player, pokeball, fromPosition, target, toPosition, isHotkey)
- + if (#player:getSummons() > 0) then
- + local pokemon = player:getSummons()[1]
- + pokeball:setPokemonName(pokemon:getName())
- + pokeball:setLevel(pokemon:getLevel())
- + pokeball:setExperience(pokemon:getExperience())
- + pokeball:setMaxHealth(pokemon:getMaxHealth())
- + pokeball:setHealth(pokemon:getHealth())
- -function onUse(player, pokeball, fromPosition, target, toPosition, isHotkey)
- - local nameList = {"Amazon", "Troll", "Orc", "Fire Devil", "Dragon", "Frost Dragon"}
- -
- - if (pokeball:getPokemonName() == "") then
- - pokeball:setPokemonName(nameList[math.random(1, 6)])
- - pokeball:setLevel(math.random(1,100))
- - pokeball:setMaxHealth(100 * pokeball:getLevel())
- - pokeball:setHealth(pokeball:getMaxHealth())
- + pokemon:remove()
- else
- local pokemon = Game.createMonster(pokeball:getPokemonName(), player:getPosition())
- pokemon:setMaster(player)
- + pokemon:setLevel(pokeball:getLevel())
- + pokemon:setExperience(pokeball:getExperience())
- +
- pokemon:setMaxHealth(pokeball:getMaxHealth())
- local currentHealth = -(pokemon:getHealth() - 1)
- pokemon:addHealth(currentHealth)
- diff --git a/forgottenserver-1.2/data/events/events.xml b/forgottenserver-1.2/data/events/events.xml
- index 77ba759..4e4af11 100644
- --- a/forgottenserver-1.2/data/events/events.xml
- +++ b/forgottenserver-1.2/data/events/events.xml
- @@ -24,4 +24,7 @@
- <event class="Player" method="onGainExperience" enabled="1" />
- <event class="Player" method="onLoseExperience" enabled="0" />
- <event class="Player" method="onGainSkillTries" enabled="1" />
- +
- + <event class="Monster" method="onDeath" enabled="1" />
- + <event class="Monster" method="onGainExperience" enabled="1" />
- </events>
- diff --git a/forgottenserver-1.2/data/events/scripts/monster.lua b/forgottenserver-1.2/data/events/scripts/monster.lua
- new file mode 100644
- index 0000000..0117f6c
- --- /dev/null
- +++ b/forgottenserver-1.2/data/events/scripts/monster.lua
- @@ -0,0 +1,15 @@
- +function Monster:onDeath()
- + local player = self:getMaster()
- + player:sendTextMessage(MESSAGE_INFO_DESCR, "Your pokemon fainted!")
- + return true
- +end
- +
- +function Monster:onGainExperience(source, exp, rawExp)
- + if not source or source:isPlayer() then
- + return exp
- + end
- +
- + -- Apply experience stage multiplier
- + --exp = exp * Game.getExperienceStage(self:getLevel())
- + return exp
- +end
- \ No newline at end of file
- diff --git a/forgottenserver-1.2/data/events/scripts/player.lua b/forgottenserver-1.2/data/events/scripts/player.lua
- index 40d1694..ff3bf3d 100644
- --- a/forgottenserver-1.2/data/events/scripts/player.lua
- +++ b/forgottenserver-1.2/data/events/scripts/player.lua
- @@ -3,63 +3,69 @@ function Player:onBrowseField(position)
- end
- function Player:onLook(thing, position, distance)
- - local description = ""
- -
- - if thing:isPokeball() then
- - description = "You see an ".. thing:getPokemonName()
- - description = description.. ", Level: ".. thing:getLevel().. ", [Hp: ".. thing:getHealth().. " / Max.Hp: ".. thing:getMaxHealth().. "]."
- - else
- - description = "You see " .. thing:getDescription(distance)
- - if self:getGroup():getAccess() then
- - if thing:isItem() then
- - description = string.format("%s\nItem ID: %d", description, thing:getId())
- -
- - local actionId = thing:getActionId()
- - if actionId ~= 0 then
- - description = string.format("%s, Action ID: %d", description, actionId)
- - end
- -
- - local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
- - if uniqueId > 0 and uniqueId < 65536 then
- - description = string.format("%s, Unique ID: %d", description, uniqueId)
- - end
- -
- - local itemType = thing:getType()
- -
- - local transformEquipId = itemType:getTransformEquipId()
- - local transformDeEquipId = itemType:getTransformDeEquipId()
- - if transformEquipId ~= 0 then
- - description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
- - elseif transformDeEquipId ~= 0 then
- - description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
- - end
- -
- - local decayId = itemType:getDecayId()
- - if decayId ~= -1 then
- - description = string.format("%s\nDecays to: %d", description, decayId)
- - end
- - elseif thing:isCreature() then
- - local str = "%s\nHealth: %d / %d"
- - if thing:getMaxMana() > 0 then
- - str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
- - end
- - description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
- + local description = "You see " .. thing:getDescription(distance)
- + if self:getGroup():getAccess() then
- + if thing:isItem() then
- + if thing:isPokeball() then
- + description = "You see an ".. thing:getPokemonName()
- + description = description.. ", Level: ".. thing:getLevel().. ", [Hp: ".. thing:getHealth().. " / Max.Hp: ".. thing:getMaxHealth().. "]."
- + end
- + description = string.format("%s\nItem ID: %d", description, thing:getId())
- +
- + local actionId = thing:getActionId()
- + if actionId ~= 0 then
- + description = string.format("%s, Action ID: %d", description, actionId)
- + end
- +
- + local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID)
- + if uniqueId > 0 and uniqueId < 65536 then
- + description = string.format("%s, Unique ID: %d", description, uniqueId)
- end
- - local position = thing:getPosition()
- - description = string.format(
- - "%s\nPosition: %d, %d, %d",
- - description, position.x, position.y, position.z
- - )
- + local itemType = thing:getType()
- +
- + local transformEquipId = itemType:getTransformEquipId()
- + local transformDeEquipId = itemType:getTransformDeEquipId()
- + if transformEquipId ~= 0 then
- + description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId)
- + elseif transformDeEquipId ~= 0 then
- + description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId)
- + end
- - if thing:isCreature() then
- - if thing:isPlayer() then
- - description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
- - end
- + local decayId = itemType:getDecayId()
- + if decayId ~= -1 then
- + description = string.format("%s\nDecays to: %d", description, decayId)
- + end
- + elseif thing:isCreature() then
- + if thing:isMonster() then
- + local level = thing:getLevel()
- + local currentExp = thing:getExperience()
- + local expForNextLevel = thing:getExpForLevel(level + 1) - currentExp
- +
- + description = description.. "\nLevel: ".. level
- + description = description.. "\nExp: ".. thing:getExperience()
- + description = description.. " / Exp for next level: ".. expForNextLevel
- + end
- +
- + local str = "%s\nHealth: %d / %d"
- + if thing:getMaxMana() > 0 then
- + str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana())
- end
- + description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "."
- end
- - end
- + local position = thing:getPosition()
- + description = string.format(
- + "%s\nPosition: %d, %d, %d",
- + description, position.x, position.y, position.z
- + )
- +
- + if thing:isCreature() then
- + if thing:isPlayer() then
- + description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp()))
- + end
- + end
- + end
- self:sendTextMessage(MESSAGE_INFO_DESCR, description)
- end
- diff --git a/forgottenserver-1.2/data/monster/Amazons/amazon.xml b/forgottenserver-1.2/data/monster/Amazons/amazon.xml
- index d2d5490..3e08f61 100644
- --- a/forgottenserver-1.2/data/monster/Amazons/amazon.xml
- +++ b/forgottenserver-1.2/data/monster/Amazons/amazon.xml
- @@ -2,7 +2,11 @@
- <monster name="Amazon" nameDescription="an amazon" race="blood" experience="60" speed="180" manacost="390">
- <health now="110" max="110" />
- <look type="137" head="113" body="120" legs="114" feet="132" corpse="20323" />
- - <targetchange interval="4000" chance="10" />
- +
- + <level min="10" max="10" />
- + <basestatus hp="150" attack="50" defense="20" specialattack="10" specialdefense="10" speed="25" />
- + <statusperlevel hp="2" attack="5" defense="1" specialattack="1.5" specialdefense="0.5" speed="3" />
- +
- <flags>
- <flag summonable="1" />
- <flag attackable="1" />
- @@ -16,9 +20,11 @@
- <flag staticattack="90" />
- <flag runonhealth="10" />
- </flags>
- +
- + <targetchange interval="1000" chance="0" />
- <attacks>
- - <attack name="melee" interval="2000" min="0" max="-45" />
- - <attack name="physical" interval="2000" chance="15" range="7" min="0" max="-40">
- + <attack name="melee" interval="2000" min="-0" max="-45" />
- + <attack name="physical" interval="2000" chance="80" range="7" min="-0" max="-40">
- <attribute key="shootEffect" value="throwingknife" />
- </attack>
- </attacks>
- diff --git a/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml b/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml
- index dc77198..e60fdca 100644
- --- a/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml
- +++ b/forgottenserver-1.2/data/monster/Serpents/sea_serpent.xml
- @@ -2,6 +2,11 @@
- <monster name="Sea Serpent" nameDescription="a sea serpent" race="blood" experience="2300" speed="350" manacost="390">
- <health now="1950" max="1950" />
- <look type="275" corpse="8307" />
- +
- + <level min="50" max="75" />
- + <basestatus hp="150" attack="50" defense="30" specialattack="25" specialdefense="10" speed="55" />
- + <statusperlevel hp="5" attack="10" defense="3" specialattack="25.5" specialdefense="5.5" speed="10" />
- +
- <targetchange interval="4000" chance="10" />
- <flags>
- <flag summonable="0" />
- diff --git a/forgottenserver-1.2/src/enums.h b/forgottenserver-1.2/src/enums.h
- index f927825..8b459f6 100644
- --- a/forgottenserver-1.2/src/enums.h
- +++ b/forgottenserver-1.2/src/enums.h
- @@ -548,12 +548,32 @@ struct CombatDamage
- struct PokemonStatus
- {
- - double attack = 0;
- - double defense = 0;
- - double hp = 0;
- - double specialAttack = 0;
- - double specialDefense = 0;
- - double speed = 0;
- + void multiplier(int multiplier)
- + {
- + attack *= multiplier;
- + defense *= multiplier;
- + hp *= multiplier;
- + specialAttack *= multiplier;
- + specialDefense *= multiplier;
- + speed *= multiplier;
- + }
- +
- + void addition(int addition)
- + {
- + attack += addition;
- + defense += addition;
- + hp += addition;
- + specialAttack += addition;
- + specialDefense += addition;
- + speed += addition;
- + }
- +
- + double attack = 1;
- + double defense = 1;
- + double hp = 1;
- + double specialAttack = 1;
- + double specialDefense = 1;
- + double speed = 1;
- };
- typedef std::list<MarketOffer> MarketOfferList;
- diff --git a/forgottenserver-1.2/src/events.cpp b/forgottenserver-1.2/src/events.cpp
- index b1a3758..c986fe9 100644
- --- a/forgottenserver-1.2/src/events.cpp
- +++ b/forgottenserver-1.2/src/events.cpp
- @@ -111,6 +111,14 @@ bool Events::load()
- } else {
- std::cout << "[Warning - Events::load] Unknown player method: " << methodName << std::endl;
- }
- + } else if (className == "Monster") {
- + if (methodName == "onDeath") {
- + info.monsterOnDeath = event;
- + } else if (methodName == "onGainExperience") {
- + info.monsterOnGainExperience = event;
- + } else {
- + std::cout << "[Warning - Events::load] Unknown monster method: " << methodName << std::endl;
- + }
- } else {
- std::cout << "[Warning - Events::load] Unknown class: " << className << std::endl;
- }
- @@ -723,3 +731,70 @@ void Events::eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_
- scriptInterface.resetScriptEnv();
- }
- +
- +void Events::eventMonsterOnDeath(Monster* monster) {
- + // Monster:onDeath(monster)
- + if (info.monsterOnDeath == -1) {
- + return;
- + }
- +
- + if (!scriptInterface.reserveScriptEnv()) {
- + std::cout << "[Error - Events::eventMonsterOnDeath] Call stack overflow" << std::endl;
- + return;
- + }
- +
- + ScriptEnvironment* env = scriptInterface.getScriptEnv();
- + env->setScriptId(info.monsterOnDeath, &scriptInterface);
- +
- + lua_State* L = scriptInterface.getLuaState();
- + scriptInterface.pushFunction(info.monsterOnDeath);
- +
- + LuaScriptInterface::pushUserdata<Monster>(L, monster);
- + LuaScriptInterface::setMetatable(L, -1, "Monster");
- +
- + scriptInterface.callVoidFunction(1);
- +}
- +
- +void Events::eventMonsterOnGainExperience(Monster* monster, Creature* source, uint64_t& exp, uint64_t rawExp)
- +{
- + // Monster:onGainExperience(source, exp, rawExp)
- + // rawExp gives the original exp which is not multiplied
- + if (info.monsterOnGainExperience == -1) {
- + return;
- + }
- +
- + if (!scriptInterface.reserveScriptEnv()) {
- + std::cout << "[Error - Events::eventPlayerOnGainExperience] Call stack overflow" << std::endl;
- + return;
- + }
- +
- + ScriptEnvironment* env = scriptInterface.getScriptEnv();
- + env->setScriptId(info.monsterOnGainExperience, &scriptInterface);
- +
- + lua_State* L = scriptInterface.getLuaState();
- + scriptInterface.pushFunction(info.monsterOnGainExperience);
- +
- + LuaScriptInterface::pushUserdata<Monster>(L, monster);
- + LuaScriptInterface::setMetatable(L, -1, "Monster");
- +
- + if (source) {
- + LuaScriptInterface::pushUserdata<Creature>(L, source);
- + LuaScriptInterface::setCreatureMetatable(L, -1, source);
- + }
- + else {
- + lua_pushnil(L);
- + }
- +
- + lua_pushnumber(L, exp);
- + lua_pushnumber(L, rawExp);
- +
- + if (scriptInterface.protectedCall(L, 4, 1) != 0) {
- + LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L));
- + }
- + else {
- + exp = LuaScriptInterface::getNumber<uint64_t>(L, -1);
- + lua_pop(L, 1);
- + }
- +
- + scriptInterface.resetScriptEnv();
- +}
- \ No newline at end of file
- diff --git a/forgottenserver-1.2/src/events.h b/forgottenserver-1.2/src/events.h
- index 03a58cc..ef22bb3 100644
- --- a/forgottenserver-1.2/src/events.h
- +++ b/forgottenserver-1.2/src/events.h
- @@ -53,6 +53,10 @@ class Events
- int32_t playerOnGainExperience = -1;
- int32_t playerOnLoseExperience = -1;
- int32_t playerOnGainSkillTries = -1;
- +
- + // Pokemon
- + int32_t monsterOnDeath = -1;
- + int32_t monsterOnGainExperience = -1;
- };
- public:
- @@ -85,6 +89,9 @@ class Events
- void eventPlayerOnLoseExperience(Player* player, uint64_t& exp);
- void eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_t& tries);
- + // Pokemon
- + void eventMonsterOnDeath(Monster* monster);
- + void eventMonsterOnGainExperience(Monster* monster, Creature* source, uint64_t& exp, uint64_t rawExp);
- private:
- LuaScriptInterface scriptInterface;
- EventsInfo info;
- diff --git a/forgottenserver-1.2/src/luascript.cpp b/forgottenserver-1.2/src/luascript.cpp
- index 6c975d6..ea3556e 100644
- --- a/forgottenserver-1.2/src/luascript.cpp
- +++ b/forgottenserver-1.2/src/luascript.cpp
- @@ -2306,6 +2306,14 @@ void LuaScriptInterface::registerFunctions()
- registerMethod("Monster", "selectTarget", LuaScriptInterface::luaMonsterSelectTarget);
- registerMethod("Monster", "searchTarget", LuaScriptInterface::luaMonsterSearchTarget);
- + registerMethod("Monster", "getLevel", LuaScriptInterface::luaMonsterGetLevel);
- + registerMethod("Monster", "setLevel", LuaScriptInterface::luaMonsterSetLevel);
- +
- + registerMethod("Monster", "getExperience", LuaScriptInterface::luaMonsterGetExperience);
- + registerMethod("Monster", "setExperience", LuaScriptInterface::luaMonsterSetExperience);
- + registerMethod("Monster", "addExperience", LuaScriptInterface::luaMonsterAddExperience);
- + registerMethod("Monster", "getExpForLevel", LuaScriptInterface::luaMonsterGetExpForLevel);
- +
- // Npc
- registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate);
- registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare);
- @@ -9759,6 +9767,87 @@ int LuaScriptInterface::luaMonsterSearchTarget(lua_State* L)
- return 1;
- }
- +int LuaScriptInterface::luaMonsterGetLevel(lua_State* L)
- +{
- + // monster:getLevel()
- + Monster* monster = getUserdata<Monster>(L, 1);
- + if (monster) {
- + lua_pushnumber(L, monster->getLevel());
- + }
- + else {
- + lua_pushnumber(L, 0);
- + }
- +
- + return 1;
- +}
- +
- +int LuaScriptInterface::luaMonsterSetLevel(lua_State *L)
- +{
- + // monster:setLevel(level)
- + Monster* monster = getUserdata<Monster>(L, 1);
- + if (monster) {
- + uint32_t level = getNumber<uint32_t>(L, 2);
- + monster->setLevel(level);
- + pushBoolean(L, true);
- + }
- +
- + return 1;
- +}
- +
- +int LuaScriptInterface::luaMonsterGetExperience(lua_State* L)
- +{
- + // monster:getExperience()
- + Monster* monster = getUserdata<Monster>(L, 1);
- + if (monster) {
- + lua_pushnumber(L, monster->getExperience());
- + }
- + else {
- + lua_pushnumber(L, 0);
- + }
- +
- + return 1;
- +}
- +
- +int LuaScriptInterface::luaMonsterSetExperience(lua_State* L)
- +{
- + // monster:setExperience(exp)
- + Monster* monster = getUserdata<Monster>(L, 1);
- + if (monster) {
- + uint64_t exp = getNumber<uint64_t>(L, 2);
- + monster->setExperience(exp);
- + }
- + return 1;
- +}
- +
- +int LuaScriptInterface::luaMonsterAddExperience(lua_State* L)
- +{
- + // monster:addExperience(experience[, sendText = false])
- + Monster* monster = getUserdata<Monster>(L, 1);
- + if (monster) {
- + int64_t experience = getNumber<int64_t>(L, 2);
- + bool sendText = getBoolean(L, 3, false);
- + monster->addExperience(nullptr, experience, sendText);
- + pushBoolean(L, true);
- + }
- +
- + return 1;
- +}
- +
- +int LuaScriptInterface::luaMonsterGetExpForLevel(lua_State* L)
- +{
- + // monster:getExpForLevel(level)
- + Monster* monster = getUserdata<Monster>(L, 1);
- + if (monster) {
- + uint32_t level = getNumber<uint32_t>(L, 2);
- + lua_pushnumber(L, monster->getExpForLevel(level));
- + }
- + else {
- + lua_pushnumber(L, 0);
- + }
- +
- + return 1;
- +}
- +
- // Npc
- int LuaScriptInterface::luaNpcCreate(lua_State* L)
- {
- diff --git a/forgottenserver-1.2/src/luascript.h b/forgottenserver-1.2/src/luascript.h
- index 6b3e933..d228a0e 100644
- --- a/forgottenserver-1.2/src/luascript.h
- +++ b/forgottenserver-1.2/src/luascript.h
- @@ -1010,6 +1010,13 @@ class LuaScriptInterface
- static int luaMonsterSelectTarget(lua_State* L);
- static int luaMonsterSearchTarget(lua_State* L);
- + static int luaMonsterGetLevel(lua_State* L);
- + static int luaMonsterSetLevel(lua_State* L);
- + static int luaMonsterGetExperience(lua_State* L);
- + static int luaMonsterSetExperience(lua_State* L);
- + static int luaMonsterAddExperience(lua_State* L);
- + static int luaMonsterGetExpForLevel(lua_State* L);
- +
- // Npc
- static int luaNpcCreate(lua_State* L);
- diff --git a/forgottenserver-1.2/src/monster.cpp b/forgottenserver-1.2/src/monster.cpp
- index ac0ac12..f9d722b 100644
- --- a/forgottenserver-1.2/src/monster.cpp
- +++ b/forgottenserver-1.2/src/monster.cpp
- @@ -22,9 +22,13 @@
- #include "monster.h"
- #include "game.h"
- #include "spells.h"
- +#include "events.h"
- +#include "configmanager.h"
- +extern ConfigManager g_config;
- extern Game g_game;
- extern Monsters g_monsters;
- +extern Events* g_events;
- int32_t Monster::despawnRange;
- int32_t Monster::despawnRadius;
- @@ -45,6 +49,14 @@ Monster::Monster(MonsterType* mtype) :
- strDescription(asLowerCaseString(mtype->nameDescription)),
- mType(mtype)
- {
- +
- + uint32_t levelCalc = mType->info.spawnLevel.max - mType->info.spawnLevel.min;
- + level = (rand() % (levelCalc > 0 ? levelCalc : 1)) + mType->info.spawnLevel.min;
- + experience = getExpForLevel(level);
- +
- + status = mType->info.statusPerLevel;
- + status.multiplier(level);
- +
- defaultOutfit = mType->info.outfit;
- currentOutfit = mType->info.outfit;
- skull = mType->info.skull;
- @@ -60,6 +72,8 @@ Monster::Monster(MonsterType* mtype) :
- std::cout << "[Warning - Monster::Monster] Unknown event name: " << scriptName << std::endl;
- }
- }
- +
- + updateBaseStatus();
- }
- Monster::~Monster()
- @@ -2002,3 +2016,171 @@ void Monster::getPathSearchParams(const Creature* creature, FindPathParams& fpp)
- fpp.fullPathSearch = !canUseAttack(getPosition(), creature);
- }
- }
- +
- +uint64_t Monster::getExperience() {
- + return experience;
- +}
- +
- +void Monster::setExperience(uint64_t exp) {
- + experience = exp;
- +}
- +
- +uint64_t Monster::getExpForLevel(int32_t lv) {
- + lv--;
- + return ((50ULL * lv * lv * lv) - (150ULL * lv * lv) + (400ULL * lv)) / 3ULL;
- +}
- +
- +uint8_t Monster::getPercentLevel(uint64_t count, uint64_t nextLevelCount) {
- + if (nextLevelCount == 0)
- + return 0;
- +
- + uint8_t result = (count * 100) / nextLevelCount;
- + if (result > 100)
- + return 0;
- +
- + return result;
- +}
- +
- +void Monster::addExperience(Creature* source, uint64_t exp, bool sendText) {
- +
- + uint64_t currLevelExp = getExpForLevel(level);
- + uint64_t nextLevelExp = getExpForLevel(level + 1);
- + uint64_t rawExp = exp;
- + if (currLevelExp >= nextLevelExp) {
- + //monster has reached max level
- + levelPercent = 0;
- + return;
- + }
- +
- + Player* master = nullptr;
- + if (getMaster()) {
- + master = getMaster()->getPlayer();
- + }
- +
- + if (master) {
- + g_events->eventMonsterOnGainExperience(this, source, exp, rawExp);
- + if (exp == 0) {
- + return;
- + }
- + }
- +
- + experience += exp;
- +
- + if (master && sendText) {
- + std::string expString = std::to_string(exp) + (exp != 1 ? " experience points." : " experience point.");
- +
- + TextMessage message(MESSAGE_EXPERIENCE, "Your pokemon gained " + expString);
- + message.position = position;
- + message.primary.value = exp;
- + message.primary.color = TEXTCOLOR_WHITE_EXP;
- + master->sendTextMessage(message);
- + }
- +
- + uint32_t prevLevel = level;
- + while (experience >= nextLevelExp) {
- + ++level;
- +
- + onAdvancedLevel();
- +
- + currLevelExp = nextLevelExp;
- + nextLevelExp = getExpForLevel(level + 1);
- + if (currLevelExp >= nextLevelExp) {
- + //player has reached max level
- + break;
- + }
- + }
- +
- + if (prevLevel != level) {
- + health = healthMax;
- +
- + setBaseSpeed(getBaseSpeed());
- + g_game.changeSpeed(this, 0);
- + g_game.addCreatureHealth(this);
- +
- + if (master != nullptr && sendText) {
- + std::ostringstream ss;
- + ss << "Your pokemon advanced from Level " << prevLevel << " to Level " << level << '.';
- + master->sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str());
- + }
- + }
- +
- + if (nextLevelExp > currLevelExp)
- + levelPercent = getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp);
- + else
- + levelPercent = 0;
- +}
- +
- +void Monster::onGainExperience(uint64_t gainExp, Creature* target)
- +{
- + if (gainExp == 0)
- + return;
- +
- + if (master)
- + master->onGainExperience(gainExp, target);
- +
- + gainExperience(target, gainExp);
- +}
- +
- +void Monster::gainExperience(Creature* source, uint64_t gainExp) {
- + if (gainExp == 0)
- + return;
- +
- + addExperience(source, gainExp, true);
- +}
- +
- +uint64_t Monster::getGainedExperience(Creature* attacker) const
- +{
- + Monster* attackerMonster = attacker->getMonster();
- + if (attackerMonster && attackerMonster != this) {
- +
- + uint64_t expLost = 0;
- + if (getLevel() <= 1)
- + expLost = mType->info.experience;
- + else
- + expLost = getLostExperience();
- +
- + return std::max<uint64_t>(0, std::floor(expLost * getDamageRatio(attacker) * 0.75));
- + }
- +
- + return 0;
- +}
- +
- +double Monster::getLostPercent() const
- +{
- + int32_t deathLosePercent = g_config.getNumber(ConfigManager::DEATH_LOSE_PERCENT);
- + if (deathLosePercent != -1)
- + return std::max<int32_t>(0, deathLosePercent) / 100.;
- +
- + double lossPercent;
- + if (level >= 25) {
- + double tmpLevel = level + (levelPercent / 100.);
- + lossPercent = static_cast<double>((tmpLevel + 50) * 50 * ((tmpLevel * tmpLevel) - (5 * tmpLevel) + 8)) / experience;
- + } else
- + lossPercent = 10;
- +
- + return lossPercent * pow(0.92, 0) / 100;
- +}
- +
- +const uint32_t Monster::getLevel() const
- +{
- + return level;
- +}
- +
- +void Monster::setLevel(uint32_t lvl)
- +{
- + level = lvl;
- +}
- +
- +void Monster::onAdvancedLevel()
- +{
- + status = mType->info.statusPerLevel;
- + status.addition(1);
- +
- + updateBaseStatus();
- +}
- +
- +void Monster::updateBaseStatus()
- +{
- + healthMax = mType->info.baseStatus.hp * status.hp;
- + health = healthMax;
- +}
- \ No newline at end of file
- diff --git a/forgottenserver-1.2/src/monster.h b/forgottenserver-1.2/src/monster.h
- index c699965..4d8f7ee 100644
- --- a/forgottenserver-1.2/src/monster.h
- +++ b/forgottenserver-1.2/src/monster.h
- @@ -173,6 +173,29 @@ class Monster final : public Creature
- BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
- bool checkDefense = false, bool checkArmor = false, bool field = false);
- + uint64_t getExperience();
- + void setExperience(uint64_t exp);
- +
- + static uint64_t getExpForLevel(int32_t lv);
- + static uint8_t getPercentLevel(uint64_t count, uint64_t nextLevelCount);
- +
- + void addExperience(Creature* source, uint64_t exp, bool sendText = false);
- + void gainExperience(Creature* source, uint64_t gainExp);
- + void onGainExperience(uint64_t gainExp, Creature* target) final;
- +
- + uint64_t getGainedExperience(Creature* attacker) const final;
- + double getLostPercent() const;
- + uint64_t getLostExperience() const final {
- +
- + return skillLoss ? static_cast<uint64_t>(experience * getLostPercent()) : 0;
- + }
- +
- + const uint32_t getLevel() const;
- + void setLevel(uint32_t lvl);
- + void onAdvancedLevel();
- +
- + void updateBaseStatus();
- +
- static uint32_t monsterAutoID;
- private:
- @@ -184,6 +207,13 @@ class Monster final : public Creature
- MonsterType* mType;
- Spawn* spawn = nullptr;
- + uint32_t level = 1;
- + uint8_t levelPercent = 0;
- +
- + uint64_t experience = 0;
- +
- + PokemonStatus status;
- +
- int64_t lastMeleeAttack = 0;
- uint32_t attackTicks = 0;
- @@ -251,9 +281,6 @@ class Monster final : public Creature
- bool isFriend(const Creature* creature) const;
- bool isOpponent(const Creature* creature) const;
- - uint64_t getLostExperience() const final {
- - return skillLoss ? mType->info.experience : 0;
- - }
- uint16_t getLookCorpse() const final {
- return mType->info.lookcorpse;
- }
- diff --git a/forgottenserver-1.2/src/monsters.cpp b/forgottenserver-1.2/src/monsters.cpp
- index caa1aee..aa28f81 100644
- --- a/forgottenserver-1.2/src/monsters.cpp
- +++ b/forgottenserver-1.2/src/monsters.cpp
- @@ -824,6 +824,98 @@ bool Monsters::loadMonster(const std::string& file, const std::string& monsterNa
- mType->info.lookcorpse = pugi::cast<uint16_t>(attr.value());
- }
- }
- +
- + if ((node = monsterNode.child("level"))) {
- + if ((attr = node.attribute("min"))) {
- + mType->info.spawnLevel.min = pugi::cast<uint32_t>(attr.value());
- + }
- + else {
- + std::cout << "[Error - Monsters::loadMonster] Missing spawn level min. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("max"))) {
- + mType->info.spawnLevel.max = pugi::cast<uint32_t>(attr.value());
- + }
- + else {
- + std::cout << "[Error - Monsters::loadMonster] Missing spawn level max. " << file << std::endl;
- + }
- + }
- +
- + if ((node = monsterNode.child("basestatus"))) {
- + if ((attr = node.attribute("hp"))) {
- + mType->info.baseStatus.hp = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing base status health. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("attack"))) {
- + mType->info.baseStatus.attack = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing base status attack. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("defense"))) {
- + mType->info.baseStatus.defense = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing base status defense. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("specialattack"))) {
- + mType->info.baseStatus.specialAttack = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing base status special attack. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("specialdefense"))) {
- + mType->info.baseStatus.specialDefense = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing base status special defense. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("speed"))) {
- + mType->info.baseStatus.speed = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status speed. " << file << std::endl;
- + }
- + }
- +
- + if ((node = monsterNode.child("statusperlevel"))) {
- + if ((attr = node.attribute("hp"))) {
- + mType->info.statusPerLevel.hp = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status per level health. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("attack"))) {
- + mType->info.statusPerLevel.attack = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status per level attack. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("defense"))) {
- + mType->info.statusPerLevel.defense = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status per level defense. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("specialattack"))) {
- + mType->info.statusPerLevel.specialAttack = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status per level special attack. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("specialdefense"))) {
- + mType->info.statusPerLevel.specialDefense = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status per level special defense. " << file << std::endl;
- + }
- +
- + if ((attr = node.attribute("speed"))) {
- + mType->info.statusPerLevel.speed = pugi::cast<double>(attr.value());
- + } else {
- + std::cout << "[Error - Monsters::loadMonster] Missing status per level speed. " << file << std::endl;
- + }
- + }
- if ((node = monsterNode.child("attacks"))) {
- for (auto attackNode : node.children()) {
- diff --git a/forgottenserver-1.2/src/monsters.h b/forgottenserver-1.2/src/monsters.h
- index e5e2731..43357cf 100644
- --- a/forgottenserver-1.2/src/monsters.h
- +++ b/forgottenserver-1.2/src/monsters.h
- @@ -88,6 +88,11 @@ struct voiceBlock_t {
- bool yellText;
- };
- +struct spawnLevel_t {
- + uint32_t min = 1;
- + uint32_t max = 1;
- +};
- +
- class MonsterType
- {
- struct MonsterInfo {
- @@ -107,6 +112,11 @@ class MonsterType
- Outfit_t outfit = {};
- RaceType_t race = RACE_BLOOD;
- + spawnLevel_t spawnLevel;
- +
- + PokemonStatus baseStatus;
- + PokemonStatus statusPerLevel;
- +
- LightInfo light = {};
- uint16_t lookcorpse = 0;
- --
- 2.7.4.1.g5468f9e
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement