• 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 system TFS 1.2 count party

shakal1994

Member
Joined
Nov 20, 2020
Messages
77
Reaction score
15
I'm using this creativescripts, I wanted you to tell everyone who attacks the monster, can you help me??
function onKill(player, target)
if target:isPlayer() or target:getMaster() then
return true
end


local targetName, startedTasks, taskId = target:getName():lower(), player:getStartedTasks()
for i = 1, #startedTasks do
taskId = startedTasks
if isInArray(tasks[taskId].creatures, targetName) then
local killAmount = player:getStorageValue(KILLSSTORAGE_BASE + taskId)
if killAmount < tasks[taskId].killsRequired then
player:setStorageValue(KILLSSTORAGE_BASE + taskId, killAmount + 1)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE,'You kill: ' .. killAmount + 1 .. "/" .. tasks[taskId].killsRequired .. " " ..tasks[taskId].raceName)
else
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE,'You complete task of ' ..tasks[taskId].raceName)
end
end
end
return true
end

--MESSAGE_STATUS_DEFAULT

Post automatically merged:

I got a creaturescripts that counts the party, the problem is that it counts the one that deals the most damage and the last hit, so it counts 2 times for the one that deals the most damage and the last hit

function onKill(player, target)
if target:isPlayer() or target:getMaster() then
return true
end

local party = player:getParty()
print("Killer: " .. player:getName())
print("Target: " .. target:getName())
local players = {}
if party then
print("There was a party")
players = party:getMembers()
leader = party:getLeader()
print("Party leader:" .. leader:getName())
table.insert(players, leader)
else
print("Solo")
players = {player}
end

print("Number of players in party: " .. #players)


for p = 1, #players do
local partyMember = players[p]
print("Processing kill for player " .. partyMember:getName())
local targetName, startedTasks, taskId = target:getName():lower(), partyMember:getStartedTasks()
for i = 1, #startedTasks do
taskId = startedTasks
if isInArray(tasks[taskId].creatures, targetName) then
local killAmount = partyMember:getStorageValue(KILLSSTORAGE_BASE + taskId)
if killAmount < tasks[taskId].killsRequired then
partyMember:setStorageValue(KILLSSTORAGE_BASE + taskId, killAmount + 1)
partyMember:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE,'You kill: ' .. killAmount + 1 .. "/" .. tasks[taskId].killsRequired .. " " ..tasks[taskId].raceName)
else
partyMember:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE,'You complete task of ' ..tasks[taskId].raceName)
end
end
end
end
return true
end

--MESSAGE_STATUS_DEFAULT
 
Last edited:
Solution
After quick chat It turned out it was meant to work for all party member (or player) that dealt any damage:
mostDamageCreature is to execute it once only for mostDmgCreature and not to execute it once again for lastHitCreature
I still got some doubts about that approach as it looks a bit hacky to me but seems like it does its job

Lua:
function onKill(player, target)
    if target:isPlayer() or target:getMaster() then
        return true
    end

    local party = player:getParty()
    local players = {}
    if party then
        players = party:getMembers()
        table.insert(players, party:getLeader())
    else
        players = { player }
    end

    local attackers = {}
    local damageMap = target:getDamageMap()...
Hmm, maybe try this "trick" (not tested):
Lua:
local damageMap = target:getDamageMap()
local mostDamageCreature
local maxTotal = 0
for pid, dmg in pairs(damageMap) do
    if dmg.total > maxTotal then
        maxTotal = dmg.total
        mostDamageCreature = pid
    end
end

if player ~= Player(mostDamageCreature) then
    return true
end

Or you could check damageRatio < desiredRatio:
Lua:
if target:isPlayer() or target:getMaster() or target:getDamageRatio(player) < 0.5 then
    return true
end

Or combine:
Lua:
local mostDamageCreature
local maxRatio = 0
for pid, _ in pairs(damageMap) do
    local ratio = target:getDamageRatio(pid)
    if ratio > maxRatio then
        mostDamageCreature = pid
        maxRatio = ratio
    end
end

if player ~= Player(mostDamageCreature) then
    return true
end

EDIT:
Sorry, I forgott getDamageRatio is something that I added on my own to my fork :D
But I think you could use solution with getDamageMap
 
Last edited:
Hmm, maybe try this "trick" (not tested):
Lua:
local damageMap = target:getDamageMap()
local mostDamageCreature
local maxTotal = 0
for pid, dmg in pairs(damageMap) do
    if dmg.total > maxTotal then
        maxTotal = maxTotal
        mostDamageCreature = pid
    end
end

if player ~= Player(mostDamageCreature) then
    return true
end

Or you could check damageRatio < desiredRatio:
Lua:
if target:isPlayer() or target:getMaster() or target:getDamageRatio(player) < 0.5 then
    return true
end
Did not work :(
 
After quick chat It turned out it was meant to work for all party member (or player) that dealt any damage:
mostDamageCreature is to execute it once only for mostDmgCreature and not to execute it once again for lastHitCreature
I still got some doubts about that approach as it looks a bit hacky to me but seems like it does its job

Lua:
function onKill(player, target)
    if target:isPlayer() or target:getMaster() then
        return true
    end

    local party = player:getParty()
    local players = {}
    if party then
        players = party:getMembers()
        table.insert(players, party:getLeader())
    else
        players = { player }
    end

    local attackers = {}
    local damageMap = target:getDamageMap()
    local mostDamageCreature
    local maxTotal = 0
    for pid, dmg in pairs(damageMap) do
        local p = Player(pid)
        if table.contains(players, p) then
            table.insert(attackers, p)
        end

        if dmg.total > maxTotal then
            maxTotal = dmg.total
            mostDamageCreature = p
        end
    end

    if player ~= mostDamageCreature then
        return true
    end

    local targetName = target:getName():lower()
    for _, attacker in ipairs(attackers) do
        local startedTasks = attacker:getStartedTasks()
        for _, taskId in ipairs(startedTasks) do
            local task = tasks[taskId]
            if table.contains(task.creatures, targetName) then
                local killAmount = attacker:getStorageValue(KILLSSTORAGE_BASE + taskId)
                if killAmount < task.killsRequired then
                    attacker:setStorageValue(KILLSSTORAGE_BASE + taskId, killAmount + 1)
                    attacker:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You kill: ' .. killAmount + 1 .. "/" .. task.killsRequired .. " " .. task.raceName)
                else
                    attacker:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You complete task of ' .. task.raceName)
                end
            end
        end
    end

    return true
end
 
Last edited:
Solution
After quick chat It turned out it was meant to work for all party member (or player) that dealt any damage:
mostDamageCreature is to execute it once only for mostDmgCreature and not to execute it once again for lastHitCreature
I still got some doubts about that approach as it looks a bit hacky to me but seems like it does its job

Lua:
function onKill(player, target)
    if target:isPlayer() or target:getMaster() then
        return true
    end

    local party = player:getParty()
    local players = {}
    if party then
        players = party:getMembers()
        table.insert(players, party:getLeader())
    else
        players = { player }
    end

    local attackers = {}
    local damageMap = target:getDamageMap()
    local mostDamageCreature
    local maxTotal = 0
    for pid, dmg in pairs(damageMap) do
        local p = Player(pid)
        if table.contains(players, p) then
            table.insert(attackers, p)
        end

        if dmg.total > maxTotal then
            maxTotal = maxTotal
            mostDamageCreature = p
        end
    end

    if player ~= mostDamageCreature then
        return true
    end

    local targetName = target:getName():lower()
    for _, attacker in ipairs(attackers) do
        local startedTasks = attacker:getStartedTasks()
        for _, taskId in ipairs(startedTasks) do
            local task = tasks[taskId]
            if table.contains(task.creatures, targetName) then
                local killAmount = attacker:getStorageValue(KILLSSTORAGE_BASE + taskId)
                if killAmount < task.killsRequired then
                    attacker:setStorageValue(KILLSSTORAGE_BASE + taskId, killAmount + 1)
                    attacker:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You kill: ' .. killAmount + 1 .. "/" .. task.killsRequired .. " " .. task.raceName)
                else
                    attacker:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You complete task of ' .. task.raceName)
                end
            end
        end
    end

    return true
end
Better result will be with change this

maxTotal = maxTotal
0 = 0
Xd
 
@shakal1994 a ye that depends on the distro, some of them return leader as a member and some don’t. Add some debug print’s to check which condition’s are met.
 
Your scripts with a few changes were perfect for me. Now regardless of being at the party or not, if the player participates he already has a task! Thank you very much for your time
function onKill(player, target)
if target:isPlayer() or target:getMaster() then
return true
end


local attackers = {}
local damageMap = target:getDamageMap()
local mostDamageCreature
local maxTotal = 0
for pid, dmg in pairs(damageMap) do
local p = Player(pid)
table.insert(attackers, p)
if dmg.total > maxTotal then
maxTotal = maxTotal
mostDamageCreature = p
end
end

if player ~= mostDamageCreature then
return true
end

local targetName = target:getName():lower()
for _, attacker in ipairs(attackers) do
local startedTasks = attacker:getStartedTasks()
for _, taskId in ipairs(startedTasks) do
local task = tasks[taskId]
if table.contains(task.creatures, targetName) then
local killAmount = attacker:getStorageValue(KILLSSTORAGE_BASE + taskId)
if killAmount < task.killsRequired then
attacker:setStorageValue(KILLSSTORAGE_BASE + taskId, killAmount + 1)
attacker:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You kill: ' .. killAmount + 1 .. "/" .. task.killsRequired .. " " .. task.raceName)
else
attacker:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You complete task of ' .. task.raceName)
end
end
end
end

return true
end
 
Back
Top