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

CreatureEvent [TFS 0.4] onLook/onKill: Item from looking at monster

Infernum

Senator
Joined
Feb 14, 2015
Messages
5,643
Solutions
559
Reaction score
3,949
This script will spawn a 2nd monster if the 1st monster is killed. Once the 2nd monster is spawned, you have 5 seconds (default) to look at it and get your item, or else it disappears.

You may configure what monsters to kill & summon, the time to disappear, effects, amount of item given, and the item id itself.

Note: the monster you want to summon's name is case sensitive.
Code:
<event type="look" name="lootlook" event="script" value="loot.lua"/>
<event type="kill" name="lootkill" event="script" value="loot.lua"/>

Code:
registerCreatureEvent(cid, "lootlook")
registerCreatureEvent(cid, "lootkill")

Code:
-- Effects in this table are used for looking at the monster --

local t = {
['rotworm'] = {Summon = 'Trainer', Time = 5, ID = 2160, Min = 1, Max = 100, Color = TEXTCOLOR_LIGHTBLUE, Effect = CONST_ME_MAGIC_BLUE},
['cat'] = {Summon = 'Wolf', Time = 5, ID = 10571, Min = 1, Max = 100, Color = TEXTCOLOR_YELLOW, Effect = CONST_ME_STUN}
}

function onKill(cid, target, damage, flags)
local p = getThingPos(target)
local r = {x=p.x, y=p.y, z=p.z, stackpos = 253}

function sendCountdown(n, pos, startEffect, startEffect2, randEffect, color)
if n == 1 then
    doSendMagicEffect(pos, startEffect)
    doSendMagicEffect(pos, startEffect2)
    doSendAnimatedText(pos, '5', color)
    doSendMagicEffect(pos, randEffect)
elseif n == 2 then
    doSendAnimatedText(pos, '4', color)
    doSendMagicEffect(pos, randEffect)
elseif n == 3 then
    doSendAnimatedText(pos, '3', color)
    doSendMagicEffect(pos, randEffect)
elseif n == 4 then
    doSendAnimatedText(pos, '2', color)
    doSendMagicEffect(pos, randEffect)
elseif n == 5 then
    doSendAnimatedText(pos, '1', color)
    doSendMagicEffect(pos, randEffect)
    end
end

function removeCreature(cid, pos)
    if cid then
        doTeleportThing(cid, getClosestFreeTile(cid, getCreaturePosition(cid), false, true))
    end
    if isMonster(getThingfromPos(pos).uid) then
        doSendMagicEffect(pos, CONST_ME_POFF)
        doRemoveCreature(getThingfromPos(pos).uid)
    end
end

-- Spawn creature --
for k,v in pairs(t) do
    if k == getCreatureName(target):lower() then
        doSendMagicEffect(p, CONST_ME_FIREATTACK)
        doCreateMonster(v.Summon, p, false, true)
        addEvent(removeCreature, v.Time*1000, cid, r)
            for i = 1, 5 do
                addEvent(sendCountdown, i * 1000, i, r, 55, 56, math.random(1,32) or math.random(34,54), 180)
            end
        end
    end
return true
end


function onLook(cid, thing, position, lookDistance)
-- Remove creature & give item when looked at -- 
for k,v in pairs(t) do
local amount = math.random(v.Min, v.Max)
    if isMonster(thing.uid) then
            if v.Summon == getCreatureName(thing.uid):lower() or v.Summon == getCreatureName(thing.uid) then
                doSendMagicEffect(position, v.Effect)
                if isItemStackable(v.ID) then
                    if getItemPluralNameById(v.ID) then
                        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. amount ..'] '.. getItemPluralNameById(v.ID) ..' collected.')
                        doSendAnimatedText(position, '+ '.. amount ..'', v.Color)
                        doRemoveCreature(thing.uid, true)
                        doPlayerGiveItem(cid, v.ID, amount)
                    elseif getItemPluralNameById(v.ID) == false then
                        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. amount ..'] '.. getItemNameById(v.ID) ..' collected.')
                        doSendAnimatedText(position, '+ '.. amount ..'', v.Color)
                        doRemoveCreature(thing.uid, true)
                        doPlayerGiveItem(cid, v.ID, amount)
                    end
                end
                if isItemStackable(v.ID) == false then
                    doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, ''.. getItemNameById(v.ID) ..' collected.')
                    doRemoveCreature(thing.uid, true)
                    doPlayerGiveItem(cid, v.ID, 1)
                end
                return false
            end
        end
    end
    return true
end
 
Last edited:
hardcoding config to 1 itemid/creature/amount isnt really a "good" way to go about it, much better to just make it a table with everything at the creature names position, then you can easily add more

also if someone gets on top of the summoned creature they will be removed instead of the creature when you dont send the cid to removecreature, but rather position
 
Last edited:
You're right about the amount, since it only uses one amount when you load in the script, which I forgot about.
For itemid and creatures, I don't know why that would be bad, but okay.
How would someone get on top of the summoned creature? You can't walk inside monsters.
 
custom spells that move ppl, getting summon under/above a floor change etc, passing the cid solves that issue completely

with the code right now you can only use this for 1 creature, what if you want both rats and caverats to drop stuff, rats gold coins, cave rats platinums? it would need quite a bit of changing, while you could just have a dynamic function that checks a table so you can easily add more creatures, and also more loot (maybe you want both gold & plats from a monster, etc)
 
Editing script now to make it easier to add new items/monsters.

EDIT: What do you exactly mean by passing cid?
 
Code:
function removeCreature(cid)
if cid then
effect(cid:pos)
removeCreature(cid)
end
end
m = doCreatreMonster(...)
addEvent(removeCreature, time, m)
something along those lines, so you use uid/cid for the creature to remove it, instead of getting the creature from pos
then you could go as far as to remove if cid then check and instead use something liek
Code:
events[cid] = addEvent(removeCreature, time, m)
onLook
if valid then
loot
stopEvent(events[cid])
end
 
Code:
function removeCreature(cid)
if cid then
effect(cid:pos)
removeCreature(cid)
end
end
m = doCreatreMonster(...)
addEvent(removeCreature, time, m)
something along those lines, so you use uid/cid for the creature to remove it, instead of getting the creature from pos
then you could go as far as to remove if cid then check and instead use something liek
Code:
events[cid] = addEvent(removeCreature, time, m)
onLook
if valid then
loot
stopEvent(events[cid])
end
I fixed the script, made the user able to configure multiple monsters, ids, amount etc.
Also I made removeCreature check cid, and if true it would move cid to closest free tile, then removes the creature :)
 
i have a couple more suggestions, such as changing tables to this format to remove the need to loop through table to find the right monster for better performance
Code:
table = {
["rat"] = {...},
["rotworm"] = {...},
}
there are a few more things i would say to change, but enough complaining from me, ill take a look at the script sometime tonight and ill return with it when im done :)
 
i have a couple more suggestions, such as changing tables to this format to remove the need to loop through table to find the right monster for better performance
Code:
table = {
["rat"] = {...},
["rotworm"] = {...},
}
there are a few more things i would say to change, but enough complaining from me, ill take a look at the script sometime tonight and ill return with it when im done :)
I'd actually appreciate your 'complaining', it helps me know what to do and get more experience with scripting.
Thanks :)
 
i have a couple more suggestions, such as changing tables to this format to remove the need to loop through table to find the right monster for better performance
Code:
table = {
["rat"] = {...},
["rotworm"] = {...},
}
there are a few more things i would say to change, but enough complaining from me, ill take a look at the script sometime tonight and ill return with it when im done :)
Edited script in 1st post, changed [1],[2] into the monster names.
Is that what you meant?
 
yeah, doing the table that way you can just do
Code:
local tmp = table[string.lower(getCreatureName(target))]
if tmp then
bla
end
to remove the need for looping through the table on every monster kill (which would be very bad especially if the loot table is big, going through it every monster kill :p)

if this was 1.x you wouldnt neeed to move anything, you could just get thing from pos by name and find it that way onLook which would be super simple, but there are ways to work around that in 0.x, but i think its easier if i write it instead of trying to explain how :p
 
yeah, doing the table that way you can just do
Code:
local tmp = table[string.lower(getCreatureName(target))]
if tmp then
bla
end
to remove the need for looping through the table on every monster kill (which would be very bad especially if the loot table is big, going through it every monster kill :p)

if this was 1.x you wouldnt neeed to move anything, you could just get thing from pos by name and find it that way onLook which would be super simple, but there are ways to work around that in 0.x, but i think its easier if i write it instead of trying to explain how :p
I'm gonna keep it the way it is, since if i use tmp method for onKill, it will spawn all Summon monsters.
Dunno how to fix that :( brain hurts
 
Sweet! I'm going to convert this to 1.2.
you dont need to, im gonna fix some things with the code and optimize it a bit, might aswell make it for 1.2 aswell while i do it since its almost no difference :)

im busy tomorrow though so i wont get around to doing it until sunday though
 
you dont need to, im gonna fix some things with the code and optimize it a bit, might aswell make it for 1.2 aswell while i do it since its almost no difference :)

im busy tomorrow though so i wont get around to doing it until sunday though
Sharing is caring :p
 
loot.lua
monsters are added like the already made ones, loot is added in the form of
{{id = x, amount = y}, {id = x, amount = y}} etc, each item id needs 1 table with id and amount values, amount can either be a number, of a table of {minValue, maxValue} for how much to get of it
Code:
-- Effects in this table are used for looking at the monster --
---compat-100.lua
bonusSummons = {}
-----------------

--loot.lua
local monsters = {
['rotworm'] = {Summon = 'Wolf', Time = 5, loot = {{id = 2160, amount = {1, 100}}}, Color = TEXTCOLOR_LIGHTBLUE, Effect = CONST_ME_MAGIC_BLUE},
['cat'] = {Summon = 'Wolf', Time = 5, loot = {{id = 10571, amount = 1}}, Color = TEXTCOLOR_YELLOW, Effect = CONST_ME_STUN}
}

local despawnTime = 5000

function sendCountdown(cid, n, pos, startEffect, startEffect2, randEffect, color)
    if isMonster(cid) then
        if n >= 0 then
            if n == (despawnTime/1000) then
                doSendMagicEffect(pos, startEffect)
                doSendMagicEffect(pos, startEffect2)
            end
            doSendAnimatedText(pos, n, 180)
            doSendMagicEffect(pos, math.random(randEffect))
            addEvent(sendCountdown, 1000, cid, n-1, pos, startEffect, startEffect2, randEffect, color)
        end
    end
    return
end

local function removeCreature(cid)
    if isMonster(cid) then
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
        doRemoveCreature(cid)
        bonusSummons[cid] = nil
    end
end

function onKill(cid, target, damage, flags)
    local p = getThingPos(target)
    local name = getCreatureName(target):lower()
    local mon = monsters[name]
    if mon then
        doSendMagicEffect(p, CONST_ME_FIREATTACK)
        monster = doCreateMonster(mon.Summon, p)
        bonusSummons[monster] = name
        addEvent(removeCreature, despawnTime, monster)
        sendCountdown(monster, despawnTime/1000, getCreaturePosition(monster), 55, 56, 54, 180)
    end
    return true
  
end

local function giveLoot(cid, t, color, position)
    for i=1,#t,1 do
        local amount = t[i].amount
        local id = t[i].id
        if type(amount) == type({}) then
            local rand = math.random(t[i].amount[1], t[i].amount[2])
            doPlayerGiveItem(cid, id, rand)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. rand ..'] '.. getItemPluralNameById(id) ..' collected.')
            doSendAnimatedText(position, '+ '.. rand ..'', color)
        else
            doPlayerGiveItem(cid, id, amount)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. amount ..'] '.. getItemPluralNameById(id) ..' collected.')
            doSendAnimatedText(position, '+ '.. amount ..'', color)
        end
    end
    return
end

function onLook(cid, thing, position, lookDistance)
    local tab = bonusSummons[thing.uid]
    if isMonster(thing.uid) and tab then  
        doSendMagicEffect(position, monsters[tab].Effect)
        giveLoot(cid, monsters[tab].loot, monsters[tab].Color, position)
        removeCreature(thing.uid)
        bonusSummons[thing.uid] = nil
    end
    return true
end
compat-100.lua
Code:
bonusSummons = {}
reworked it for 0.x now, from my testing it works like intended
so i changed it around a little bit, now it doesnt loop through any table except the loot table (incase you want several items per look etc)
i changed sendCountdown to more of a generic function, it now depends on despawnTime variable for how long the effects show, no need to do anything other than change despawnTime to make it show more effects, it also checks if the loot creature the effect spawned together with actually still exists (so effects doesnt show after you take loot etc)

i changed onkill so it fetches the table directly from the key with the killed monsters name instead of doing a loop, when creating the monster i also do
monster = doCreateMonster(...) which returns the CID of the spawned creature, and then i send that cid to sendCountdown for example so it can check if it still exists..
i also use that returned CID and do
bonusSummons[monster] = name
so at CID key in bonusSummons the name of the monster is saved (so when you look at it, it gets the loot data from monsters table easily with monsters[bonusSummons[cid]]
i added giveLoot as an extra function, just because i made it so tables of loot are allowed in monsters, so you can give several items etc.. without this and just 1 item and random amount code would be -20 lines :p
since i save the monster in bonusSummons at CID key, i can just simply do bonusSummons[thing.uid] on look and check if that position still exists, which removes the need to loop throug monsters table to find if its a valid loot summon (and you cant look at any other random monster with the same name as bonus loot summon since that one wont exist in bonusSummons[].

i dont think i have time to convert it to 1.x for a couple of days, so @Jeffro if you still want to do it go ahead, i dont think i will change this code :p
 
loot.lua
monsters are added like the already made ones, loot is added in the form of
{{id = x, amount = y}, {id = x, amount = y}} etc, each item id needs 1 table with id and amount values, amount can either be a number, of a table of {minValue, maxValue} for how much to get of it
Code:
-- Effects in this table are used for looking at the monster --
---compat-100.lua
bonusSummons = {}
-----------------

--loot.lua
local monsters = {
['rotworm'] = {Summon = 'Wolf', Time = 5, loot = {{id = 2160, amount = {1, 100}}}, Color = TEXTCOLOR_LIGHTBLUE, Effect = CONST_ME_MAGIC_BLUE},
['cat'] = {Summon = 'Wolf', Time = 5, loot = {{id = 10571, amount = 1}}, Color = TEXTCOLOR_YELLOW, Effect = CONST_ME_STUN}
}

local despawnTime = 5000

function sendCountdown(cid, n, pos, startEffect, startEffect2, randEffect, color)
    if isMonster(cid) then
        if n >= 0 then
            if n == (despawnTime/1000) then
                doSendMagicEffect(pos, startEffect)
                doSendMagicEffect(pos, startEffect2)
            end
            doSendAnimatedText(pos, n, 180)
            doSendMagicEffect(pos, math.random(randEffect))
            addEvent(sendCountdown, 1000, cid, n-1, pos, startEffect, startEffect2, randEffect, color)
        end
    end
    return
end

local function removeCreature(cid)
    if isMonster(cid) then
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
        doRemoveCreature(cid)
        bonusSummons[cid] = nil
    end
end

function onKill(cid, target, damage, flags)
    local p = getThingPos(target)
    local name = getCreatureName(target):lower()
    local mon = monsters[name]
    if mon then
        doSendMagicEffect(p, CONST_ME_FIREATTACK)
        monster = doCreateMonster(mon.Summon, p)
        bonusSummons[monster] = name
        addEvent(removeCreature, despawnTime, monster)
        sendCountdown(monster, despawnTime/1000, getCreaturePosition(monster), 55, 56, 54, 180)
    end
    return true
 
end

local function giveLoot(cid, t, color, position)
    for i=1,#t,1 do
        local amount = t[i].amount
        local id = t[i].id
        if type(amount) == type({}) then
            local rand = math.random(t[i].amount[1], t[i].amount[2])
            doPlayerGiveItem(cid, id, rand)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. rand ..'] '.. getItemPluralNameById(id) ..' collected.')
            doSendAnimatedText(position, '+ '.. rand ..'', color)
        else
            doPlayerGiveItem(cid, id, amount)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. amount ..'] '.. getItemPluralNameById(id) ..' collected.')
            doSendAnimatedText(position, '+ '.. amount ..'', color)
        end
    end
    return
end

function onLook(cid, thing, position, lookDistance)
    local tab = bonusSummons[thing.uid]
    if isMonster(thing.uid) and tab then 
        doSendMagicEffect(position, monsters[tab].Effect)
        giveLoot(cid, monsters[tab].loot, monsters[tab].Color, position)
        removeCreature(thing.uid)
        bonusSummons[thing.uid] = nil
    end
    return true
end
compat-100.lua
Code:
bonusSummons = {}
reworked it for 0.x now, from my testing it works like intended
so i changed it around a little bit, now it doesnt loop through any table except the loot table (incase you want several items per look etc)
i changed sendCountdown to more of a generic function, it now depends on despawnTime variable for how long the effects show, no need to do anything other than change despawnTime to make it show more effects, it also checks if the loot creature the effect spawned together with actually still exists (so effects doesnt show after you take loot etc)

i changed onkill so it fetches the table directly from the key with the killed monsters name instead of doing a loop, when creating the monster i also do
monster = doCreateMonster(...) which returns the CID of the spawned creature, and then i send that cid to sendCountdown for example so it can check if it still exists..
i also use that returned CID and do
bonusSummons[monster] = name
so at CID key in bonusSummons the name of the monster is saved (so when you look at it, it gets the loot data from monsters table easily with monsters[bonusSummons[cid]]
i added giveLoot as an extra function, just because i made it so tables of loot are allowed in monsters, so you can give several items etc.. without this and just 1 item and random amount code would be -20 lines :p
since i save the monster in bonusSummons at CID key, i can just simply do bonusSummons[thing.uid] on look and check if that position still exists, which removes the need to loop throug monsters table to find if its a valid loot summon (and you cant look at any other random monster with the same name as bonus loot summon since that one wont exist in bonusSummons[].

i dont think i have time to convert it to 1.x for a couple of days, so @Jeffro if you still want to do it go ahead, i dont think i will change this code :p
Looks cool :)
 
loot.lua
monsters are added like the already made ones, loot is added in the form of
{{id = x, amount = y}, {id = x, amount = y}} etc, each item id needs 1 table with id and amount values, amount can either be a number, of a table of {minValue, maxValue} for how much to get of it
Code:
-- Effects in this table are used for looking at the monster --
---compat-100.lua
bonusSummons = {}
-----------------

--loot.lua
local monsters = {
['rotworm'] = {Summon = 'Wolf', Time = 5, loot = {{id = 2160, amount = {1, 100}}}, Color = TEXTCOLOR_LIGHTBLUE, Effect = CONST_ME_MAGIC_BLUE},
['cat'] = {Summon = 'Wolf', Time = 5, loot = {{id = 10571, amount = 1}}, Color = TEXTCOLOR_YELLOW, Effect = CONST_ME_STUN}
}

local despawnTime = 5000

function sendCountdown(cid, n, pos, startEffect, startEffect2, randEffect, color)
    if isMonster(cid) then
        if n >= 0 then
            if n == (despawnTime/1000) then
                doSendMagicEffect(pos, startEffect)
                doSendMagicEffect(pos, startEffect2)
            end
            doSendAnimatedText(pos, n, 180)
            doSendMagicEffect(pos, math.random(randEffect))
            addEvent(sendCountdown, 1000, cid, n-1, pos, startEffect, startEffect2, randEffect, color)
        end
    end
    return
end

local function removeCreature(cid)
    if isMonster(cid) then
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
        doRemoveCreature(cid)
        bonusSummons[cid] = nil
    end
end

function onKill(cid, target, damage, flags)
    local p = getThingPos(target)
    local name = getCreatureName(target):lower()
    local mon = monsters[name]
    if mon then
        doSendMagicEffect(p, CONST_ME_FIREATTACK)
        monster = doCreateMonster(mon.Summon, p)
        bonusSummons[monster] = name
        addEvent(removeCreature, despawnTime, monster)
        sendCountdown(monster, despawnTime/1000, getCreaturePosition(monster), 55, 56, 54, 180)
    end
    return true
 
end

local function giveLoot(cid, t, color, position)
    for i=1,#t,1 do
        local amount = t[i].amount
        local id = t[i].id
        if type(amount) == type({}) then
            local rand = math.random(t[i].amount[1], t[i].amount[2])
            doPlayerGiveItem(cid, id, rand)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. rand ..'] '.. getItemPluralNameById(id) ..' collected.')
            doSendAnimatedText(position, '+ '.. rand ..'', color)
        else
            doPlayerGiveItem(cid, id, amount)
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, '['.. amount ..'] '.. getItemPluralNameById(id) ..' collected.')
            doSendAnimatedText(position, '+ '.. amount ..'', color)
        end
    end
    return
end

function onLook(cid, thing, position, lookDistance)
    local tab = bonusSummons[thing.uid]
    if isMonster(thing.uid) and tab then 
        doSendMagicEffect(position, monsters[tab].Effect)
        giveLoot(cid, monsters[tab].loot, monsters[tab].Color, position)
        removeCreature(thing.uid)
        bonusSummons[thing.uid] = nil
    end
    return true
end
compat-100.lua
Code:
bonusSummons = {}
reworked it for 0.x now, from my testing it works like intended
so i changed it around a little bit, now it doesnt loop through any table except the loot table (incase you want several items per look etc)
i changed sendCountdown to more of a generic function, it now depends on despawnTime variable for how long the effects show, no need to do anything other than change despawnTime to make it show more effects, it also checks if the loot creature the effect spawned together with actually still exists (so effects doesnt show after you take loot etc)

i changed onkill so it fetches the table directly from the key with the killed monsters name instead of doing a loop, when creating the monster i also do
monster = doCreateMonster(...) which returns the CID of the spawned creature, and then i send that cid to sendCountdown for example so it can check if it still exists..
i also use that returned CID and do
bonusSummons[monster] = name
so at CID key in bonusSummons the name of the monster is saved (so when you look at it, it gets the loot data from monsters table easily with monsters[bonusSummons[cid]]
i added giveLoot as an extra function, just because i made it so tables of loot are allowed in monsters, so you can give several items etc.. without this and just 1 item and random amount code would be -20 lines :p
since i save the monster in bonusSummons at CID key, i can just simply do bonusSummons[thing.uid] on look and check if that position still exists, which removes the need to loop throug monsters table to find if its a valid loot summon (and you cant look at any other random monster with the same name as bonus loot summon since that one wont exist in bonusSummons[].

i dont think i have time to convert it to 1.x for a couple of days, so @Jeffro if you still want to do it go ahead, i dont think i will change this code :p

Will be using this! Thank you<3 Beautiful work
 
Back
Top