• 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!

Lua Task.lua (Creaturescript).

Zodia

Member
Joined
Feb 21, 2020
Messages
220
Reaction score
20
After a long time breaking my head, I managed to make the party shared by players within a party. But I have some problems with the final version of the code.


If any player has 2 players in a party, one player gives a hit, and the other gives the "last" hit, one task counts twice for each.

The would be ideal:

A task will only be told to party members if exp sharing is active - Evitaria service, of a low level, receiving help in really strong shows.

Limit to 4 players. That is, over 4 players at the party (preferably if for each vocation) a task does not count.


Would anyone know how to guide me in this?
Or at least help with the duplicate problem?


Thanks.

Task.lua (creaturescript).
Lua:
function onKill(creature, target)
    local monster = config[target:getName():lower()]
    if not monster or target:getMaster() then
        return true
    end

    local damageMap = target:getDamageMap()
    for attackerId, damage in pairs(damageMap) do
        local player = Player(attackerId)
        if player then
            ------------------------------------------------
            local task = player:getParty()
            if task then
                local monstersKilled = player:getStorageValue(monster.storage)
                if monstersKilled >= monster.start then
                    if damageMap.total > player:getDamageMap().total then
                        return false
                    end
                    player:setStorageValue(monster.storage, monstersKilled + 1)
                    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You have killed [" .. monstersKilled .. "/" .. monster.count .. "] " .. monster.plural .. ".")
                end
            end
        end
        ------------------------------------------------
    end

    return true
end
 
After a long time breaking my head, I managed to make the party shared by players within a party. But I have some problems with the final version of the code.


If any player has 2 players in a party, one player gives a hit, and the other gives the "last" hit, one task counts twice for each.

The would be ideal:

A task will only be told to party members if exp sharing is active - Evitaria service, of a low level, receiving help in really strong shows.

Limit to 4 players. That is, over 4 players at the party (preferably if for each vocation) a task does not count.


Would anyone know how to guide me in this?
Or at least help with the duplicate problem?


Thanks.

Task.lua (creaturescript).
Lua:
function onKill(creature, target)
    local monster = config[target:getName():lower()]
    if not monster or target:getMaster() then
        return true
    end

    local damageMap = target:getDamageMap()
    for attackerId, damage in pairs(damageMap) do
        local player = Player(attackerId)
        if player then
            ------------------------------------------------
            local task = player:getParty()
            if task then
                local monstersKilled = player:getStorageValue(monster.storage)
                if monstersKilled >= monster.start then
                    if damageMap.total > player:getDamageMap().total then
                        return false
                    end
                    player:setStorageValue(monster.storage, monstersKilled + 1)
                    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You have killed [" .. monstersKilled .. "/" .. monster.count .. "] " .. monster.plural .. ".")
                end
            end
        end
        ------------------------------------------------
    end

    return true
end


i created similar code some time ago. Maybe there is other way to do it but i made simple table and insert leader + party members if they wanst in table already like:

local players = {}
local members = player:getParty():getMembers()
for i = 1, #members do
--here other code blablalbal, damage map etc. and then
if(not table.contains(players, members) then..
--and after then you just iterate players and give kill count for every player cuz every is unique
end


Lua:
local questMonsters = {
    ['Wolf'] = {
        {
            storage = {5555, 0}, count = 200, npc = "Test npc"
        }
    },
    ['Troll'] = {
        {
            storage = {50123, 0}, count = 200, npc = "test npc"
        }
    },
}
local mobCache = {}
for questMob, questinfo in pairs(questMonsters) do
    for i = 1, #questinfo do
        local cacheEntry = mobCache[questinfo[i].storage[1]]
        if(not cacheEntry) then
            mobCache[questinfo[i].storage[1]] = {}
        end
        if(not table.contains(mobCache[questinfo[i].storage[1]], questMob)) then
            table.insert(mobCache[questinfo[i].storage[1]], questMob)
        end
    end
end

function onKill(cid, target, lastHit)
    if(not target:isMonster()) then return true end
    local targetName = target:getName()
    local questEntry = questMonsters[targetName]
    if(questEntry) then
        local players = {}
        local killer = Player(cid)
        table.insert(players, killer:getId())
        local party = killer:getParty()
        if(party) then
            local members = party:getMembers()
            for i = 1, #members do
                for _cid, _damage in pairs(target:getDamageMap()) do
                    if(members[i] and Creature(members[i])) then
                        if(_cid == members[i]) then
                            if(not table.contains(players, _cid)) then
                                table.insert(players, _cid)
                                break
                            end
                            break
                        end
                    end
                end
            end
        end

        for index = 1, #players do
            for i = 1, #questEntry do
                local player = Player(players[index])
                if(not player) then break end
                local currentQuest = questEntry[i]
                local currentStorage = player:getStorageValue(currentQuest.storage[1])
                if(currentStorage >= currentQuest.storage[2]) then
                    local newKillCount = currentStorage + 1
                    if(newKillCount > currentQuest.count) then
                        break
                    elseif(newKillCount == currentQuest.count) then
                        player:sendTextMessage(MESSAGE_EVENT_ORANGE, ''.. currentQuest.npc ..': You clearly killed all required monsters! Comeback to me to claim reward.')
                    else
                        local mobCacheRet = mobCache[currentQuest.storage[1]]
                        local infoName = targetName
                        if(mobCacheRet) then
                            if(#mobCacheRet > 1) then
                                infoName = "("..infoName..table.concat(mobCacheRet, ", ")..")"
                            end
                        end
                        player:sendTextMessage(MESSAGE_EVENT_ORANGE, ''.. currentQuest.npc ..': You killed '.. newKillCount .. ' of ' .. currentQuest.count .. ' '.. infoName ..'.')
                    end
                    player:setStorageValue(currentQuest.storage[1], newKillCount)
                 end
            end
        end
    end

return true
end

just realized that my code have bug when im using break, cuz if u have multiple tasks for same monsters activated it will stop counting them if one of your tasks for that monster is done. Need to remove this break and instead use if not :D
 
i created similar code some time ago. Maybe there is other way to do it but i made simple table and insert leader + party members if they wanst in table already like:

local players = {}
local members = player:getParty():getMembers()
for i = 1, #members do
--here other code blablalbal, damage map etc. and then
if(not table.contains(players, members) then..
--and after then you just iterate players and give kill count for every player cuz every is unique
end


Lua:
local questMonsters = {
    ['Wolf'] = {
        {
            storage = {5555, 0}, count = 200, npc = "Test npc"
        }
    },
    ['Troll'] = {
        {
            storage = {50123, 0}, count = 200, npc = "test npc"
        }
    },
}
local mobCache = {}
for questMob, questinfo in pairs(questMonsters) do
    for i = 1, #questinfo do
        local cacheEntry = mobCache[questinfo[i].storage[1]]
        if(not cacheEntry) then
            mobCache[questinfo[i].storage[1]] = {}
        end
        if(not table.contains(mobCache[questinfo[i].storage[1]], questMob)) then
            table.insert(mobCache[questinfo[i].storage[1]], questMob)
        end
    end
end

function onKill(cid, target, lastHit)
    if(not target:isMonster()) then return true end
    local targetName = target:getName()
    local questEntry = questMonsters[targetName]
    if(questEntry) then
        local players = {}
        local killer = Player(cid)
        table.insert(players, killer:getId())
        local party = killer:getParty()
        if(party) then
            local members = party:getMembers()
            for i = 1, #members do
                for _cid, _damage in pairs(target:getDamageMap()) do
                    if(members[i] and Creature(members[i])) then
                        if(_cid == members[i]) then
                            if(not table.contains(players, _cid)) then
                                table.insert(players, _cid)
                                break
                            end
                            break
                        end
                    end
                end
            end
        end

        for index = 1, #players do
            for i = 1, #questEntry do
                local player = Player(players[index])
                if(not player) then break end
                local currentQuest = questEntry[i]
                local currentStorage = player:getStorageValue(currentQuest.storage[1])
                if(currentStorage >= currentQuest.storage[2]) then
                    local newKillCount = currentStorage + 1
                    if(newKillCount > currentQuest.count) then
                        break
                    elseif(newKillCount == currentQuest.count) then
                        player:sendTextMessage(MESSAGE_EVENT_ORANGE, ''.. currentQuest.npc ..': You clearly killed all required monsters! Comeback to me to claim reward.')
                    else
                        local mobCacheRet = mobCache[currentQuest.storage[1]]
                        local infoName = targetName
                        if(mobCacheRet) then
                            if(#mobCacheRet > 1) then
                                infoName = "("..infoName..table.concat(mobCacheRet, ", ")..")"
                            end
                        end
                        player:sendTextMessage(MESSAGE_EVENT_ORANGE, ''.. currentQuest.npc ..': You killed '.. newKillCount .. ' of ' .. currentQuest.count .. ' '.. infoName ..'.')
                    end
                    player:setStorageValue(currentQuest.storage[1], newKillCount)
                 end
            end
        end
    end

return true
end

just realized that my code have bug when im using break, cuz if u have multiple tasks for same monsters activated it will stop counting them if one of your tasks for that monster is done. Need to remove this break and instead use if not :D


I tried but it didn't work. And there were no errors on the console.
Do I need to adapt something in the code or in the NPC?
 
I've been up for about 30 hours, so not doing this right now..

But here's my idea, if someone wants to do it on their own.

(This would work for entire party. You could modify the idea further to do the 1 storage for each vocation idea.. but there's a bunch of unknowns.. what if there is 2 knight's 2 paladins? Only 1 knight 1 paladin get's it? There's not enough information in the posts to know, so not going to bother. xD)

onKill for the trigger..
find all players in party that are within range of the creature and store them in an array.
give all players in array the storage like you normally would AND
also store all of the players who received the storage in another global array with the creatureId as the index.

--
So the first person in the party that the onKill triggers for, will basically give everyone the storages / rewards, and everyone else, you just check if they're in the array of players who have already received the rewards, using the creatureId.

--
And of course make a clean-up function, to clear out the table of old creatureId's.

--
Sorry if above makes no sense, but again.. 30+ hours. xD
 
I've been up for about 30 hours, so not doing this right now..

But here's my idea, if someone wants to do it on their own.

(This would work for entire party. You could modify the idea further to do the 1 storage for each vocation idea.. but there's a bunch of unknowns.. what if there is 2 knight's 2 paladins? Only 1 knight 1 paladin get's it? There's not enough information in the posts to know, so not going to bother. xD)

onKill for the trigger..
find all players in party that are within range of the creature and store them in an array.
give all players in array the storage like you normally would AND
also store all of the players who received the storage in another global array with the creatureId as the index.

--
So the first person in the party that the onKill triggers for, will basically give everyone the storages / rewards, and everyone else, you just check if they're in the array of players who have already received the rewards, using the creatureId.

--
And of course make a clean-up function, to clear out the table of old creatureId's.

--
Sorry if above makes no sense, but again.. 30+ hours. xD

I found it interesting. <3 Too bad I'm just starting ... But it's still a good study
 
Back
Top