• 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 onKill teleport all spectators

Lava Titan

Developer
Joined
Jul 25, 2009
Messages
1,551
Solutions
1
Reaction score
88
Location
Portugal
Hello, I wrote this, I thought it was working fine until I noticed it's executing all config at same time instead of execute only the part related to the monster killed...

Can some1 have a look and tell me what I got wrong?
(If possible post an example how to correct please)

Code:
--[[ Config]]--
local monsters = {
    [1] = {
        name = "Demon",
        tpFrom = {x = 4639, y = 4973, z = 4},
        tpTo = {x = 4647, y = 4991, z = 4},
        msg = "Test Msg 1",
        msgPos = {x = 4638, y = 4968, z = 4},
    },
    [2] = {
        name = "Rotworm",
        tpFrom = {x = 4639, y = 4973, z = 4},
        tpTo = {x = 4647, y = 4991, z = 4},
        msg = "Test Msg 2",
        msgPos = {x = 4638, y = 4968, z = 4},
    }
}

--<< Script Start >>--
function onKill(creature, target)
    if target:isPlayer(target) then
        print("Error..")
    return true
    end

    for i = 1, #monsters do
        local spectators = getCustomSpectators(monsters[i].tpFrom, false, true, false, false, 10, 10, 10, 10)

        for k = 1, #spectators do
            local function teleportSpectators(pos) -- monsters[i].tpTo
                spectators[k]:teleportTo(pos)
            return true
            end

            local function spectatorsSpeak(msg) -- monsters[i].tpTo
                spectators[k]:say(msg, TALKTYPE_MONSTER_SAY, false, spectators[k], monsters[i].msgPos)
            return true
            end

            local function spectatorsCountdown(cid)
                addEvent(spectatorsSpeak, 1000, "10")
                addEvent(spectatorsSpeak, 2000, "9")
                addEvent(spectatorsSpeak, 3000, "8")
                addEvent(spectatorsSpeak, 4000, "7")
                addEvent(spectatorsSpeak, 5000, "6")
                addEvent(spectatorsSpeak, 6000, "5")
                addEvent(spectatorsSpeak, 7000, "4")
                addEvent(spectatorsSpeak, 8000, "3")
                addEvent(spectatorsSpeak, 9000, "2")
                addEvent(spectatorsSpeak, 10000, "1")
            return true
            end

            if target:isMonster(target) then
                if target:getName() == monsters[i].name then
                    spectators[k]:say(monsters[i].msg, TALKTYPE_MONSTER_SAY, false, spectators[k], monsters[i].msgPos)
                    addEvent(spectatorsCountdown, 10000, cid)
                    addEvent(teleportSpectators, 20000, monsters[i].tpTo)
                end

            end

        end

    end

return true
end

Thanks in advance!
 
Solution
I would done something like this:

Code:
local config = {
    ["rat"] = {
        teleportFrom = Position(1000, 1000, 7),
        teleportDestination = Position(100, 100, 7),
        message = {"Hello", Position(1000, 100, 7)}
    }
}

local function executeEventCode(cid, t, time)
    local player = Player(cid)
    if player then
        if time == 0 then
            player:teleportTo(t.teleportDestination)
            return
        end

        player:say(time, TALKTYPE_MONSTER_SAY, false, player, t.message[2])
    end

    addEvent(executeEventCode, 1000, cid, t, time - 1)
end

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

    local t =...
I'm sorry but I can't understand your example XD it's like I'm still in learning process and none of the scripts I had to create until now lookt like that :P
 
I'm sorry but I can't understand your example XD it's like I'm still in learning process and none of the scripts I had to create until now lookt like that :p
You can't just copy and paste code into a script and expect it to work like you'd like it to.

Your defining functions in a loop, calling methods on a target & ending the script, even if the target isn't a player and if you didn't do the above mentioned the script still would not execute because your passing the wrong values to the function, your looking for creatures but you set it to look for players, not to mention you forgot to include the definition for the core function.

So start over or just tell people what you want to accomplish.
 
im not sure what your trying to say Codex, but ok
I fixed the script (at least it works 100% for me and theres no errors in console)

I may not fully understand lua but it seems you don't like me or smth cuz you seem a bit offensive there.

(For people who want to use it)

Code:
--[[ Config]]--
local monsters = {
    [1] = {
        name = "Demon",
        tpFrom = {x = 4639, y = 4973, z = 4},
        tpTo = {x = 4647, y = 4991, z = 4},
        msg = "Test Msg 1",
        msgPos = {x = 4638, y = 4968, z = 4},
    },
    [2] = {
        name = "Rotworm",
        tpFrom = {x = 4648, y = 4991, z = 4},
        tpTo = {x = 4638, y = 5005, z = 4},
        msg = "Test Msg 2",
        msgPos = {x = 4647, y = 4989, z = 4},
    },
    [3] = {
        name = "Rotworm Mother",
        tpFrom = {x = 4648, y = 4991, z = 4},
        tpTo = {x = 4638, y = 5005, z = 4},
        msg = "Test Msg 3",
        msgPos = {x = 4647, y = 4989, z = 4},
    }   
}
--<< Script Start >>--
function onKill(creature, target)
    if not target:isMonster() or target:getMaster() then
    return true
    end

    for i = 1, #monsters do
        local spectators = getCustomSpectators(monsters[i].tpFrom, false, true, false, false, 10, 10, 10, 10)

        for k = 1, #spectators do
            local function teleportSpectators(pos) -- monsters[i].tpTo
                spectators[k]:teleportTo(pos)
            return true
            end

            local function spectatorsSpeak(msg) -- monsters[i].tpTo
                spectators[k]:say(msg, TALKTYPE_MONSTER_SAY, false, spectators[k], monsters[i].msgPos)
            return true
            end

            local function spectatorsCountdown(cid)
                addEvent(spectatorsSpeak, 1000, "10")
                addEvent(spectatorsSpeak, 2000, "9")
                addEvent(spectatorsSpeak, 3000, "8")
                addEvent(spectatorsSpeak, 4000, "7")
                addEvent(spectatorsSpeak, 5000, "6")
                addEvent(spectatorsSpeak, 6000, "5")
                addEvent(spectatorsSpeak, 7000, "4")
                addEvent(spectatorsSpeak, 8000, "3")
                addEvent(spectatorsSpeak, 9000, "2")
                addEvent(spectatorsSpeak, 10000, "1")
            return true
            end

            if target:isMonster(target) then
                if target:getName() == monsters[i].name then
                    spectators[k]:say(monsters[i].msg, TALKTYPE_MONSTER_SAY, false, spectators[k], monsters[i].msgPos)
                    addEvent(spectatorsCountdown, 10000, cid)
                    addEvent(teleportSpectators, 20000, monsters[i].tpTo)
                end

            end

        end

    end

return true
end

If you want to improve the script be my guest, just don't post it here, I don't want Codex to think this is a move to obtain the script with sexy look.
 
I changed the positions and the gathering spectators function in order to test it properly on my server.

For me the best way to learn was to study scripts made by people who are more knowledgeable than me and also by searching questions up on Google and reading and really trying to understand the concept.

I'm posting this not only to help you learn, but also to help myself learn. I hope some more experience programmers can let me know where I can improve myself and what errors I'm making.

Code:
--[[ Config]]--
local monsters = {
    ["demon"] = {
        --name = "Demon",
        tpFrom = Position(32338,32222,7),
        tpTo = Position(32334,32222,6),
        msg = "Test Msg 1",
        msgPos = Position(32334,32222,6),
    },
    ["rotworm"] = {
       -- name = "Rotworm",
        tpFrom = Position(32338,32222,7),
        tpTo = Position(32334,32222,6),
        msg = "Test Msg 2",
        msgPos = Position(32334,32222,6),
    },
    msgSeconds = 10 -- How long should the countdown be? (in seconds)
}

-- Teleport Function
local function teleportSpectators(cid, pos)
    Player(cid):teleportTo(pos)
end
-- Send countdown Function
local function spectatorsSpeak(msg, cid, pos)
    Player(cid):say(msg, TALKTYPE_MONSTER_SAY, true, Player(cid), pos)
end
-- Funciton to start countdown
local function spectatorsCountdown(msg, cid, pos)
    for i=1, msg do
        addEvent(spectatorsSpeak, i*1000, ((msg+1)-i), Player(cid):getId(), pos)
    end
end

--<< Script Start >>--
function onKill(creature, target)
    -- Make sure the target is not a player, is a monster, and not a summon of a player
    if target:isPlayer() or not target:isMonster() or target:getMaster() then
        return true
    end
  
    -- Make sure the monster is in our table
    local monster = monsters[target:getName():lower()]
    if not monster then
        return true
    end
  
    local spectators = Game.getSpectators(monster.tpFrom, false, true, 10, 10, 10, 10) -- You were using some custom function I didn't have
    for k = 1, #spectators do
        local dude = spectators[k]
        dude:say(monster.msg, TALKTYPE_MONSTER_SAY, false, dude, monster.msgPos)
        addEvent(spectatorsCountdown, 10000, monsters.msgSeconds, dude:getId(), monster.msgPos)
        addEvent(teleportSpectators, 20000, dude:getId(), monster.tpTo)
    end
  
return true
end
 
@Codex NG

What I want to acomplish is, instead of people saying you have a error in a loop, string, variable, blabla, I prefer them to say "You have a error in line 9 (for example)" and then I will focus on that line to see what's wrong with it, but if you tell me the other way like:

Your defining functions in a loop, calling methods on a target & ending the script, even if the target isn't a player and if you didn't do the above mentioned the script still would not execute because your passing the wrong values to the function, your looking for creatures but you set it to look for players, not to mention you forgot to include the definition for the core function.

I don't understand this, in my mind I just know what the functions do, I put them together and boom it works or doesn't, if it doesn't I start printing to see what's the issue..

I know it's retarded what I'm saying and I should see a LUA tutorial before start posting for help, but I'm retard, what can I say :X

P.S: I don't want people to correct my mess and then I just copy paste, if that's what you think.
 
Last edited:
@Codex NG

What I want to acomplish is, instead of people saying you have a error in a loop, string, variable, blabla, I prefer them to say "You have a error in like 9 (for example)" and then I will focus on that line to see what's wrong with it, but if you tell me the other way like:



I don't understand this, in my mind I just know what the functions do, I put them together and boom it works or doesn't, if it doesn't I start printing to see what's the issue..

I know it's retarded what I'm saying and I should see a LUA tutorial before start posting for help, but I'm retard, what can I say :X

P.S: I don't want people to correct my mess and then I just copy paste, if that's what you think.
I agree you are.
 
As I was rewriting your script, I started to notice that it was starting to look a lot like what @J.Dre posted.
(http://paste.diath.net/3A94271D/raw)

I stopped because we can't interpret what "getCustomSpectators" means, since you didn't provide the function for us.

@J.Dre: Does the damage map store by CID? If so, in theory, if a player were to contribute to the damage map and then die, their CID would not match their old one in the spectator map and would not be teleported (the intended effect) - right?
If so, this would be preferable to getting an area's spectators; unless you're concerned about players contributing to the damage map with one attack, for example.

Hmm, just a thought.
Red
 
@Red : Yep, the damage map store attackers by their CID.

@imkingran : Keep in mind that you should verify whether the userdata object is valid or not, before you start using meta methods in addEvent. Also there is no need to use the meta method Creature.getId when you already have passed CID to a function (Referring to the spectator functions).
 
I would done something like this:

Code:
local config = {
    ["rat"] = {
        teleportFrom = Position(1000, 1000, 7),
        teleportDestination = Position(100, 100, 7),
        message = {"Hello", Position(1000, 100, 7)}
    }
}

local function executeEventCode(cid, t, time)
    local player = Player(cid)
    if player then
        if time == 0 then
            player:teleportTo(t.teleportDestination)
            return
        end

        player:say(time, TALKTYPE_MONSTER_SAY, false, player, t.message[2])
    end

    addEvent(executeEventCode, 1000, cid, t, time - 1)
end

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

    local t = config[target:getName():lower()]
    if not t then
        return true
    end

    for _, spectator in ipairs(Game.getSpectators(t.teleportFrom, false, true, 10, 10, 10, 10)) do
        spectator:say(t.message[1], TALKTYPE_MONSTER_SAY, false, spectator, t.message[2])
        executeEventCode(spectator:getId(), t, 10)
    end

    return true
end
 
Solution
Back
Top