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

NPC Visual Gambler NPC [TFS 1.x]

Printer

if Printer then print("LUA") end
Senator
Premium User
Joined
Dec 27, 2009
Messages
5,782
Solutions
31
Reaction score
2,284
Location
Sweden?
Inspired by: https://otland.net/threads/the-gambling-man-the-interactive-dicer.197833/

Z7HnD16OS.gif


I'm pretty sure the code can be improved, but i leave it as it now.

  • Automatic money convert!
  • No need configure positions, just make sure gambler is on the left and player on the right!
  • Bonus on the win! configureable!
  • Min and Max Bet! configureable!
  • Ani-Trash!
  • Anti-Cheat!
Code:
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

local config = {
    bonusPercent = 2,
    minimumBet = 100,
    maximumBet = 10000000
}

local storeMoneyAmount = 0 -- Do not touch [We store the amount cash which got betted here]
local ITEM_BLOCKING = 8046

local function getMoneyAmount(position)
    local moneyAmount = 0
    for _, item in ipairs(Tile(position):getItems()) do
        local itemId = item:getId()
        if itemId == ITEM_GOLD_COIN then
            moneyAmount = moneyAmount + item.type
        elseif itemId == ITEM_PLATINUM_COIN then
            moneyAmount = moneyAmount + item.type * 100
        elseif itemId == ITEM_CRYSTAL_COIN then
            moneyAmount = moneyAmount + item.type * 10000
        end
    end

    return moneyAmount
end

local function handleMoney(cid, position, bonus)
    local npc = Npc(cid)
    if not npc then
        return
    end

    -- Lets remove the cash which was betted
    for _, item in ipairs(Tile(position):getItems()) do
        if isInArray({ITEM_GOLD_COIN, ITEM_PLATINUM_COIN, ITEM_CRYSTAL_COIN, ITEM_BLOCKING}, item:getId()) then
            item:remove()
        end
    end

    -- We lost, no need to continue
    if bonus == 0 then
        npc:say("You lost!", TALKTYPE_SAY)
        position:sendMagicEffect(CONST_ME_POFF)
        return
    end

    -- Cash calculator
    local goldCoinAmount = storeMoneyAmount * bonus
    local crystalCoinAmount = math.floor(goldCoinAmount / 10000)
    goldCoinAmount = goldCoinAmount - crystalCoinAmount * 10000
    local platinumCoinAmount = math.floor(goldCoinAmount / 100)
    goldCoinAmount = goldCoinAmount - platinumCoinAmount * 100

    if goldCoinAmount ~= 0 then
        Game.createItem(ITEM_GOLD_COIN, goldCoinAmount, position)
    end

    if platinumCoinAmount ~= 0 then
        Game.createItem(ITEM_PLATINUM_COIN, platinumCoinAmount, position)
    end

    if crystalCoinAmount ~= 0 then
        Game.createItem(ITEM_CRYSTAL_COIN, crystalCoinAmount, position)
    end

    position:sendMagicEffect(math.random(CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_BLUE))
    npc:say("You Win!", TALKTYPE_SAY)
end

local function startRollDice(cid, position, number)
    for i = 5792, 5797 do
        local dice = Tile(position):getItemById(i)
        if dice then
            dice:transform(5791 + number)
            break
        end
    end

    local npc = Npc(cid)
    if npc then
        npc:say(string.format("%s rolled a %d", npc:getName(), number), TALKTYPE_MONSTER_SAY)
    end
end

local function executeEvent(cid, dicePosition, number, moneyPosition, bonus)
    local npc = Npc(cid)
    if not npc then
        return
    end
   
    if getMoneyAmount(moneyPosition) ~= storeMoneyAmount then
        npc:say("Where is the money?!", TALKTYPE_SAY)
        return
    end
   
    -- Roll Dice
    addEvent(startRollDice, 400, cid, dicePosition, number)
    dicePosition:sendMagicEffect(CONST_ME_CRAPS)
   
    -- Handle Money
    addEvent(handleMoney, 600, cid, moneyPosition, bonus)
end

local function creatureSayCallback(cid, type, msg)
    if not isInArray({"high", "low"}, msg) then -- Ignore other replies
        return false
    end

    -- Npc Variables
    local npc = Npc()
    local npcPosition = npc:getPosition()

    -- Check if player stand in position
    local playerPosition = Position(npcPosition.x + 2, npcPosition.y, npcPosition.z)
    local topCreature = Tile(playerPosition):getTopCreature()
    if not topCreature then
        npc:say("Please go stand next to me.", TALKTYPE_SAY)
        playerPosition:sendMagicEffect(CONST_ME_TUTORIALARROW)
        playerPosition:sendMagicEffect(CONST_ME_TUTORIALSQUARE)
        return false
    end

    -- Make sure also the player who stand there, is the one who is betting. To keep out people from disturbing
    if topCreature:getId() ~= cid then
        return false
    end
    -- High or Low numbers
    local rollType = 0
    if msgcontains(msg, "low") then
        rollType = 1
    elseif msgcontains(msg, "high") then
        rollType = 2
    else
        return false
    end

    -- Check money Got betted
    local moneyPosition = Position(npcPosition.x + 1, npcPosition.y - 1, npcPosition.z)
    storeMoneyAmount = getMoneyAmount(moneyPosition)
    if storeMoneyAmount < config.minimumBet or storeMoneyAmount > config.maximumBet then
        npc:say(string.format("You can only bet min: %d and max: %d gold coins.", config.minimumBet, config.maximumBet), TALKTYPE_SAY)
        return false
    end
    -- Money is betted, lets block them from getting moved // This is one way, else we can set actionid, on the betted cash.
    Game.createItem(ITEM_BLOCKING, 1, moneyPosition)

    -- Roll Number
    local rollNumber = math.random(6)

    -- Win or Lose
    local bonus = 0
    if rollType == 1 and isInArray({1, 2, 3}, rollNumber) then
        bonus = config.bonusPercent
    elseif rollType == 2 and isInArray({4, 5, 6}, rollNumber) then
        bonus = config.bonusPercent
    end
   
    -- Money handle and roll dice
    addEvent(executeEvent, 100, npc:getId(), Position(npcPosition.x, npcPosition.y - 1, npcPosition.z), rollNumber, moneyPosition, bonus)
    return true
end

function onThink()
    -- Anti trash
    local npcPosition = Npc():getPosition()
    local moneyPosition = Position(npcPosition.x + 1, npcPosition.y - 1, npcPosition.z)

    for _, item in ipairs(Tile(moneyPosition):getItems()) do
        local itemId = item:getId()
        if not isInArray({ITEM_GOLD_COIN, ITEM_PLATINUM_COIN, ITEM_CRYSTAL_COIN, ITEM_BLOCKING}, itemId) and ItemType(itemId):isMovable() then
            item:remove()
        end
    end
   
    local dicePosition = Position(npcPosition.x, npcPosition.y - 1, npcPosition.z)
    for _, item in ipairs(Tile(dicePosition):getItems()) do
        local itemId = item:getId()
        if not isInArray({5792, 5793, 5794, 5795, 5796, 5797}, itemId) and ItemType(itemId):isMovable() then
            item:remove()
        end
    end

    npcHandler:onThink()                   
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
 
Last edited:
Wow awesome! I currently have one like this but you pick a number, not high low. So this will be a nice change!
 
I tested in OTX 2 and


Code:
[15/12/2015 19:26:5] [Error - NpcScript Interface]
[15/12/2015 19:26:5] data/npc/scripts/gambler.lua:onThink
[15/12/2015 19:26:5] Description:
[15/12/2015 19:26:5] data/npc/scripts/gambler.lua:152: attempt to call global 'Npc' (a nil value)
[15/12/2015 19:26:5] stack traceback:
[15/12/2015 19:26:5]     data/npc/scripts/gambler.lua:152: in function <data/npc/scripts/gambler.lua:151>
 
I tested in OTX 2 and


Code:
[15/12/2015 19:26:5] [Error - NpcScript Interface]
[15/12/2015 19:26:5] data/npc/scripts/gambler.lua:onThink
[15/12/2015 19:26:5] Description:
[15/12/2015 19:26:5] data/npc/scripts/gambler.lua:152: attempt to call global 'Npc' (a nil value)
[15/12/2015 19:26:5] stack traceback:
[15/12/2015 19:26:5]     data/npc/scripts/gambler.lua:152: in function <data/npc/scripts/gambler.lua:151>

OTX 2 is based in 0.3.7 not in TFS 1.x so it's not compatible.
 
look's good but there is one bug... If you say "H" and take your money fast... you make's a bet but you don't lose your money.. . That's mean " Casino take the money to slow " ;P
 
@Printer
Have some bugs with your script:
- It's too slow, if you take your money fast... you make's a bet and you don't lose money;
- If you bet 1kk you get nothing;
 
@Printer
Have some bugs with your script:
- It's too slow, if you take your money fast... you make's a bet and you don't lose money;
- If you bet 1kk you get nothing;
Updated the code, it should now block the coins from getting moved.
About bet 1kk, it seems that it's source releated. So i have started a issue in github.
 
Updated the code, it should now block the coins from getting moved.
About bet 1kk, it seems that it's source releated. So i have started a issue in github.

Still can be moved by using browse field.
 
As i commented on the code. You can also block the money by adding actionid. Maybe it's the best way todo it.

Code:
function Player:onBrowseField(position)
    local tile = Tile(position)
    if tile then
        local topItem = tile:getTopTopItem()
        if topItem and topItem:getId() == 8046 then
            return false
        end
    end

    return true
end
 
try like this :) I edited this script :) Now Work's with

H / L / High / LOW option :)


Code:
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

local config = {
    bonusPercent = 2,
    minimumBet = 20000,
    maximumBet = 500000
}

local storeMoneyAmount = 0 -- Do not touch [We store the amount cash which got betted here]
local ITEM_BLOCKING = 8046

local function getMoneyAmount(position)
    local moneyAmount = 0
    for _, item in ipairs(Tile(position):getItems()) do
        local itemId = item:getId()
        if itemId == ITEM_GOLD_COIN then
            moneyAmount = moneyAmount + item.type
        elseif itemId == ITEM_PLATINUM_COIN then
            moneyAmount = moneyAmount + item.type * 100
        elseif itemId == ITEM_CRYSTAL_COIN then
            moneyAmount = moneyAmount + item.type * 10000
        end
    end

    storeMoneyAmount = moneyAmount
    return moneyAmount
end 

local function handleMoney(cid, position, bonus)
    -- Lets remove the cash which was betted
    for _, item in ipairs(Tile(position):getItems()) do
        if isInArray({ITEM_GOLD_COIN, ITEM_PLATINUM_COIN, ITEM_CRYSTAL_COIN, ITEM_BLOCKING}, item:getId()) then
            item:remove()
        end
    end

    local npc = Npc(cid)
    if not npc then
        return
    end

    -- We lost, no need to continue
    if bonus == 0 then
        npc:say("You lost!", TALKTYPE_SAY)
        position:sendMagicEffect(CONST_ME_POFF)
        return
    end

    -- Cash calculator
    local goldCoinAmount = storeMoneyAmount * bonus
    local crystalCoinAmount = math.floor(goldCoinAmount / 10000)
    goldCoinAmount = goldCoinAmount - crystalCoinAmount * 10000
    local platinumCoinAmount = math.floor(goldCoinAmount / 100)
    goldCoinAmount = goldCoinAmount - platinumCoinAmount * 100

    if goldCoinAmount ~= 0 then
        Game.createItem(ITEM_GOLD_COIN, goldCoinAmount, position)
    end

    if platinumCoinAmount ~= 0 then
        Game.createItem(ITEM_PLATINUM_COIN, platinumCoinAmount, position)
    end

    if crystalCoinAmount ~= 0 then
        Game.createItem(ITEM_CRYSTAL_COIN, crystalCoinAmount, position)
    end

    position:sendMagicEffect(math.random(CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_BLUE))
    npc:say("You Win!", TALKTYPE_SAY)
end

local function startRollDice(cid, position, number)
    for i = 5792, 5797 do
        local dice = Tile(position):getItemById(i)
        if dice then
            dice:transform(5791 + number)
            break
        end
    end

    local npc = Npc(cid)
    if npc then
        npc:say(string.format("%s rolled a %d", npc:getName(), number), TALKTYPE_MONSTER_SAY)
    end
end

local function creatureSayCallback(cid, type, msg)
    if not isInArray({"high", "h", "low", "l"}, msg) then -- Ignore other replies
        return false
    end

    -- Npc Variables
    local npc = Npc()
    local npcPosition = npc:getPosition()

    -- Check if player stand in position
    local playerPosition = Position(npcPosition.x + 2, npcPosition.y, npcPosition.z)
    local topCreature = Tile(playerPosition):getTopCreature()
    if not topCreature then
        npc:say("Please go stand next to me.", TALKTYPE_SAY)
        playerPosition:sendMagicEffect(CONST_ME_TUTORIALARROW)
        playerPosition:sendMagicEffect(CONST_ME_TUTORIALSQUARE)
        return false
    end

    -- Make sure also the player who stand there, is the one who is betting. To keep out people from disturbing
    if topCreature:getId() ~= cid then
        return false
    end
  
    -- High or Low numbers
    local rollType = 0
    if msgcontains(msg, "low") then
        rollType = 1
    elseif msgcontains(msg, "l") then
        rollType = 1
    elseif msgcontains(msg, "high") then
        rollType = 2
    elseif msgcontains(msg, "h") then
        rollType = 2
    else
        return false
    end

    -- Check money Got betted
    local moneyPosition = Position(npcPosition.x + 1, npcPosition.y - 1, npcPosition.z)
    if getMoneyAmount(moneyPosition) < config.minimumBet or getMoneyAmount(moneyPosition) > config.maximumBet then
        npc:say(string.format("You can only bet min: %d and max: %d gold coins.", config.minimumBet, config.maximumBet), TALKTYPE_SAY)
        return false
    end
  
    -- Money is betted, lets block them from getting moved // This is one way, else we can set actionid, on the betted cash.
    Game.createItem(ITEM_BLOCKING, 1, moneyPosition)

    -- Roll Number
    local rollNumber = math.random(6)
    -- Dice
    local dicePosition = Position(npcPosition.x, npcPosition.y - 1, npcPosition.z)
    addEvent(startRollDice, 1, npc:getId(), dicePosition, rollNumber)
    dicePosition:sendMagicEffect(CONST_ME_CRAPS)
    -- Win or Lose
    local bonus = 0
    if rollType == 1 and isInArray({1, 2, 3}, rollNumber) then
        bonus = config.bonusPercent
    elseif rollType == 2 and isInArray({4, 5, 6}, rollNumber) then
        bonus = config.bonusPercent
    end

    -- Money Handeling
    addEvent(handleMoney, 1, npc:getId(), moneyPosition, bonus)
    return true
end

function onThink()
    -- Anti trash
    local npcPosition = Npc():getPosition()
    local moneyPosition = Position(npcPosition.x + 1, npcPosition.y - 1, npcPosition.z)
    for _, item in ipairs(Tile(moneyPosition):getItems()) do
        local itemId = item:getId()
        if not isInArray({ITEM_GOLD_COIN, ITEM_PLATINUM_COIN, ITEM_CRYSTAL_COIN, ITEM_BLOCKING}, itemId) and ItemType(itemId):isMovable() then
            item:remove()
        end
    end
    npcHandler:onThink()                     
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
 
I guess the NPC have to take the money, count it, then proceed. I guess it could take a sec and rather make it right then being abused. :)

Kind Regards,
Eldin.
 
Still too slow, players with bot can move the money too fast.
Now it should check the original bet and if the bet amount has been changed. Then it will not give reward.
You should consider to update your tfs else under:
Code:
local ITEM_BLOCKING = 8046

Add this:

Code:
local ITEM_GOLD_COIN = 2148
local ITEM_PLATINUM_COIN = 2152
local ITEM_CRYSTAL_COIN = 2160
 
Back
Top