• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

OOP Classes for older TFS versions (0.3.x / 0.4x / ...)

Evil Hero

Legacy Member
TFS Developer
Joined
Dec 12, 2007
Messages
1,254
Solutions
27
Reaction score
721
Location
Germany
I've wrote this little lib for compatibility to the new oop way we approached at 1.x
This makes it so that 1.x scripts are working for older versions aswell

It's just a beginning, I'd like everyone to contribute to it, it's quite a pain in the ass to recall all functions.
Code:
Creature = {}
Player = {}
Monster = {}
Npc = {}
Game = {}
Condition = {}
Combat = {}

function createClass(class, inheritance)
   setmetatable(class, {
   __index = inheritance and inheritance or nil,
   __call =
   function(self, cid)
     if not cid then
       self = {__index = class}
       setmetatable(self, self)
       return self
     end
     local cid = type(cid) == "number" and cid or type(cid) == "string" and getPlayerByNameWildcard(cid)
     if cid then
       if not self[cid] then
         self[cid] = {__index = class}
         setmetatable(self[cid], self[cid])
         self[cid].cid = cid
         return self[cid]
       else
         return self[cid]
       end
     else
       return nil
     end
   end
   })
end

createClass(Creature)
createClass(Player, Creature)
createClass(Monster, Creature)
createClass(Npc, Creature)
createClass(Game)
createClass(Condition)
createClass(Combat)

-- access metatable functions from creature
function Creature:getPlayer() return Player(self.cid) end
function Creature:getMonster() return Monster(self.cid) end
function Creature:getNpc() return Npc(self.cid) end

-- Creature
-- Creature get functions
function Creature:getId() return self.cid end
function Creature:getName() return getCreatureName(self.cid) end
function Creature:getHealth() return getCreatureHealth(self.cid) end
function Creature:getMaxHealth() return getCreatureMaxHealth(self.cid) end
function Creature:getMana() return getCreatureMana(self.cid) end
function Creature:getMaxMana() return getCreatureMaxMana(self.cid) end
function Creature:getStorageValue(id) return getCreatureStorageValue(self.cid, id) end
function Creature:getHiddenHealth() return getCreatureHideHealth(self.cid) end
function Creature:getSpeakType() return getCreatureSpeakType(self.cid) end
function Creature:getLookDirection() return getCreatureLookDirection(self.cid) end

-- Creature set functions
function Creature:setMaxHealth(health) return setCreatureMaxHealth(self.cid, health) end
function Creature:setMaxMana(mana) return setCreatureMaxMana(self.cid, mana) end
function Creature:setStorageValue(storage, value) return setCreatureStorageValue(self.cid, storage, value) end
function Creature:setHiddenHealth(hide) doCreatureSetHideHealth(self.cid, hide) end
function Creature:setSpeakType(type) doCreatureSetSpeakType(self.cid, type) end

-- Creature misc. functions
function Creature:teleportTo(newpos, pushmove) doTeleportThing(self.cid, newpos, pushmove or false) end
function Creature:addHealth(health, hitEffect, hitColor, force) doCreatureAddHealth(self.cid, health, hitEffect, hitColor, force) end
function Creature:addMana(mana) doCreatureAddMana(self.cid, mana) end
function Creature:say(text, type, ghost, cid, pos) doCreatureSay(self.cid, text, type or SPEAK_SAY, ghost or false, cid or 0, pos) end
function Creature:addCondition(condition) doAddCondition(self.cid, condition) end
function Creature:removeCondition(onlyPersistent, type, subId) if onlyPersistent then doRemoveConditions(self.cid, onlyPersistent) else doRemoveCondition(self.cid, type, subId) end end
function Creature:moveCreature(direction) doMoveCreature(self.cid, direction) end
function Creature:isCreature() return isCreature(self.cid) end
function Creature:isPlayer() return isPlayer(self.cid) end
function Creature:isMonster() return isMonster(self.cid) end
function Creature:isNpc() return isNpc(self.cid) end
function Creature:remove(forceLogout) doRemoveCreature(self.cid, forceLogout or true) end

-- Player
-- Player get functions
function Player:getLevel() return getPlayerLevel(self.cid) end
function Player:getExperience() return getPlayerExperience(self.cid) end
function Player:getMagicLevel(ignoreBuffs) return getPlayerMagLevel(self.cid, ignoreBuffs) end
function Player:getManaSpent() return getPlayerSpentMana(self.cid) end
function Player:getFood() return getPlayerFood(self.cid) end
function Player:getAccess() return getPlayerAccess(self.cid) end
function Player:getGhostAccess() return getPlayerGhostAccess(self.cid) end
function Player:getSkillLevel(skillid) return getPlayerSkillLevel(self.cid, skillid) end
function Player:getSkillTries(skillid) return getPlayerSkillTries(self.cid, skillid) end
function Player:getTown() return getPlayerTown(self.cid) end
function Player:getVocation() return getPlayerVocation(self.cid) end
function Player:getBaseVocation() local vocation = self:getVocation(); return vocation > 4 and vocation - 4 or vocation end
function Player:getIp() return getPlayerIp(self.cid) end
function Player:getRequiredMana(magicLevel) return getPlayerRequiredMana(self.cid, magicLevel) end
function Player:getRequiredSkillTries(skillId, skillLevel) return getPlayerRequiredSkillTries(self.cid, skillId, skillLevel) end
function Player:getItemCount(itemid, subType) return getPlayerItemCount(self.cid, itemid, subType or -1) end
function Player:getMoney() return getPlayerMoney(self.cid) end
function Player:getSoul() return getPlayerSoul(self.cid) end
function Player:getCap() return getPlayerFreeCap(self.cid) end
function Player:getLight() return getPlayerLight(self.cid) end
function Player:getSlotItem(slot) return getPlayerSlotItem(self.cid, slot) end

-- Player set functions
function Player:setMaxCap(cap) doPlayerSetMaxCapacity(self.cid, cap) end
function Player:setTown(townid) doPlayerSetTown(self.cid, townid) end
function Player:setVocation(vocation) doPlayerSetVocation(self.cid, vocation) end


-- Player send functions
function Player:sendCancelMsg(text) doPlayerSendCancel(self.cid, text) end
function Player:sendDefaultCancelMsg(ReturnValue) doPlayerSendDefaultCancel(self.cid, ReturnValue) end
function Player:sendTextMessage(MessageClasses, message) doPlayerSendTextMessage(self.cid, MessageClasses, message) end
function Player:sendChannelMessage(author, message, SpeakClasses, channel) doPlayerSendChannelMessage(self.cid, author, message, SpeakClasses, channel) end
function Player:sendToChannel(targetId, SpeakClasses, message, channel, time) doPlayerSendToChannel(self.cid, targetId, SpeakClasses, message, channel, time) end
function Player:addMoney(money) doPlayerAddMoney(self.cid, money) end
function Player:removeMoney(money) doPlayerRemoveMoney(self.cid, money) end
function Player:transferMoney(target, money) doPlayerTransferMoneyTo(self.cid, target, money) end
function Player:showTextDialog(itemid, text) doShowTextDialog(self.cid, itemid, text) end
function Player:addSkillTries(skillid, n, useMultiplier) doPlayerAddSkillTry(self.cid, skillid, n, useMultiplier or false) end

-- Player misc. functions
function Player:feed(food) doPlayerFeed(self.cid, food) end
function Player:addSpentMana(amount, useMultiplier) doPlayerAddSpentMana(self.cid, amount, useMultiplier) end
function Player:addSoul(soul) doPlayerAddSoul(self.cid, soul) end
function Player:addItem(itemid, count, canDropOnMap, subtype) return doPlayerAddItem(self.cid, itemid, count, canDropOnMap, subtype) end
function Player:addItemEx(uid, canDropOnMap) return doPlayerAddItemEx(self.cid, uid, canDropOnMap or false) end
function Player:addExperience(amount) doPlayerAddExperience(self.cid, amount) end
function Player:savePlayer(shallow) doPlayerSave(self.cid, shallow or false) end
function Player:isPzLocked() return isPlayerPzLocked(self.cid) end

-- Game
function Game.getStorageValue(key) return getGlobalStorageValue(key) end
function Game.setStorageValue(key, value) setGlobalStorageValue(key, value) end
function Game.getChannelUsers(channelId) return getChannelUsers(channelId) end
function Game.setWorldType(type) return setWorldType(type) end
function Game.getWorldType() return getWorldType() end
function Game.getSpectators(centerPos, rangex, rangey, multifloor) return getSpecators(centerPos, rangex, rangey, multifloor or false) end
function Game.getPlayers() return getPlayersOnline() end
function Game.getExperienceStage(level) return getExperienceStage(level) end
function Game.getGameState() return getGameState() end
function Game.setGameState(state) return doSetGameState(state) end
function Game.startRaid(raid) return doExecuteRaid(raid) end
function Game.createItem(itemId, count, position) return doCreateItem(itemId, count, position) end
function Game.createMonster(name, pos, extend, force, displayError) return doCreateMonster(name, pos, extend or false, force or false, displayError or true) end
function Game.createNpc(name, pos, displayError) return doCreateNpc(name, pos, displayError or true) end

-- Condition
--

-- Combat
--
If there is enough contribution on this, then I'll consider writing all the other Classes aswell.
 
Last edited:
Shouldn't we be starting with Creature?
Since an npc, monster and player is a creature, I am not too sure how inheritance works in lua tho.
 
I've wrote this little lib for compatibility to the new oop way we approached at 1.x
This makes it so that 1.x scripts (atleast Player functions) are working for older versions aswell

It's just a beginning, I'd like everyone to contribute to it, it's quite a pain in the ass to recall all functions.
Code:
Player = {__index = Player}
setmetatable(Player, {
   __call =
   function(self, cid)
     if not self[cid] then
       self[cid] = {__index = Player}
       setmetatable(self[cid], self[cid])
       self[cid].cid = cid
       return self[cid]
     else
       return self[cid]
     end
   end
})

function Player:getId() return self.cid end
function Player:getName() return getPlayerName(self.cid) end
function Player:getHealth() return getPlayerHealth(self.cid) end
function Player:getMaxHealth() return getPlayerMaxHealth(self.cid) end
function Player:getMana() return getPlayerMana(self.cid) end
function Player:getMaxMana() return getPlayerMaxMana(self.cid) end
function Player:getStorageValue(id) return getPlayerStorageValue(self.cid, id) end

function Player:setMaxHealth(health) return setPlayerMaxHealth(self.cid, health) end
function Player:setMaxMana(mana) return setPlayerMaxMana(self.cid, mana) end
function Player:setStorageValue(storage, value) return setPlayerStorageValue(self.cid, storage, value) end
If there is enough contribution on this, then I'll consider writing all the other Classes aswell.
"Player = {__index = Player}"
This is not necessary, in fact you are not even setting __index, it's still nil. :3
 
"Player = {__index = Player}"
This is not necessary, in fact you are not even setting __index, it's still nil. :3
Just playing around with the code, although it works, is this inheritance or something else entirely different.
Code:
Creature = {}
Creature.__index = Creature

setmetatable(Creature, {
    __call = function(cls, ...)
        return cls.new(...)
    end,
   })

function Creature:whoami()
    return "I am a Creature."
end


Player = getmetatable(setmetatable({}, Creature))
print(Player:whoami())
Code:
I am a Creature.
Metatables are little sketchy for me.

Sorry for disrupting this thread, I'll bring my question to support :)
 
Just playing around with the code, although it works, is this inheritance or something else entirely different.
Code:
Creature = {}
Creature.__index = Creature

setmetatable(Creature, {
    __call = function(cls, ...)
        return cls.new(...)
    end,
   })

function Creature:whoami()
    return "I am a Creature."
end


Player = getmetatable(setmetatable({}, Creature))
print(Player:whoami())
Code:
I am a Creature.
Metatables are little sketchy for me.

Sorry for disrupting this thread, I'll bring my question to support :)
Couple of things:
1) You don't need to have Creature.__index = Creature, thats not necessary as i've said.

2) You didn't define "new" so this will not work as a "class" (you cannot create objects it will give error)

3) This assignment is the same as Player = Creature.

If you want to do inheritance you can see this code:
Code:
function newClass(constructor, parent)
    local methods = { }
    if parent then
        methods.__parent = parent
    end
    local MT = {__index = function(a, b) if methods[b] then return methods[b] elseif methods.__parent and methods.__parent[b] then return methods.__parent[b] end end}

    local call = function(self, ...)
        local obj = constructor(...)
        if not obj then
            return nil
        end

        return setmetatable(obj, MT)
    end

    return setmetatable(methods, {__call = call})
end

Creature = newClass(function(id)
    return {id = id}
end)

Player = newClass(function(id, guild)
    return {id = id, guild = guild}
end, Creature)

function Creature:getId()
    return self.id
end

function Player:getGuild()
    return self.guild
end

player = Player(10, 1)
creature = Creature(8)

print(player:getId()) -- Using Creature:getId as it has no definition for Player:getId
print(player:getGuild()) -- Using Player:getGuild
print(creature:getId()) -- Using Creature:getId
print(creature:getGuild()) -- Error, creature has no method getGuild
 
Couple of things:
1) You don't need to have Creature.__index = Creature, thats not necessary as i've said.
It's for the aesthetics :p
2) You didn't define "new" so this will not work as a "class" (you cannot create objects it will give error)
Code:
function Creature.new()
    return "This is new"
end
Code:
print(Player:whoami(), Creature())
Code:
I am a Creature    This is new
3) This assignment is the same as Player = Creature.
Yes, I understand that much.
If you want to do inheritance you can see this code:
Code:
function newClass(constructor, parent)
    local methods = { }
    if parent then
        methods.__parent = parent
    end
    local MT = {__index = function(a, b) if methods[b] then return methods[b] elseif methods.__parent and methods.__parent[b] then return methods.__parent[b] end end}

    local call = function(self, ...)
        local obj = constructor(...)
        if not obj then
            return nil
        end

        return setmetatable(obj, MT)
    end

    return setmetatable(methods, {__call = call})
end

Creature = newClass(function(id)
    return {id = id}
end)

Player = newClass(function(id, guild)
    return {id = id, guild = guild}
end, Creature)

function Creature:getId()
    return self.id
end

function Player:getGuild()
    return self.guild
end

player = Player(10, 1)
creature = Creature(8)

print(player:getId()) -- Using Creature:getId as it has no definition for Player:getId
print(player:getGuild()) -- Using Player:getGuild
print(creature:getId()) -- Using Creature:getId
print(creature:getGuild()) -- Error, creature has no method getGuild
So what does all that code do and why is better than the version I wrote, what makes it different?
Could you please provide an in-depth explanation of its execution?
 
It's for the aesthetics :p

Code:
function Creature.new()
    return "This is new"
end
Code:
print(Player:whoami(), Creature())
Code:
I am a Creature    This is new

Yes, I understand that much.

So what does all that code do and why is better than the version I wrote, what makes it different?
Could you please provide an in-depth explanation of its execution?
It's different because if you define it like this you are not doing inheritance, both are the same and if you define new methods for one the other one will have it as well.

Tried to explain as best as i could:
Code:
function newClass(constructor, parent)
    local methods = { } -- This is the main table that will have the call metamethod to construct the object, so it will also contains all the methods that you define for this class later on
    if parent then
        -- parent is the class (table with all methods of one class) so it will keep the reference to it in methods.__parent.
        methods.__parent = parent
    end
    local MT = {__index = function(a, b)
        if methods[b] then -- This will check if the current method being called is defined in the main class
            return methods[b] -- This returns the function in the main class
        elseif methods.__parent and methods.__parent[b] then -- This will check if it has a parent and if the parent has the method being called
            return methods.__parent[b] -- This returns the function in the parent class.
        end
    end}

    local call = function(self, ...) -- This will call the constructor function that returns a table containing the information for that class objects
        local obj = constructor(...)
        if not obj then
            return nil
        end

        return setmetatable(obj, MT) -- Sets metatable to the object that is returning when you call it
    end

    return setmetatable(methods, {__call = call}) -- Sets the constructor call metamethod to create objects
end
 
"Player = {__index = Player}"
This is not necessary, in fact you are not even setting __index, it's still nil. :3
Silly me, forgot that you couldn't do it this way in lua
but keeping the self index is just fine from what I read, if you go by inheritance from deep nesting __index this works as a break.
 
I did some for 0.3.6 :)
Code:
function Creature:getHealth() return getCreatureHealth(self.cid) end
function Creature:getMaxHealth() return getCreatureMaxHealth(self.cid) end
function Creature:getMana() return getCreatureMana(self.cid) end
function Creature:getMaxMana() return getCreatureMaxMana(self.cid) end
function Creature:getHiddenHealth() return getCreatureHideHealth(self.cid) end
function Creature:setHiddenHealth(hide) doCreatureSetHideHealth(self.cid, hide) end
function Creature:getSpeakType() return getCreatureSpeakType(self.cid) end
function Creature:setSpeakType(type) doCreatureSetSpeakType(self.cid, type) end
function Creature:getLookDirection() return getCreatureLookDirection(self.cid) end


function Player:getLevel() return getPlayerLevel(self.cid) end
function Player:getExperience() return getPlayerExperience(self.cid) end
function Player:getMagicLevel(ignoreBuffs) return getPlayerMagLevel(self.cid, ignoreBuffs) end
function Player:getManaSpent() return getPlayerSpentMana(self.cid) end
function Player:getFood() return getPlayerFood(self.cid) end
function Player:getAccess() return getPlayerAccess(self.cid) end
function Player:getGhostAccess() return getPlayerGhostAccess(self.cid) end
function Player:getSkillLevel(skillid) return getPlayerSkillLevel(self.cid, skillid) end
function Player:getSkillTries(skillid) return getPlayerSkillTries(self.cid, skillid) end
function Player:getTown() return getPlayerTown(self.cid) end
function Player:getVocation() return getPlayerVocation(self.cid) end
function Player:getBaseVocation() local vocation = self:getVocation() return vocation > 4 and vocation - 4 or vocation end
function Player:getIp() return getPlayerIp(self.cid) end
function Player:getRequiredMana(magicLevel) return getPlayerRequiredMana(self.cid, magicLevel) end
function Player:getRequiredSkillTries(skillId, skillLevel) return getPlayerRequiredSkillTries(self.cid, skillId, skillLevel) end
function Player:getItemCount(itemid, subType) return getPlayerItemCount(self.cid, itemid, subType or -1) end
function Player:getMoney() return getPlayerMoney(self.cid) end
function Player:getSoul() return getPlayerSoul(self.cid) end
function Player:getCap() return getPlayerFreeCap(self.cid) end
function Player:getLight() return getPlayerLight(self.cid) end
function Player:getSlotItem(slot) return getPlayerSlotItem(self.cid, slot) end
function Player:getWeapon(ignoreAmmo) return getPlayerWeapon(self.cid, ignoreAmmo) end
function Player:getItemById(deepSearch, itemId, subType) return getPlayerItemById(self.cid, deepSearch, itemId, subType or -1) end
 
Last edited:
Code:
function Player:getDepotItems(depoid) return getPlayerDepotItems(self.cid, depotid) end
function Player:getGuildId() return getPlayerGuildId(self.cid) end
function Player:getGuildName() return getPlayerGuildName(self.cid) end
function Player:getGuildRankId() return getPlayerGuildRankId(self.cid) end
function Player:getGuildRank() return getPlayerGuildRank(self.cid) end
function Player:getGuildNick() return getPlayerGuildNick(self.cid) end
function Player:getGuildLevel() return getPlayerGuildLevel(self.cid) end
function Player:getGUID() return getPlayerGUID(self.cid) end
function Player:getDescription() return getPlayerNameDescription(self.cid) end
function Player:setDescription(desc) doPlayerSetNameDescription(self.cid, desc) end
function Player:getSpecialDescription() return getPlayerSpecialDescription(self.cid) end
function Player:setSpecialDescription(desc) doPlayerSetSpecialDescription(self.cid, desc) end
function Player:getAccountId() return getPlayerAccountId(self.cid) end
function Player:getAccount() return getPlayerAccount(self.cid) end
function Player:getFlagValue(flag) return getPlayerFlagValue(self.cid, flag) end
function Player:getCustomFlagValue(flag) return getPlayerCustomFlagValue(self.cid, flag) end
function Player:getPromotion() return getPlayerPromotionLevel(self.cid) end
function Player:setPromotion(level) doPlayerSetPromotionLevel(self.cid, level) end
function Player:getGroup() return getPlayerGroupId(self.cid) end
function Player:setGroup(newGroupId) doPlayerSetGroupId(self.cid, newGroupId) end
function Player:sendOutfitWindow() doPlayerSendOutfitWindow(self.cid) end
function Player:learnSpell(name) doPlayerLearnInstantSpell(self.cid, name) end
function Player:forgetSpell(name) doPlayerUnlearnInstantSpell(self.cid, name) end
function Player:getLearnedSpell(name) return getPlayerLearnedInstantSpell(self.cid, name) end
function Player:getSpellCount() return getPlayerInstantSpellCount(self.cid) end
function Player:getSpellInfo(index) if type(index) == 'number' then return getPlayerInstantSpellInfo(self.cid, index) end return getInstantSpellInfo(self.cid, index) end
function Player:getStorageValue(key) return getCreatureStorage(self.cid, key) end
function Player:setStorageValue(key, value) doCreatureSetStorage(self.cid, key, value) end


Game = {}

function Game.getStorage(key) return getStorage(key) end
function Game.setStorage(key, value) doSetStorage(key, value) end
function Game.getChannelUsers(channelId) return getChannelUsers(channelId) end
function Game.getPlayersOnline() return getPlayersOnline() end
 
Last edited:
Code:
function Player:feed(food) doPlayerFeed(self.cid, food) end
function Player:sendCancelMessage(text) doPlayerSendCancel(self.cid, text) end
function Player:sendDefaultCancelMessage(ReturnValue) doPlayerSendDefaultCancel(self.cid, ReturnValue) end

function Creature:teleportTo(newpos, pushmove) doTeleportThing(self.cid, newpos, pushmove or false) end
 
Last edited:
thanks @Omni Cloud updated first post
but one thing, please keep the code convention the same as I did, makes it easier to merge.
 
thanks @Omni Cloud updated first post
but one thing, please keep the code convention the same as I did, makes it easier to merge.
You should change your createClass to accept a constructor function, like this you can only create creature classes. And you should place conditions like in TFS 1.x like:
https://github.com/otland/forgottenserver/blob/master/src/luascript.cpp#L7419-7446

Something like:
Code:
Player = newClass(function(param)
    if type(param) == 'string' then
        local cid = getPlayerByNameWildcard(param)
        if not cid then
            return nil
        end
        return {cid = cid}
    elseif type(param) == 'number' then
        if not getPlayerGUID(param) then
            return nil
        end
        return {cid = param}
    else
        return nil
    end
end, Creature)
 
Code:
function Creature:addHealth(health, hitEffect, hitColor, force) doCreatureAddHealth(self.cid, health, hitEffect, hitColor, force) end
function Creature:setMaxHealth(health) setCreatureMaxHealth(self.cid, health) end
function Creature:say(text, type, ghost, cid, pos) doCreatureSay(self.cid, text, type or SPEAK_SAY, ghost or false, cid or 0, pos) end
function Creature:addCondition(condition) doAddCondition(self.cid, condition) end
function Creature:removeCondition(onlyPersistent, type, subId) if onlyPersistent then doRemoveConditions(self.cid, onlyPersistent) else doRemoveCondition(self.cid, type, subId) end end
function Creature:onMoveCreature(direction) doMoveCreature(self.cid, direction) end
function Creature:isCreature() return isCreature(self.cid) end


function Player:addMana(mana) doCreatureAddMana(self.cid, mana) end
function Player:setMaxCap(cap) doPlayerSetMaxCapacity(self.cid, cap) end
function Player:addSpentMana(amount, useMultiplier) doPlayerAddSpentMana(self.cid, amount, useMultiplier) end
function Player:addSoul(soul) doPlayerAddSoul(self.cid, soul) end
function Player:addItem(itemid, count, canDropOnMap, subtype) return doPlayerAddItem(self.cid, itemid, count, canDropOnMap, subtype) end
function Player:addItemEx(uid, canDropOnMap) return doPlayerAddItemEx(self.cid, uid, canDropOnMap or false) end
function Player:sendTextMessage(MessageClasses, message) doPlayerSendTextMessage(self.cid, MessageClasses, message) end
function Player:sendChannelMessage(author, message, SpeakClasses, channel) doPlayerSendChannelMessage(self.cid, author, message, SpeakClasses, channel) end
function Player:sendToChannel(targetId, SpeakClasses, message, channel, time) doPlayerSendToChannel(self.cid, targetId, SpeakClasses, message, channel, time) end
function Player:addMoney(money) doPlayerAddMoney(self.cid, money) end
function Player:removeMoney(money) doPlayerRemoveMoney(self.cid, money) end
function Player:transferMoney(target, money) doPlayerTransferMoneyTo(self.cid, target, money) end
function Player:showTextDialog(itemid, text) doShowTextDialog(self.cid, itemid, text) end
function Player:addSkillTries(skillid, n, useMultiplier) doPlayerAddSkillTry(self.cid, skillid, n, useMultiplier or false) end
function Player:remove(forceLogout) doRemoveCreature(self.cid, forceLogout or true) end
function Player:setTown(townid) doPlayerSetTown(self.cid, townid) end
function Player:setVocation(vocation) doPlayerSetVocation(self.cid, vocation) end
function Player:addExperience(amount) doPlayerAddExperience(self.cid, amount) end
function Player:savePlayer(shallow) doPlayerSave(self.cid, shallow or false) end
function Player:isPlayer() return isPlayer(self.cid) end
function Player:isPzLocked() return isPlayerPzLocked(self.cid) end

Monster = newClass(function(id)
    return {id = id}
end, Creature)

function Monster:isMonster() return isMonster(self.cid) end

Npc = newClass(function(id)
    return {id = id}
end, Creature)

function Npc:isNpc() return isNpc(self.cid) end
 
Last edited:
Code:
Combat = newClass(function()
    self.combat = createCombatObject()
    return self.combat
end)

function Combat:setArea(area) return setCombatArea(self.combat, area) end

Condition = newClass(function(type, ticks, buff, subId)
    self = {type = type, ticks = ticks or -1, buff = buff or false, subId = subId or 1}
    return createConditionObject(self.type, self.ticks, self.buff, self.subId)
end)
 
Last edited:
You should change your createClass to accept a constructor function, like this you can only create creature classes. And you should place conditions like in TFS 1.x like:
https://github.com/otland/forgottenserver/blob/master/src/luascript.cpp#L7419-7446

Something like:
Code:
Player = newClass(function(param)
    if type(param) == 'string' then
        local cid = getPlayerByNameWildcard(param)
        if not cid then
            return nil
        end
        return {cid = cid}
    elseif type(param) == 'number' then
        if not getPlayerGUID(param) then
            return nil
        end
        return {cid = param}
    else
        return nil
    end
end, Creature)
done, except for the fact that I didn't implement the userdata check, doesn't make sense to add that.
Code:
function Creature:addHealth(health, hitEffect, hitColor, force) doCreatureAddHealth(self:getId(), health, hitEffect, hitColor, force) end
function Creature:setMaxHealth(health) setCreatureMaxHealth(self:getId(), health) end
function Creature:say(text, type, ghost, cid, pos) doCreatureSay(self:getId(), text, type or SPEAK_SAY, ghost or false, cid or 0, pos) end
function Creature:addCondition(condition) doAddCondition(self:getId(), condition) end
function Creature:removeCondition(onlyPersistent, type, subId) if onlyPersistent then doRemoveConditions(self:getId(), onlyPersistent) else doRemoveCondition(self:getId(), type, subId) end end
function Creature:onMoveCreature(direction) doMoveCreature(self:getId(), direction) end
function Creature:isCreature() return isCreature(self:getId()) end


function Player:addMana(mana) doCreatureAddMana(self:getId(), mana) end
function Player:setMaxCap(cap) doPlayerSetMaxCapacity(self:getId(), cap) end
function Player:addSpentMana(amount, useMultiplier) doPlayerAddSpentMana(self:getId(), amount, useMultiplier) end
function Player:addSoul(soul) doPlayerAddSoul(self:getId(), soul) end
function Player:addItem(itemid, count, canDropOnMap, subtype) return doPlayerAddItem(self:getId(), itemid, count, canDropOnMap, subtype) end
function Player:addItemEx(uid, canDropOnMap) return doPlayerAddItemEx(self:getId(), uid, canDropOnMap or false) end
function Player:sendTextMessage(MessageClasses, message) doPlayerSendTextMessage(self:getId(), MessageClasses, message) end
function Player:sendChannelMessage(author, message, SpeakClasses, channel) doPlayerSendChannelMessage(self:getId(), author, message, SpeakClasses, channel) end
function Player:sendToChannel(targetId, SpeakClasses, message, channel, time) doPlayerSendToChannel(self:getId(), targetId, SpeakClasses, message, channel, time) end
function Player:addMoney(money) doPlayerAddMoney(self:getId(), money) end
function Player:removeMoney(money) doPlayerRemoveMoney(self:getId(), money) end
function Player:transferMoney(target, money) doPlayerTransferMoneyTo(self:getId(), target, money) end
function Player:showTextDialog(itemid, text) doShowTextDialog(self:getId(), itemid, text) end
function Player:addSkillTries(skillid, n, useMultiplier) doPlayerAddSkillTry(self:getId(), skillid, n, useMultiplier or false) end
function Player:remove(forceLogout) doRemoveCreature(self:getId(), forceLogout or true) end
function Player:setTown(townid) doPlayerSetTown(self:getId(), townid) end
function Player:setVocation(vocation) doPlayerSetVocation(self:getId(), vocation) end
function Player:addExperience(amount) doPlayerAddExperience(self:getId(), amount) end
function Player:savePlayer(shallow) doPlayerSave(self:getId(), shallow or false) end
function Player:isPlayer() return isPlayer(self:getId()) end
function Player:isPzLocked() return isPlayerPzLocked(self:getId()) end

Monster = newClass(function(id)
    return {id = id}
end, Creature)

function Monster:isMonster() return isMonster(self:getId()) end

Npc = newClass(function(id)
    return {id = id}
end, Creature)

function Npc:isNpc() return isNpc(self:getId()) end
Code:
Combat = newClass(function()
    self.combat = createCombatObject()
    return self.combat
end)

function Combat:setArea(area) return setCombatArea(self.combat, area) end

Condition = newClass(function(type, ticks, buff, subId)
    self = {type = type, ticks = ticks or -1, buff = buff or false, subId = subId or 1}
    return createConditionObject(self.type, self.ticks, self.buff, self.subId)
end)
thanks will add them soon.
btw refrain from using self:getId(), it's easier to call self.cid as we don't have to call an extra function everytime which gives us the exact same table field as we could get with self.cid anyway :p
 
Omg, awesome! Im waiting for final lib :D
 
Back
Top