NPC [TFS 1.x] Dicer/Gambler NPC

Nekiro

Support Team
Support Team
Joined
Sep 7, 2015
Messages
1,960
Best answers
86
Reaction score
735
I was bored and just scripted dicer npc for tfs 1.x, all you do is setup config and you ready to go. Dicer will count the money that player put on counter also will calculate how much he won and put the won money back on the counter.

Make sure the npc can't move, so he won't run away from depot :)

Preview:

Code:
Code:
-- written by Nekiro#5727 // otland: https://otland.net/members/nekiro.214311/

local config = {
    bet = {
        min = 30000, -- gold coins // 30k
        max = 6000000,
        win = 120, -- 120% high/low
        winNum = 300, -- 300% numbers
    },

    playerPosition = Position(32352, 32226, 7), -- player must stay on this position to talk with npc
    dicerCounter = Position(32353, 32225, 7), -- counter position
}

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)        npcHandler:onCreatureDisappear(cid)            end
function onCreatureSay(cid, type, msg)        npcHandler:onCreatureSay(cid, type, msg)        end
function onThink()
    npcHandler:onThink()
    local tile = Tile(config.playerPosition)
    if tile then
        local player = tile:getTopCreature()
        if not player then
            npcHandler.focuses = {}
            npcHandler:updateFocus()
        end
    end
end

local function getCoinValue(id)
    if id == 2160 then
        return 10000
    elseif id == 2152 then
        return 100
    elseif id == 2148 then
        return 1
    end
    return 0
end

local function getBetValue()
    local value = 0
    local tile = Tile(config.dicerCounter)
    if tile then
        local items = tile:getItems()
        if not items or #items == 0 then
            return 0
        end

        local tempMoney = {}
        for _, item in pairs(items) do
            if table.contains({2160, 2152, 2148}, item:getId()) then
                value = value + getCoinValue(item:getId()) * item:getCount()
                tempMoney[#tempMoney + 1] = item
            end
        end

        if value >= config.bet.min and value <= config.bet.max then -- valid bet
            for _, item in pairs(tempMoney) do
                item:remove()
            end
            return value
        end
    end
    return nil
end

local function createMoney(money)
    local table = {}
    local currentMoney = money
    local crystals = math.floor(currentMoney / 10000)
    currentMoney = currentMoney - crystals * 10000
    while crystals > 0 do
        local count = math.min(100, crystals)
        table[#table + 1] = {2160, count}
        crystals = crystals - count
    end

    local platinums = math.floor(currentMoney / 100)
    if platinums ~= 0 then
        table[#table + 1] = {2152, platinums}
        currentMoney = currentMoney - platinums * 100
    end

    if currentMoney ~= 0 then
        table[#table + 1] = {2148, currentMoney}
    end
    return table
end

local function greetCallback(cid)
    local player = Player(cid)
    if player:getPosition() ~= config.playerPosition then
        npcHandler:say("If you want to play with me please come near me.", cid)
        return false
    end
    return true
end

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)
    if player:getPosition() ~= config.playerPosition then
        npcHandler:unGreet(cid)
        return false
    end

    local thisNpc = Npc(getNpcCid())
    if table.contains({"low", "high", "h", "l", "1", "2", "3", "4", "5", "6"}, msg) then
        local bet = getBetValue()
        if not bet then
            npcHandler:say("Your bet is higher or lower than the max (".. config.bet.max ..") or min (".. config.bet.min ..") bet.", cid)
            npcHandler.topic[cid] = 0
            return true
        end

        local number = math.random(1, 6)
        thisNpc:say(thisNpc:getName() .. " rolled a ".. number .. ".", TALKTYPE_MONSTER_SAY)
        thisNpc:getPosition():sendMagicEffect(CONST_ME_CRAPS)
        if table.contains({"low", "l"}, msg) then
            if table.contains({1, 2, 3}, number) then
                local wonMoney = bet * (config.bet.win / 100)
                npcHandler:say("Congratulations, you won! Here's your (".. wonMoney ..") gold coins.", cid)
                config.dicerCounter:sendMagicEffect(math.random(29, 31))
                for _, coin in pairs(createMoney(wonMoney)) do
                    Game.createItem(coin[1], coin[2], config.dicerCounter)
                end
            else
                npcHandler:say("No luck this time, you lost.", cid)
            end
        elseif table.contains({"high", "h"}, msg) then
            if table.contains({4, 5, 6}, number) then
                local wonMoney = bet * (config.bet.win / 100)
                npcHandler:say("Congratulations, you won! Here's your (".. wonMoney ..") gold coins.", cid)
                config.dicerCounter:sendMagicEffect(math.random(29, 31))
                for _, coin in pairs(createMoney(wonMoney)) do
                    Game.createItem(coin[1], coin[2], config.dicerCounter)
                end
            else
                npcHandler:say("No luck this time, you lost.", cid)
            end
        elseif table.contains({"1", "2", "3", "4", "5", "6"}, msg) then
            if number == tonumber(msg) then
                local wonMoney = bet * (config.bet.winNum / 100)
                npcHandler:say("Congratulations, you won! Here's your (".. wonMoney ..") gold coins.", cid)
                config.dicerCounter:sendMagicEffect(math.random(29, 31))
                for _, coin in pairs(createMoney(wonMoney)) do
                    Game.createItem(coin[1], coin[2], config.dicerCounter)
                end
            else
                npcHandler:say("No luck this time, you lost.", cid)
            end
        end
    end
    return true
end

npcHandler:setMessage(MESSAGE_GREET, "Welcome to my cassino! I'm offering {high/low} and {numbers}, to start just put your {money} on {counter} and say {number} or {high/low}.")
npcHandler:setMessage(MESSAGE_FAREWELL, 'Good bye.')
npcHandler:setMessage(MESSAGE_WALKAWAY, 'Good bye.')

npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 

silveralol

Advanced OT User
Joined
Mar 16, 2010
Messages
1,461
Best answers
8
Reaction score
184
you should declare the positions more generic, to be possible to use the same npc in numerious places, but nice!
 
OP
Nekiro

Nekiro

Support Team
Support Team
Joined
Sep 7, 2015
Messages
1,960
Best answers
86
Reaction score
735
you should declare the positions more generic, to be possible to use the same npc in numerious places, but nice!
No, that's your opinion. I'm sharing one npc not gamble/dice system.
 

silveralol

Advanced OT User
Joined
Mar 16, 2010
Messages
1,461
Best answers
8
Reaction score
184
why be so stupid ? but ok, its your script :) gl baby
 

Selenia-Global

Selenia-Global.com
Joined
Jan 21, 2018
Messages
28
Best answers
1
Reaction score
1
awesome!
Hello Nekiro . How can i make it so when it says hi it says the name of the player back in this

npcHandler:setMessage(MESSAGE_GREET, "Welcome "name of the player here" to my cassino! I'm offering {high/low} and {numbers}, to start just put your {money} on {counter} and say {number} or {high/low}.")

Should i ad Getplayernmame or just add {PLAYERNAME} or how? XD

Thanks in advance buddy.
 

flaviiojr

Active Member
Joined
Jan 20, 2017
Messages
230
Best answers
13
Reaction score
35
awesome!
Hello Nekiro . How can i make it so when it says hi it says the name of the player back in this

npcHandler:setMessage(MESSAGE_GREET, "Welcome "name of the player here" to my cassino! I'm offering {high/low} and {numbers}, to start just put your {money} on {counter} and say {number} or {high/low}.")

Should i ad Getplayernmame or just add {PLAYERNAME} or how? XD

Thanks in advance buddy.
|PLAYERNAME|
 

Selenia-Global

Selenia-Global.com
Joined
Jan 21, 2018
Messages
28
Best answers
1
Reaction score
1
Thanks a lot flavioojr! :D!

One more question.. why two 1 in if table.contains({"low", "high", "h", "l", "1", "2", "3", "4", "5", "6"}, msg) then

and how can i make it so it pays more?
thanks in advance

Thanks a lot flavioojr! :D!

One more question.. why two 1 in if table.contains({"low", "high", "h", "l", "1", "2", "3", "4", "5", "6"}, msg) then

and how can i make it so it pays more?
thanks in advance
Im so sorry!!! im practicly blind i didnt saw it was an L pls forgive me!! (i couldnt edit the post, or erase it.!!
 
Last edited by a moderator:

LIINDI

New Member
Joined
Mar 14, 2018
Messages
78
Best answers
1
Reaction score
3
@Nekiro

Hey man. Really cool code!
Do you know why it says "There is not enough room" when trying to spawn him in? Can't seem to spawn him anywhere. No error code in console either.. Any thoughts?
 

Selenia-Global

Selenia-Global.com
Joined
Jan 21, 2018
Messages
28
Best answers
1
Reaction score
1
@Nekiro

Hey man. Really cool code!
Do you know why it says "There is not enough room" when trying to spawn him in? Can't seem to spawn him anywhere. No error code in console either.. Any thoughts?
It has to do with you not adding the xml in npc folder...or you didnt import the npx xml onto the map ( use remeres map editor , import npc , select the name of the npc you wish to import, then erase any underscore "_" that has in between (if you didnt add any) and there you have it! :D! also... if this was the issue pls like it :D!
 

Eldin

Eldin Projects
Premium User
Joined
Jun 12, 2008
Messages
1,304
Best answers
0
Reaction score
534
Location
Sweden
@Nekiro - First of all, great script! Thank you for that.
I do however have an issue once I say "Hi", placed the Money on the counter and say the number or "High/low".

Nothing happens, no Money is taken and the NPC doesn't respond, Instead I get this message in the console:
Code:
Lua Script Error: [Npc interface]
data/npc/scripts/GamblerThree.lua:onCreatureSay
data/npc/scripts/GamblerThree.lua:118: attempt to call field 'contains' (a nil v
alue)
stack traceback:
        [C]: in function 'contains'
        data/npc/scripts/GamblerThree.lua:118: in function 'callback'
        data/npc/lib/npcsystem/npchandler.lua:411: in function 'onCreatureSay'
        data/npc/scripts/GamblerThree.lua:22: in function <data/npc/scripts/Gamb
lerThree.lua:22>
TFS 1.2.
I can't seem to figure it out, any help appriciated. Thanks in advance!

Best Regards,
Eldin
 

Xizze

New Member
Joined
Nov 3, 2008
Messages
2
Best answers
0
Reaction score
0
@Nekiro - First of all, great script! Thank you for that.
I do however have an issue once I say "Hi", placed the Money on the counter and say the number or "High/low".

Nothing happens, no Money is taken and the NPC doesn't respond, Instead I get this message in the console:
Code:
Lua Script Error: [Npc interface]
data/npc/scripts/GamblerThree.lua:onCreatureSay
data/npc/scripts/GamblerThree.lua:118: attempt to call field 'contains' (a nil v
alue)
stack traceback:
        [C]: in function 'contains'
        data/npc/scripts/GamblerThree.lua:118: in function 'callback'
        data/npc/lib/npcsystem/npchandler.lua:411: in function 'onCreatureSay'
        data/npc/scripts/GamblerThree.lua:22: in function <data/npc/scripts/Gamb
lerThree.lua:22>
TFS 1.2.
I can't seem to figure it out, any help appriciated. Thanks in advance!

Best Regards,
Eldin
Im getting the same error on my server TFS 1.2

From the console
"Lua Script Error: [Npc interface]
data/npc/scripts/Dice.lua:eek:nCreatureSay
data/npc/scripts/Dice.lua:116: attempt to call field 'contains' (a nil value)"

i guess the getBetValue function returns nil. But i cant figure out why.

EDIT: SOLVED!

I added this to global.lua file:

table.contains = function(array, value)
for _, targetColumn in pairs(array) do
if targetColumn == value then
return true
end
end
return false
end
 
Last edited:

Itutorial

Veteran OT User
Joined
Dec 23, 2014
Messages
1,542
Best answers
35
Reaction score
379
I modified this code to allow multi location with 1 code.

With that being said the code can only be used on NPC's that have the same table that must be defined in the code between the npc and player.

Add the itemid for the table between the player and npc in the code: config.tableID.

Code:
-- written by Nekiro#5727 // otland: https://otland.net/members/nekiro.214311/
-- Modified by Itutorial

local config = {
    tableID = 1111 -- Set to the table itemid that is between the two lock boxes between the player and npc
    bet = {
        min = 30000, -- gold coins // 30k
        max = 6000000,
        win = 120, -- 120% high/low
        winNum = 300, -- 300% numbers
    }
}

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)        npcHandler:onCreatureDisappear(cid)            end
function onCreatureSay(cid, type, msg)        npcHandler:onCreatureSay(cid, type, msg)        end
function onThink()
    npcHandler:onThink()
    local tile = Tile(config.playerPosition)
    if tile then
        local player = tile:getTopCreature()
        if not player then
            npcHandler.focuses = {}
            npcHandler:updateFocus()
        end
    end
end

local function getCoinValue(id)
    if id == 2160 then
        return 10000
    elseif id == 2152 then
        return 100
    elseif id == 2148 then
        return 1
    end
    return 0
end

local function getBetValue()
    local value = 0
    local tile = Tile(config.dicerCounter)
    if tile then
        local items = tile:getItems()
        if not items or #items == 0 then
            return 0
        end

        local tempMoney = {}
        for _, item in pairs(items) do
            if table.contains({2160, 2152, 2148}, item:getId()) then
                value = value + getCoinValue(item:getId()) * item:getCount()
                tempMoney[#tempMoney + 1] = item
            end
        end

        if value >= config.bet.min and value <= config.bet.max then -- valid bet
            for _, item in pairs(tempMoney) do
                item:remove()
            end
            return value
        end
    end
    return nil
end

local function createMoney(money)
    local table = {}
    local currentMoney = money
    local crystals = math.floor(currentMoney / 10000)
    currentMoney = currentMoney - crystals * 10000
    while crystals > 0 do
        local count = math.min(100, crystals)
        table[#table + 1] = {2160, count}
        crystals = crystals - count
    end

    local platinums = math.floor(currentMoney / 100)
    if platinums ~= 0 then
        table[#table + 1] = {2152, platinums}
        currentMoney = currentMoney - platinums * 100
    end

    if currentMoney ~= 0 then
        table[#table + 1] = {2148, currentMoney}
    end
    return table
end

local function greetCallback(cid)
    local player = Player(cid)
    if player:getPosition() ~= config.playerPosition then
        npcHandler:say("If you want to play with me please come near me.", cid)
        return false
    end
    return true
end

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end
    
    local thisNpc = Npc(getNpcCid())
    local npcPosition = thisNpc:getPosition()
    
    local checkPositions = {
        [1] = {x = npcPosition.x - 1, y = npcPosition.y - 1, z = npcPosition.z},
        [2] = {x = npcPosition.x + 1, y = npcPosition.y - 1, z = npcPosition.z},
        [3] = {x = npcPosition.x - 1, y = npcPosition.y + 1, z = npcPosition.z},
        [4] = {x = npcPosition.x + 1, y = npcPosition.y + 1, z = npcPosition.z}
    }
    
    local playerRequiredPosition = nil
    
    for i = 1, #checkPositions do
        if Tile(checkPositions[i]):getTopDownItem().itemid == config.tableID then
            if i == 1 or i == 3 then
                playerRequiredPosition = {x = npcPosition.x - 2, y = npcPosition.y, z = npcPosition.z}
            else
                playerRequiredPosition = {x = npcPosition.x + 2, y = npcPosition.y, z = npcPosition.z}
            end
        end
    end
    
    local player = Player(cid)
    if playerRequiredPosition == nil or player:getPosition() ~= playerRequiredPosition then
        npcHandler:unGreet(cid)
        return false
    end
    
    if table.contains({"low", "high", "h", "l", "1", "2", "3", "4", "5", "6"}, msg) then
        local bet = getBetValue()
        if not bet then
            npcHandler:say("Your bet is higher or lower than the max (".. config.bet.max ..") or min (".. config.bet.min ..") bet.", cid)
            npcHandler.topic[cid] = 0
            return true
        end

        local number = math.random(1, 6)
        thisNpc:say(thisNpc:getName() .. " rolled a ".. number .. ".", TALKTYPE_MONSTER_SAY)
        thisNpc:getPosition():sendMagicEffect(CONST_ME_CRAPS)
        if table.contains({"low", "l"}, msg) then
            if table.contains({1, 2, 3}, number) then
                local wonMoney = bet * (config.bet.win / 100)
                npcHandler:say("Congratulations, you won! Here's your (".. wonMoney ..") gold coins.", cid)
                config.dicerCounter:sendMagicEffect(math.random(29, 31))
                for _, coin in pairs(createMoney(wonMoney)) do
                    Game.createItem(coin[1], coin[2], config.dicerCounter)
                end
            else
                npcHandler:say("No luck this time, you lost.", cid)
            end
        elseif table.contains({"high", "h"}, msg) then
            if table.contains({4, 5, 6}, number) then
                local wonMoney = bet * (config.bet.win / 100)
                npcHandler:say("Congratulations, you won! Here's your (".. wonMoney ..") gold coins.", cid)
                config.dicerCounter:sendMagicEffect(math.random(29, 31))
                for _, coin in pairs(createMoney(wonMoney)) do
                    Game.createItem(coin[1], coin[2], config.dicerCounter)
                end
            else
                npcHandler:say("No luck this time, you lost.", cid)
            end
        elseif table.contains({"1", "2", "3", "4", "5", "6"}, msg) then
            if number == tonumber(msg) then
                local wonMoney = bet * (config.bet.winNum / 100)
                npcHandler:say("Congratulations, you won! Here's your (".. wonMoney ..") gold coins.", cid)
                config.dicerCounter:sendMagicEffect(math.random(29, 31))
                for _, coin in pairs(createMoney(wonMoney)) do
                    Game.createItem(coin[1], coin[2], config.dicerCounter)
                end
            else
                npcHandler:say("No luck this time, you lost.", cid)
            end
        end
    end
    return true
end

npcHandler:setMessage(MESSAGE_GREET, "Welcome to my cassino! I'm offering {high/low} and {numbers}, to start just put your {money} on {counter} and say {number} or {high/low}.")
npcHandler:setMessage(MESSAGE_FAREWELL, 'Good bye.')
npcHandler:setMessage(MESSAGE_WALKAWAY, 'Good bye.')

npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Top