• 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 Blue Arrow when drop item rare

Carlitos Flow

Developer (lvl*1)
Joined
Mar 2, 2011
Messages
156
Solutions
4
Reaction score
10
Hello, im trying to add the magic effect #55 when x player drops x item (like an item rare) from a corpse of monster, its not working, anyone can help me please? Thanks (already registed in login)
-(Arrow effect appear on the corpse from the monster)
I was testing with print console and only prints number 0 and 1

Lua:
local effect = 55                             
local arrow = {55, 60}                     --Effect and seconds.

function isRare(itemid)
local items = {5897, 2666, 3976}          --IDs from items
 return isInArray(ids, itemid)
end

function sendEffect(pos, time)
    if time < 0 then
        return true
    end
    doSendMagicEffect(pos, arrow[1])
    addEvent(sendEffect, 1000, pos, time - 1)
end
local function func(cid, position, corpseid, effect)
    print(1)
    if not isCreature(cid) then return true end
    local corpse = getTileItemById(position, corpseid).uid
    if corpse <= 1 then return end
    if not isContainer(corpse) then return true end
    for slot = 0, (getContainerSize(corpse)-1) do
        local item = getContainerItem(corpse, slot)
        if item.uid <= 1 then return end
        if isRare(item.itemid) then
            print(2)
            return doSendMagicEffect(position, effect)
        end
    end
end
function onKill(cid, target, lastHit)

    print(0)
    if not isMonster(target) then return true end
    local corpse = getMonsterInfo(getCreatureName(target)).lookCorpse

    addEvent(func, 5, getCreatureSummons(cid)[1], getThingPos(target), corpse, effect)
    return true
end
 
Solution
Lua:
local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 5

local function countdown(pos, timer)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 6500, pos, timer - 1)
end

local function scanContainer(uid, pos)
    for i = getContainerSize(uid) - 1, 0, -1 do
        local item = getContainerItem(uid, i)
        if isContainer(item.uid) then
            scanContainer(item.uid, pos)
        else
            if isInArray(rare_items, item.itemid) then
                doSendMagicEffect(pos, effect)
                addEvent(countdown, 6500, pos, timer)
            end
        end
    end
end

local function scanCorpse(pos, corpseId)
    local corpse =...
Little bug. Look bro, the item 5897 is the wolf paw, when a wolf drops 1 wolf paw, don't show the effect, only if have other corpse inside of which drops the wolf paw. (you need kill other wolf on the same position of the corpse who drop the item to show the effect)

Give this a try;
Lua:
function countdown(pos, timer, effect)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 1000, pos, timer - 1, effect)
end

local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 60

function onKill(cid, target, corpse, lastHit)
    local idc, pos = getMonsterInfo(getCreatureName(target)).lookCorpse, getCreaturePosition(target)
    local corpse = getTileItemById(pos, idc).uid

    if isMonster(target) then
        if isContainer(corpse) then
            for i = getContainerSize(corpse)-1, 0, -1 do
                local containerItem = getContainerItem(corpse, i)
                if isContainer(containerItem) then
                    for i = getContainerSize(containerItem)-1, 0, -1 do
                        if isInArray(rare_items, getContainerItem(corpse, i).itemid) then
                            doSendMagicEffect(pos, effect)
                            addEvent(countdown, 1000, pos, timer, effect)
                            return true
                        end
                    end
                elseif isInArray(rare_items, containerItem.itemid) then
                    doSendMagicEffect(pos, effect)
                    addEvent(countdown, 1000, pos, timer, effect)
                    return true
                end
            end
        end
    end
    return true
end
 
if anyone is interested I wrote this for TFS 1.x but you can set what loot rate to notify players
Lua:
local effect = CONST_ME_TUTORIALARROW -- magic effect
local chance = 5 -- magic effect for item that drops less than 5% of the time

function onLogin(player)
    player:registerEvent('rarelootkill')
    return true
end

function onKill(player, target)
    if target:isMonster() then target:registerEvent('rarelootdeath') end
    return true
end

function getContainerItemIds(container)
    t = {}
    if not container then return t end
    if not container:getSize() then return t end
    for i = container:getSize()-1, 1, -1 do
        table.insert(t,container:getItem(i):getId())
    end
    return t
end

function hasItemById(container,itemid)
    if not itemid or not container then return false end
    if isInArray(getContainerItemIds(container),itemid) then return true end
    return false
end

function onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    if not creature then return true end
    local loot = creature:getType():getLoot()
    if not loot then return true end
    local totalchance = 0
    for i, k in pairs(loot) do
        totalchance = totalchance + k.chance
    end
    addEvent(function()
        for i, k in pairs(loot) do
            if not corpse or not killer then
                return
            end
            if hasItemById(corpse,k.itemId) and k.chance/totalchance < chance/100  then
                corpse:getPosition():sendMagicEffect(effect)
                killer:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You looted a "..ItemType(k.itemId):getName().."!")
            end
        end
    end,1)
    return true
end
XML:
    <event type="login" name="rarelootlogin" script="loot.lua" />
    <event type="kill" name="rarelootkill" script="loot.lua" />
    <event type="death" name="rarelootdeath" script="loot.lua" />
not extensively tested, be careful
 
Last edited:
Give this a try;
Lua:
function countdown(pos, timer, effect)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 1000, pos, timer - 1, effect)
end

local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 60

function onKill(cid, target, corpse, lastHit)
    local idc, pos = getMonsterInfo(getCreatureName(target)).lookCorpse, getCreaturePosition(target)
    local corpse = getTileItemById(pos, idc).uid

    if isMonster(target) then
        if isContainer(corpse) then
            for i = getContainerSize(corpse)-1, 0, -1 do
                local containerItem = getContainerItem(corpse, i)
                if isContainer(containerItem) then
                    for i = getContainerSize(containerItem)-1, 0, -1 do
                        if isInArray(rare_items, getContainerItem(corpse, i).itemid) then
                            doSendMagicEffect(pos, effect)
                            addEvent(countdown, 1000, pos, timer, effect)
                            return true
                        end
                    end
                elseif isInArray(rare_items, containerItem.itemid) then
                    doSendMagicEffect(pos, effect)
                    addEvent(countdown, 1000, pos, timer, effect)
                    return true
                end
            end
        end
    end
    return true
end
The same problem of the corpse, need other inside of who drops the item
 
But what? Do you have bags inside of bags?
This will check the corpse itself, if it has a container in the corpse it will check that aswell.
If i kill a wolf than drops a wolf paw, don't show any effect, but i kill other wolf on the same position of the wolf than drops a Wolf paw, it will show the effect, its a bug. :/
 
But what? Do you have bags inside of bags?
This will check the corpse itself, if it has a container in the corpse it will check that aswell.

I think he meant that there's no corpse when onKill is executed. Therefore if another monster dies on the same tile, the old corpse is taken into account, but the latest corpse is not there yet in onKill handler. Any chance there's a bug there?? Likee, the corpse is there only if player is killed, but for monsters onKill is executed before loot is generated and thus no corpse exists at the time of onKill event?
 
I think he meant that there's no corpse when onKill is executed. Therefore if another monster dies on the same tile, the old corpse is taken into account, but the latest corpse is not there yet in onKill handler. Any chance there's a bug there?? Likee, the corpse is there only if player is killed, but for monsters onKill is executed before loot is generated and thus no corpse exists at the time of onKill event?
Yes, another monster need dies on the same tile for the script be executed. Bump
 
Try using onDeath, that should be executed after the corpse has been added to the game; tfs-old-svn/creatureevent.cpp at 1b7500bb947de1827c39174b05c31fea92c10240 · otland/tfs-old-svn · GitHub

Guys a little video of the bug. The first respawn drops somes wolf paws, i need kill other respawn on the same tile from who drops (x1 respawn) to got the effect. :/

Script:
Lua:
function countdown(pos, timer, effect)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 6500, pos, timer - 1, effect)
end

local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 5

function onKill(cid, target, corpse, lastHit)
    local idc, pos = getMonsterInfo(getCreatureName(target)).lookCorpse, getCreaturePosition(target)
    local corpse = getTileItemById(pos, idc).uid

    if isMonster(target) then
        if isContainer(corpse) then
            for i = getContainerSize(corpse)-1, 0, -1 do
                local containerItem = getContainerItem(corpse, i)
                if isContainer(containerItem) then
                    for b = getContainerSize(containerItem)-1, 0, -1 do
                        if isInArray(rare_items, getContainerItem(corpse, b).itemid) then
                            doSendMagicEffect(pos, effect)
                            addEvent(countdown, 6500, pos, timer, effect)
                            return true
                        end
                    end
                elseif isInArray(rare_items, containerItem.itemid) then
                    doSendMagicEffect(pos, effect)
                    addEvent(countdown, 6500, pos, timer, effect)
                    return true
                end
            end
        end
    end
    return true
end
 
Lua:
local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 5

local function countdown(pos, timer)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 6500, pos, timer - 1)
end

local function scanContainer(uid, pos)
    for i = getContainerSize(uid) - 1, 0, -1 do
        local item = getContainerItem(uid, i)
        if isContainer(item.uid) then
            scanContainer(item.uid, pos)
        else
            if isInArray(rare_items, item.itemid) then
                doSendMagicEffect(pos, effect)
                addEvent(countdown, 6500, pos, timer)
            end
        end
    end
end

local function scanCorpse(pos, corpseId)
    local corpse = getTileItemById(pos, corpseId)
    if not corpse then
        return
    end
    if not isContainer(corpse.uid) then
        return
    end
    scanContainer(corpse.uid, pos)
end

function onKill(cid, target, corpse, lastHit)
    if isPlayer(target) then
        return true
    end
    local corpseId = getMonsterInfo(getCreatureName(target)).lookCorpse
    local pos = getCreaturePosition(target)
    addEvent(scanCorpse, 1, pos, corpseId)
    return true
end
 
Last edited:
Solution
Lua:
local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 5

local function countdown(pos, timer)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 6500, pos, timer - 1)
end

local function scanContainer(uid, pos)
    for i = getContainerSize(uid) - 1, 0, -1 do
        local item = getContainerItem(uid, i)
        if isContainer(item.uid) then
            scanContainer(item.uid, pos)
        else
            if isInArray(rare_items, item.itemid) then
                doSendMagicEffect(pos, effect)
                addEvent(countdown, 6500, pos, timer)
            end
        end
    end
end

local function scanCorpse(pos, corpseId)
    local corpse = getTileItemById(pos, corpseId)
    if not corpse then
        return
    end
    if not isContainer(corpse.uid) then
        return
    end
    scanContainer(corpse.uid, pos)
end

function onKill(cid, target, corpse, lastHit)
    local corpseId = getMonsterInfo(getCreatureName(target)).lookCorpse
    local pos = getCreaturePosition(target)
    if not isMonster(target) then
        return
    end
    addEvent(scanCorpse, 1, pos, corpseId)
    return true
end
Solved! Thank you guys! specially Xeraphus ^^
 
Last edited:
I found a bug, when you kill another player on the console:
/bluearrow.lua:eek:nKill
Description:
/bluearrow.lua:43: attempt to index a boolean value stack traceback:
Monster not found.
 
Lua:
local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 5

local function countdown(pos, timer)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 6500, pos, timer - 1)
end

local function scanContainer(uid, pos)
    for i = getContainerSize(uid) - 1, 0, -1 do
        local item = getContainerItem(uid, i)
        if isContainer(item.uid) then
            scanContainer(item.uid, pos)
        else
            if isInArray(rare_items, item.itemid) then
                doSendMagicEffect(pos, effect)
                addEvent(countdown, 6500, pos, timer)
            end
        end
    end
end

local function scanCorpse(pos, corpseId)
    local corpse = getTileItemById(pos, corpseId)
    if not corpse then
        return
    end
    if not isContainer(corpse.uid) then
        return
    end
    scanContainer(corpse.uid, pos)
end

function onKill(cid, target, corpse, lastHit)
    if not isMonster(target) then
        return
    end
    local corpseId = getMonsterInfo(getCreatureName(target)).lookCorpse
    local pos = getCreaturePosition(target)
    addEvent(scanCorpse, 1, pos, corpseId)
    return true
end
 
Lua:
local rare_items = {5897}
local effect = CONST_ME_TUTORIALARROW
local timer = 5

local function countdown(pos, timer)
    if timer < 0 then
        return true
    end
    doSendMagicEffect(pos, effect)
    addEvent(countdown, 6500, pos, timer - 1)
end

local function scanContainer(uid, pos)
    for i = getContainerSize(uid) - 1, 0, -1 do
        local item = getContainerItem(uid, i)
        if isContainer(item.uid) then
            scanContainer(item.uid, pos)
        else
            if isInArray(rare_items, item.itemid) then
                doSendMagicEffect(pos, effect)
                addEvent(countdown, 6500, pos, timer)
            end
        end
    end
end

local function scanCorpse(pos, corpseId)
    local corpse = getTileItemById(pos, corpseId)
    if not corpse then
        return
    end
    if not isContainer(corpse.uid) then
        return
    end
    scanContainer(corpse.uid, pos)
end

function onKill(cid, target, corpse, lastHit)
    if not isMonster(target) then
        return
    end
    local corpseId = getMonsterInfo(getCreatureName(target)).lookCorpse
    local pos = getCreaturePosition(target)
    addEvent(scanCorpse, 1, pos, corpseId)
    return true
end
Same problem, the player doesn't dead only 0 of life.
@Static_ Maybe you can fix it bro, you make the script, thank you in advance guys.
 
Same problem, the player doesn't dead only 0 of life.
@Static_ Maybe you can fix it bro, you make the script, thank you in advance guys.
1. dont tag me
2. ill be nice anyways and help
does this only happen on specific monsters? if so then you need to have the monster name from the actual monster xml the same as the one in monsters.xml
for example name="Demon" in demon.xml has to be name="Demon" in monsters.xml
 
1. dont tag me
2. ill be nice anyways and help
does this only happen on specific monsters? if so then you need to have the monster name from the actual monster xml the same as the one in monsters.xml
for example name="Demon" in demon.xml has to be name="Demon" in monsters.xml
Sorry. Well bro, its happens when one player attack other player. With monster it works.

@Edit: I fix it, thanks anyway. On the function onKill
Lua:
function onKill(cid, target, corpse, lastHit)
   if isMonster(target) then
    local corpseId = getMonsterInfo(getCreatureName(target)).lookCorpse
    local pos = getCreaturePosition(target)
    addEvent(scanCorpse, 1, pos, corpseId)
    else
    return 0
end
    return true
 end
 
Last edited:
Sorry. Well bro, its happens when one player attack other player. With monster it works.

@Edit: I fix it, thanks anyway. On the function onKill
Lua:
function onKill(cid, target, corpse, lastHit)
   if isMonster(target) then
    local corpseId = getMonsterInfo(getCreatureName(target)).lookCorpse
    local pos = getCreaturePosition(target)
    addEvent(scanCorpse, 1, pos, corpseId)
    else
    return 0
end
    return true
 end
edited the code in the best answer post
 
if anyone is interested I wrote this for TFS 1.x but you can set what loot rate to notify players
Lua:
local effect = CONST_ME_TUTORIALARROW -- magic effect
local chance = 5 -- magic effect for item that drops less than 5% of the time

function onLogin(player)
    player:registerEvent('rarelootkill')
    return true
end

function onKill(player, target)
    if target:isMonster() then target:registerEvent('rarelootdeath') end
    return true
end

function getContainerItemIds(container)
    t = {}
    if not container then return t end
    if not container:getSize() then return t end
    for i = container:getSize()-1, 1, -1 do
        table.insert(t,container:getItem(i):getId())
    end
    return t
end

function hasItemById(container,itemid)
    if not itemid or not container then return false end
    if isInArray(getContainerItemIds(container),itemid) then return true end
    return false
end

function onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    if not creature then return true end
    local loot = creature:getType():getLoot()
    if not loot then return true end
    local totalchance = 0
    for i, k in pairs(loot) do
        totalchance = totalchance + k.chance
    end
    addEvent(function()
        for i, k in pairs(loot) do
            if not corpse or not killer then
                return
            end
            if hasItemById(corpse,k.itemId) and k.chance/totalchance < chance/100  then
                corpse:getPosition():sendMagicEffect(effect)
                killer:sendTextMessage(MESSAGE_STATUS_DEFAULT, "You looted a "..ItemType(k.itemId):getName().."!")
            end
        end
    end,1)
    return true
end
XML:
    <event type="login" name="rarelootlogin" script="loot.lua" />
    <event type="kill" name="rarelootkill" script="loot.lua" />
    <event type="death" name="rarelootdeath" script="loot.lua" />
not extensively tested, be careful

How do I adapt this code to increase the effect time for 5s?
Besides that. How do I make the code work only if I drop some item that is allocated to rare_items = {5897, 5888, 5821}

Can someone help me?
 
Back
Top