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

Action TFS 1.X Water, Lava, Swamp fishing + bowlable monsters

Itutorial

Excellent OT User
Joined
Dec 23, 2014
Messages
2,307
Solutions
68
Reaction score
981
This is what this system supports:
1) Ability to fish inside Water, Lava, and Swamp.
2) Ability to catch monsters in all of them
3) A message can be broadcasted when a player catchs a monster
4) Players have the ability to turn catching normal fish on or off in water
5) Players can use a talkaction to check the requirements for catching monsters in each type
6) Players can check other players catchs of each type of monster even if they are offline
7) Players can Bowl and release certain monsters (you can customize which ones)
8) Players can ONLY bowl monsters they catch from the water or ones they release from bowls

First execute this SQL query in your database.
Code:
CREATE TABLE IF NOT EXISTS `fishing_catchs` (
  `player_id` int(11) NOT NULL,
  `name` varchar(32) NOT NULL,
  `amount` int(11) NOT NULL,
  PRIMARY KEY (`player_id`)
) ENGINE=InnoDB;

Now add this into your global.lua or if you don't have that create a file in data/lib
Lua:
fishOwners = {}

function getPlayerCatchs(playerId, name)
       local resultr, ret = db.storeQuery("SELECT `"..name.."` FROM `fishing_catchs` WHERE `player_id` = "..playerId..";")
        ret = result.getDataInt(resultr, name)
        result.free(resultr)
        return ret or 0
end

function addPlayerCatch(playerId, name, amount)
    db.query("UPDATE `fishing_catchs` SET `"..name.."` = `"..name.."` + "..amount.." WHERE `player_id` = "..playerId..";")
end

function getOfflinePlayerId(name)
    local resultr, ret = db.storeQuery("SELECT `id` FROM `players` WHERE `name` = "..name..";")
        ret = result.getDataInt(resultr, name)
        result.free(resultr)
        return ret or 0
end

Now the fishing code.
Lua:
--ACTION SCRIPT--
local waters = {4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4665, 4666, 4820, 4821, 4822, 4823, 4824, 4825, 4608, 4609, 4610, 4611, 4612, 4613, 7236}
local lava = {598, 599, 600, 601, 9883}
local swamp = {4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712}

local water_monsters = {
    [1] = {name = "Water Monster One", chance = 1000, fishing = 100, level = 500, msg = "|PLAYERNAME| has caught a Monster One!", broadcastToServer = true}
}

local lava_monsters = {
    [1] = {name = "Lava Monster One", chance = 1000, fishing = 100, level = 500, msg = "|PLAYERNAME| has caught a Monster One!", broadcastToServer = true}
}

local swap_monsters = {
    [1] = {name = "Swamp Monster One", chance = 1000, fishing = 100, level = 500, msg = "|PLAYERNAME| has caught a Monster One!", broadcastToServer = true}
}

local chance = 500000000

local catchFishStorage = 15000 --This is used to so players can turn catching regular fish off or on.
local chanceCatchNormalFish = 20 --20% chance to catch normal fish
local chanceCatchNorthernPike = 10 --10% chance to catch northerpike
local fishId = 1111 -- Item id of normal fish
local NorthernPikeId = 1111 -- Item id of northern pike

local bowlable_monsters = {"Water Monster One", "Lava Monster One", "Swamp Monster One"} -- List of monsters that can be bowled. Make it empty is no monsters can be bowled. --

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if Tile(player:getPosition()):hasFlag(TILESTATE_PROTECTIONZONE) then
        return player:sendCancelMessage("You may not fish from protection zone.")
    end
   
    if not isInArray(waters, target.itemid) and not isInArray(lava, target.itemid) and not isInArray(swamp, target.itemid) then
        return false
    end
   
    local tmp_table = {}
   
    if isInArray(waters, target.itemid) then
        tmp_table = water_monsters
        toPosition:sendMagicEffect(CONST_ME_LOSEENERGY)
    elseif isInArray(lava, target.itemid) then
        tmp_table = lava_monsters
        toPosition:sendMagicEffect(CONST_ME_HITBYFIRE)
    elseif isInArray(swamp, target.itemid) then
        tmp_table = swap_monsters
        toPosition:sendMagicEffect(CONST_ME_POISONHIT)
    end
   
    for i = 1, #tmp_table do
        if player:getLevel() >= tmp_table[i].level and player:getSkillLevel(SKILL_FISHING) >= tmp_table[i].fishing then
            local catchChance = math.random(1, chance)
           
            if catchChance <= tmp_table[i].chance then
                local MONS = Game.createMonster(tmp_table[i].name, player:getPosition())
               
                if MONS then
                    addPlayerCatch(player:getGuid(), tmp_table[i].name, 1)
                    fishOwners[MONS:getId()] = player:getGuid()
               
                    if tmp_table[i].broadcast then
                        local text = string.gsub(tmp_table[i].msg, "|PLAYERNAME|", player:getName())
                        Game.broadcastMessage(text)
                    end
                end
            break
            end
        end
    end
   
    if isInArray(waters, target.itemid) then
        if player:getStorageValue(catchFishStorage) == 1 then
            if math.random(1, 100) <= chanceCatchNormalFish then
                player:addItem(fishId, 1, true)
            else
                if math.random(1, 100) <= chanceCatchNorthernPike then
                    player:addItem(northernPikeId, 1, true)
                end
            end
        end
    end
   
    player:addSkillTry(SKILL_FISHING, 1)
return true
end

Now the Bowls code. The empty bowl itemid is 5928 and a filled one is 5929
Lua:
--ACTIONSCRIPT BOWLS.lua--
local catchable_monsters = {
    [1] = {name = "Water Monster One", aid = 15500},
    [2] = {name = "Lava Monster One", aid = 15501},
    [3] = {name = "Swamp Monster One", aid = 15502}
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if Tile(player:getPosition()):hasFlag(TILESTATE_PROTECTIONZONE) then
        return player:sendCancelMessage("You cannot use bowls inside protection zones.")
    end
   
    if item.itemid == 5928 then
        local MONSTER = {}
        for i = 1, #catchable_monsters do
            if target:getName() == catchable_monsters[i].name then
                MONSTER = catchable_monsters[i]
                break
            end
        end
       
        if not MONSTER then
            return player:sendCancelMessage("This monster cannot be bowled.")
        end
   
        if fishOwners[target:getId()] == nil then
            return player:sendCancelMessage("You cannot catch monsters your did not fish up or unbowl.")
        end
   
        if fishOwners[target:getId()] ~= nil and fishOwners[target:getId()] ~= player:getGuid() then
            return player:sendCancelMessage("This is not your monster to bowl.")
        end
   
    if target:remove() and item:remove() then
        local BOWL = player:addItem(5929, 1, false)
        BOWL:setAttribute('aid', MONSTER.aid)
        BOWL:setAttribute('description', "It contains a(n) "..MONSTER.name..".")
    end
   
    elseif item.itemid == 5929 then
        local MONSTER = {}
        for i = 1, #catchable_monsters do
            if item.actionid == catchable_monsters[i].aid then
                MONSTER = catchable_monsters[i]
                break
            end
        end
       
        if not MONSTER then return false end
       
        local MONS = Game.createMonster(MONSTER.name, player:getPosition())
       
        if MONS then
            if item:remove() then
                fishOwners[target:getId()] = player:getGuid()
           
                local players = Game.getPlayers()
                for k, z in ipairs(players) do
                    local G_Player = Player(z)
               
                    if G_Player and G_Player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then
                        G_Player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Player: "..player:getName().." has released a(n) "..MONSTER.name..".")
                    end
                end
            else
                MONS:remove()
            end
        end
    end
return true
end

Now the spell to turn normal fishing off and on
Lua:
local catchFishStorage = 15000 --This is used to so players can turn catching regular fish off or on.

function onCastSpell(creature, variant)
    if creature:getStorageValue(catchFishStorage) == 1 then
        creature:setStorageValue(catchFishStorage, 0)
        creature:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You will now catch normal fish and fishing monsters.")
    else
        creature:setStorageValue(catchFishStorage, 1)
        creature:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You will no longer catch normal fish. You will only catch monsters.")
    end
return true
end

Now the talkaction to show requirements for catching monsters in each type
Lua:
local water_monsters = {
    [1] = {name = "Water Monster One", fishing = 100, level = 500}
}

local lava_monsters = {
    [1] = {name = "Lava Monster One", fishing = 100, level = 500}
}

local swamp_monsters = {
    [1] = {name = "Swamp Monster One", fishing = 100, level = 500}
}

function onSay(player, words, param, channel)
    local text = "[Requirements for catching monsters]\n*Monster - Level - Fishing\n\n|Water Monsters|\n"
   
    for i = 1, #water_monsters do
        if i ~= #water_monsters then
            text = text..""..water_monsters[i].name.." "..water_monsters[i].level.." "..water_monsters[i].fishing.."\n"
        else
            text = text..""..water_monsters[i].name.." "..water_monsters[i].level.." "..water_monsters[i].fishing
        end
    end
       
    text = text.."\n\n~Lava Monsters~\n"
       
    for i = 1, #lava_monsters do
        if i ~= #lava_monsters then
            text = text..""..lava_monsters[i].name.." "..lava_monsters[i].level.." "..lava_monsters[i].fishing.."\n"
        else
            text = text..""..lava_monsters[i].name.." "..lava_monsters[i].level.." "..lava_monsters[i].fishing
        end
    end
       
    text = text.."\n\n~Swamp Monsters~\n"
       
    for i = 1, #swamp_monsters do
        if i ~= #swamp_monsters then
            text = text..""..swamp_monsters[i].name.." "..swamp_monsters[i].level.." "..swamp_monsters[i].fishing.."\n"
        else
            text = text..""..swamp_monsters[i].name.." "..swamp_monsters[i].level.." "..swamp_monsters[i].fishing
        end
    end

    player:showTextDialog(2580, text)
    return false
end

Now the code to show another players catchs (talkaction)
Lua:
local water_monsters = {
    [1] = {name = "Water Monster One"}
}

local lava_monsters = {
    [1] = {name = "Lava Monster One"}
}

local swamp_monsters = {
    [1] = {name = "Swamp Monster One"}
}

function onSay(player, words, param, channel)
    local target = nil
    local targetEx = nil
    local targetId = 0
   
    if not param then
        target = Player(player)
    else
        target = Player(param)
    end
   
    if not target then
        targetEx = getOfflinePlayerId(param)
    end
   
    if targetEx ~= nil and targetEx == 0 then
        player:sendCancelMessage("Player does not exist.")
        return false
    end
   
    if targetEx ~= nil and targetEx ~= 0 then
        targetId = targetEx
    else
        if target then
            targetId = target:getGuid()
        end
    end
   
    local text = "["..param.."'s Catchs]\n~Water Monsters~\n"
   
        for i = 1, #water_monsters do
            if i ~= #water_monsters then
                text = text..""..water_monsters[i].name..": "..getPlayerCatchs(targetId, water_monsters[i].name).."\n"
            else
                text = text..""..water_monsters[i].name..": "..getPlayerCatchs(targetId, water_monsters[i].name)
            end
        end
       
        text = text.."\n\n~Lava Monsters~\n"
       
        for i = 1, #lava_monsters do
            if i ~= #lava_monsters then
                text = text..""..lava_monsters[i].name..": "..getPlayerCatchs(targetId, lava_monsters[i].name).."\n"
            else
                text = text..""..lava_monsters[i].name..": "..getPlayerCatchs(targetId, lava_monsters[i].name)
            end
        end
       
        text = text.."\n\n~Swamp Monsters~\n"
       
        for i = 1, #swamp_monsters do
            if i ~= #swamp_monsters then
                text = text..""..swamp_monsters[i].name..": "..getPlayerCatchs(targetId, swamp_monsters[i].name).."\n"
            else
                text = text..""..swamp_monsters[i].name..": "..getPlayerCatchs(targetId, swamp_monsters[i].name)
            end
        end
       
        player:showTextDialog(2580, text)
return false
end

I hope this is useful for someone.
 
[Error - mysql_real_query] Query: UPDATE fishing_catchs SET Dragon = Dragon + 1 WHERE player_id = 11;
Message: Unknown column 'Dragon' in 'field list'
[Error - mysql_real_query] Query: UPDATE fishing_catchs SET Dragon = Dragon + 1 WHERE player_id = 11;
Message: Unknown column 'Dragon' in 'field list'

Lua Script Error: [Action Interface]
data/actions/scripts/fishbowl.lua:eek:nUse
data/actions/scripts/fishbowl.lua:55: attempt to call method 'getId' (a nil value)
stack traceback:
[C]: in function 'getId'
data/actions/scripts/fishbowl.lua:55: in function <data/actions/scripts/fishbowl.lua:8>
 
[Error - mysql_real_query] Query: UPDATE fishing_catchs SET Dragon = Dragon + 1 WHERE player_id = 11;
Message: Unknown column 'Dragon' in 'field list'
[Error - mysql_real_query] Query: UPDATE fishing_catchs SET Dragon = Dragon + 1 WHERE player_id = 11;
Message: Unknown column 'Dragon' in 'field list'

Lua Script Error: [Action Interface]
data/actions/scripts/fishbowl.lua:eek:nUse
data/actions/scripts/fishbowl.lua:55: attempt to call method 'getId' (a nil value)
stack traceback:
[C]: in function 'getId'
data/actions/scripts/fishbowl.lua:55: in function <data/actions/scripts/fishbowl.lua:8>


Propably it should be inside function addPlayerCatch:
Code:
    db.query("UPDATE `fishing_catchs` SET `amount` = amount + "..amount.." WHERE `player_id` = "..playerId.." and `name` = `"..name.."`;")
 
Last edited:
Change
Code:
function addPlayerCatch(playerId, name, amount)
    db.query("UPDATE `fishing_catchs` SET `"..name.."` = `"..name.."` + "..amount.." WHERE `player_id` = "..playerId..";")
end

for

Code:
function addPlayerCatch(playerId, name, amount)
    db.query("UPDATE `fishing_catchs` SET `amount` = `amount` + "..amount.." WHERE `player_id` = "..playerId.." and `name` = "..name..";")
end
 
Change
Code:
function addPlayerCatch(playerId, name, amount)
    db.query("UPDATE `fishing_catchs` SET `"..name.."` = `"..name.."` + "..amount.." WHERE `player_id` = "..playerId..";")
end

for

Code:
function addPlayerCatch(playerId, name, amount)
    db.query("UPDATE `fishing_catchs` SET `amount` = `amount` + "..amount.." WHERE `player_id` = "..playerId.." and `name` = "..name..";")
end

Code:
[Error - mysql_real_query] Query: UPDATE `fishing_catchs` SET `amount` = `amount` + 1 WHERE `player_id` = 11 and `name` = Dragon;
Message: Unknown column 'Dragon' in 'where clause'

i get this error now
 
Code:
[Error - mysql_real_query] Query: UPDATE `fishing_catchs` SET `amount` = `amount` + 1 WHERE `player_id` = 11 and `name` = Dragon;
Message: Unknown column 'Dragon' in 'where clause'

i get this error now

Try this (not tested)
Code:
function addPlayerCatch(playerId, name, amount)
    db.query("INSERT INTO `fishing_catchs` (`player_id`, `name`, `amount`) VALUES ("..playerId..", \""..name.."\", 1) ON DUPLICATE KEY UPDATE `amount` = `amount` + "..amount..";")
end
 
Try this (not tested)
Code:
function addPlayerCatch(playerId, name, amount)
    db.query("INSERT INTO `fishing_catchs` (`player_id`, `name`, `amount`) VALUES ("..playerId..", \""..name.."\", 1) ON DUPLICATE KEY UPDATE `amount` = `amount` + "..amount..";")
end
that fixes the database problem but i still have this one if tried changing it to player:getid but no luck
Code:
data/actions/scripts/fishbowl.lua:onUse
data/actions/scripts/fishbowl.lua:55: attempt to call method 'getId' (a nil value)
stack traceback:
        [C]: in function 'getId'
        data/actions/scripts/fishbowl.lua:55: in function <data/actions/scripts/fishbowl.lua:8>
 
that fixes the database problem but i still have this one if tried changing it to player:getid but no luck
Code:
data/actions/scripts/fishbowl.lua:onUse
data/actions/scripts/fishbowl.lua:55: attempt to call method 'getId' (a nil value)
stack traceback:
        [C]: in function 'getId'
        data/actions/scripts/fishbowl.lua:55: in function <data/actions/scripts/fishbowl.lua:8>

I'm not sure how it should work.
Try test if target is a monster before line 55.
If target isn't a monster then return false.
 
I got this error

[Error - mysql_real_query] Query: SELECT `id` FROM `players` WHERE `name` = ; Message: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 [Error - mysql_store_result] Query: SELECT `id` FROM `players` WHERE `name` = ; Message: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1

Also got this error with:

player:addSkillTry(SKILL_FISHING, 1)
 
Last edited:
i keep getting this error
unknown.png
and cant get your mysql

function addPlayerCatch(playerId, name, amount)
db.query("INSERT INTO fishing_catchs (player_id, name, amount) VALUES ("..playerId..", \""..name.."\", 1) ON DUPLICATE KEY UPDATE amount = amount + "..amount..";")
end

to run it keeps saying there is an error around the word function ! if anyone could pm me or help that would be stellar! thank you !!!
 
Lua:
function addPlayerCatch(playerId, name, amount)
    db.query("UPDATE `fishing_catchs` SET `amount` = `amount` + "..amount.." WHERE `player_id` = "..playerId.." and `name` = '"..name.."';")
end
 
im not tossing any errors any more but i cant get the monsters to release from the fishing bowl? and the mysql file stopped saying errors but it doesnt announce on the server that i caught any thing? thats not really an issue or concern i just wanna be able to relase the monster any idea on what i could be missing ? thank you
 
Back
Top