• 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 Xikini's Free Scripting Service TFS 1.3

Status
Not open for further replies.

Xikini

I whore myself out for likes
Senator
Joined
Nov 17, 2010
Messages
6,909
Solutions
589
Reaction score
5,542
Please request
actions / creatureevents / globalevents / npcs / movements / talkactions

Do not request
spells / weapons / monsters / source editing / database queries

My goal of this thread is to learn TFS 1.3 scripting.

------------------------------------
Support

If you have an issue with one of my scripts, I will attempt to help you, but not in this thread.
Make a thread in the support board.
Ensure to follow all rules of the support board.
Without all neccesary information it's impossible to help you.

------------------------------------
I will only be scripting for TFS 1.3

Not TFS 1.1 / 1.2
Not OTServBR / OTX
and certainly not TFS 0.4

When requesting a script, don't ask for "this script I saw on super popular OT".

I don't care where the idea came from.
I don't want to see a video of the script in action.

I'm here to learn how to script better.
Just describe what the script is supposed to do, and I'll try to make it.

Any script that I make in response to a request from this thread will be shared publically, here, in this thread.

I'm not going to make anything in private, so post your request in this thread only.
Please, for the love of god, don't pm me asking to make a script.
I will actually add you to my ignore list if you do that.
--------------

Anyways!

Thanks for coming by and checking the thread out.
If you think there is a better way to script something, feel free to let me know.
I'm here to learn.

Cheers,

Xikini

----

Completed Scripts

DPS Dummy -> using RevScripts
!playerinfo character name -> using RevScripts
Positional Text talkaction -> using RevScripts
||--> Updated version that can use text & effects
Vocational Item Bonus's -> using RevScripts
||--> Updated version with easier config.
Simple damge buff potion -> using Revscripts
Kill monster in specific area, remove stone for x seconds -> using RevScripts
Training Room Teleporter -> using RevScripts
Lever that removes/adds/transforms objects or ground tiles -> using RevScripts
Loot from monster goes into single backpack, no matter how much loot there is.
Extra loot in monsters, based on chance and tier list -> using RevScripts
||--> Updated version that allows specific monsters to have their own loot table
Random Item chest that disappears after use, and respawns after x time -> using RevScripts
Multiple players required to open passageway.
Monster Arena Lever (x amount of waves, complete all waves, teleport appears) -> using RevScripts
Daily Boosted Creatures (experience & loot chance of items)
||--> Updated main file of boosted creatures, so that it triggers at midnight, instead of when the server starts up.
Reward Chest - Extremely simple. -> using Revscripts
Simple Npc that can sell an item, via text.

----

Extremely useful libs that I use quite often.

data/lib/core/player.lua
Give player items by table

data/lib/core/container.lua
getContainerFreeSlots

----

To-Do List

Shalaby - Player death counter. (Movement and talkaction)
Shalaby - Npc kill monster task, with item reward.
Shalaby - Boss respawn after x time.

-------

Last spot I've read messages
 
Last edited:
Thanks for the last script. @Xikini

Create a damage formula for each vocation. My general idea is that sorcerers have more damage than druids.

My script (default):
LUA:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 4.3) + 32
    local max = (level / 5) + (magicLevel * 7.4) + 48
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(creature, variant, isHotkey)
    return combat:execute(creature, variant)
end
LUA:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH)

function onGetFormulaValues(player, level, magicLevel)
    local min = 0
    local max = 0
    local vocation = player:getVocation():getId()
 
    if vocation == 1 then
        min = (level / 5) + (magicLevel * 4.3) + 132
        max = (level / 5) + (magicLevel * 7.4) + 148
    elseif vocation == 2 then
        min = (level / 5) + (magicLevel * 4.3) + 32
        max = (level / 5) + (magicLevel * 7.4) + 48
    end
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(creature, variant, isHotkey)
    return combat:execute(creature, variant)
end
 
The last script also worked perfectly, thanks. @Xikini

I would like the NPC to check if the player has a premium account.
If you don't have it, follow the list price.
If you do, buy the items for 20% more

NPC (default):
LUA:
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()                        end

local shopModule = ShopModule:new()
npcHandler:addModule(shopModule)

shopModule:addBuyableItem({'devil helmet'}, 5954, 5000, 1, 'demon horn')
shopModule:addBuyableItem({'mini mummy'}, 11207, 5000, 1, 'mini mummy')
shopModule:addBuyableItem({'heaven blossom'}, 5921, 5000, 1, 'heaven blossom')
shopModule:addBuyableItem({'stone wing'}, 11195, 5000, 1, 'stone wing')


npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
@nefinoo your "Monster Arena Lever (x amount of waves, complete all waves, teleport appears)" is finished.

I was semi-absent for awhile soo... sorry if you no longer need this

bandicam-2021-02-08-07-09-13-500.gif

Untitled.png
LUA:
--[[
____  ___.__ __   .__       .__ 
\   \/  /|__|  | _|__| ____ |__|
 \     / |  |  |/ /  |/    \|  |
 /     \ |  |    <|  |   |  \  |
/___/\  \|__|__|_ \__|___|  /__|
      \_/        \/       \/    

]]--

local event = {
    monsters = {
        {"rat", "rat", "rat"},                  -- wave 1
        {"cave rat", "cave rat", "cave rat"},   -- wave 2 -- you can add infinite waves.
        {"troll", "troll", "troll"},            -- wave 3
        {"cyclops", "cyclops", "cyclops smith"} -- wave final. (boss?)
    },
    spawnArea = {Position(259, 233, 7), Position(269, 237, 7)}, -- {top_Left_Corner, bottom_Right_Corner}
    leverIds = {1945, 1946}, -- left, right
    leverActionId = 45000,
    teleportTimer = 30, -- how long the teleport stays
    teleportDestination = Position(264, 230, 7),
   
    creatures = {}, -- don't touch
    currentWave = 0 -- don't touch
}

local function verifyEventCreatures()
    if #event.creatures > 0 then
        local creature = nil
        for pid = #event.creatures, 1, -1 do
            creature = Creature(event.creatures[pid][1])
            if not creature then
                table.remove(event.creatures, pid)
            end
        end
    end
end

local function spawnEventCreatures(wave, indexTracker)
    local attempts = 0
    local randomPosition = nil
    local creature = nil
    while attempts < 20 do
        randomPosition = Position(math.random(event.spawnArea[1].x, event.spawnArea[2].x), math.random(event.spawnArea[1].y, event.spawnArea[2].y), math.random(event.spawnArea[1].z, event.spawnArea[2].z))
        creature = Game.createMonster(event.monsters[wave][indexTracker], randomPosition, false, false)
        if not creature then
            tile = Tile(randomPosition)
            if tile and tile:isWalkable() and not Creature(tile:getTopCreature()) then
                creature = Game.createMonster(event.monsters[wave][indexTracker], randomPosition, false, true)
            end
        end
        if creature then
            indexTracker = indexTracker + 1
            table.insert(event.creatures, {creature:getId()})
            break
        end
        attempts = attempts + 1
    end
    if indexTracker <= #event.monsters[wave] then
        addEvent(spawnEventCreatures, 333, wave, indexTracker)
    end
end

local function flopLever(position, leverId, transformTo)
    Tile(position):getItemById(leverId):transform(transformTo)
end

local function removeLever(position, leverId)
    Tile(position):getItemById(leverId):remove()
end

local function createLever(position, leverId, actionId)
    local lever = Game.createItem(leverId, 1, position)
    lever:setActionId(actionId)
end

local function removeMagicForcefield(position)
    Tile(position):getItemById(1387):remove()
end

local function createMagicForcefield(position, destination)
    local magicForcefield = Game.createItem(1387, 1, position)
    magicForcefield:setDestination(destination)
end

local function countDown(timer, position)
    if timer % 5 == 0 and timer ~= 0 then
        for _, creature in pairs(Game.getPlayers()) do
            creature:say(timer, TALKTYPE_MONSTER_SAY, false, nil, position)
            break
        end
    end
    if timer > 0 then
        addEvent(countDown, 1000, timer - 1, position)
    end
end

local function monitorEvent(leverPosition)
    verifyEventCreatures()
    if #event.creatures > 0 then
        addEvent(monitorEvent, 1000, leverPosition)
        return
    end
    addEvent(Position.sendMagicEffect, 500, leverPosition, CONST_ME_POFF)
    addEvent(Position.sendMagicEffect, 1500, leverPosition, CONST_ME_POFF)
    addEvent(createLever, 2500, leverPosition, event.leverIds[1], event.leverActionId)
    addEvent(Position.sendMagicEffect, 2500, leverPosition, CONST_ME_MORTAREA)
end

local function eventManager(leverPosition)
    flopLever(leverPosition, event.leverIds[1], event.leverIds[2])
    addEvent(Position.sendMagicEffect, 500, leverPosition, CONST_ME_POFF)
    addEvent(Position.sendMagicEffect, 1500, leverPosition, CONST_ME_POFF)
    addEvent(removeLever, 2500, leverPosition, event.leverIds[2])
    if event.currentWave + 1 > #event.monsters then
        addEvent(createMagicForcefield, 2500, leverPosition, event.teleportDestination)
        addEvent(countDown, 2500, event.teleportTimer, leverPosition)
        addEvent(removeMagicForcefield, (1000 * event.teleportTimer) + 2500, leverPosition)
        addEvent(createLever, (1000 * event.teleportTimer) + 2500, leverPosition, event.leverIds[1], event.leverActionId)
        addEvent(Position.sendMagicEffect, (1000 * event.teleportTimer) + 2500, leverPosition, CONST_ME_MORTAREA)
        event.creatures = {}
        event.currentWave = 0
        return
    end
    event.currentWave = event.currentWave + 1
    addEvent(Position.sendMagicEffect, 2500, leverPosition, CONST_ME_FIREAREA)
    addEvent(spawnEventCreatures, 5000, event.currentWave, 1)
    addEvent(monitorEvent, 7500, leverPosition)
end


local monsterWaveEvent = Action()

function monsterWaveEvent.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if item.itemid == event.leverIds[1] then
        eventManager(toPosition)
    end
    return true
end

monsterWaveEvent:aid(event.leverActionId)
monsterWaveEvent:register()
 
@AbraxasCal @Loney

I spent more time then I care to admit trying to increase the monster loot chance..

BUT I FINALLY FIGURED OUT A WAY TO DO IT!
Fuck yeah.

Alright. xD

So this script will choose X amount of monsters and 'boost' them.
Boosted monsters can give extra experience, and can give extra loot chance percent.

Untitled.png

Install instructions.

Inside data\events\scripts\player.lua
Find this function function Player:onGainExperience(source, exp, rawExp)
Paste the code from below above this line
return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
LUA:
    if source:isMonster() and table.contains(boostedMonsters, source:getName():lower()) then
        exp = exp * boostedMonstersExperienceMultiplier
    end

Inside data\lib\core\container.lua
Find this function function Container.createLootItem(self, item)

Replace this line of code
LUA:
    if randvalue < item.chance then
With this code
LUA:
    local chance = item.chance
    if creatureName ~= nil and table.contains(boostedMonsters, creatureName:lower()) then
        chance = chance * boostedMonstersLootChanceMultiplier
        if chance > MAX_LOOTCHANCE then
            chance = MAX_LOOTCHANCE
        end
    end
    if randvalue < chance then

Inside data\scripts\eventcallbacks\monster\default_onDropLoot.lua
Find this line local item = corpse:createLootItem(monsterLoot[i])
Replace with the code below
LUA:
local item = corpse:createLootItem(monsterLoot[i], self:getName())

And finally create a new lua file inside data\scripts
I called mine boostedMonsters.lua
Paste the following code. (which updated the boostedMonsters when you start-up the server.)
(If you want the boostedMonsters to only change at midnight, Use This Version instead)
LUA:
boostedMonsters = {}
boostedMonstersExperienceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double experience)
boostedMonstersLootChanceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double chance of loot.) (1.36% -> 2.72%)(88% -> 100%)

local boostedMonstersAmount = 2 -- how many arrays from boostedMonstersList will be chosen
-- NOTE: Ensure that this amount does not exceed the amount of arrays in boostedMonstersList.. or your server will crash.

local boostedMonstersList = {
    {"rat", "cave rat"}, -- setup like this, so an entire monster race can become boosted
    {"troll"},
    {"cyclops"}, -- don't put the same monster twice.. or bad things might happen. xP
    {"demon"},
    {"fire elemental"}
}

local function generateBoostedMonstersText()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            if i == #boostedMonsters then
                text = text .. " and "
            else
                text = text .. ", "
            end
        end
        text = text .. boostedMonsters[i]
    end
    text = "Today's boosted monsters are " .. text .. "."
    return text
end

local function chooseBoostedMonsters()
    local boostedMonstersCount = 0
    while boostedMonstersCount < boostedMonstersAmount do
        local randomMonster = math.random(#boostedMonstersList)
        if not table.contains(boostedMonsters, boostedMonstersList[randomMonster][1]:lower()) then
            for i = 1, #boostedMonstersList[randomMonster] do
                table.insert(boostedMonsters, boostedMonstersList[randomMonster][i]:lower())
            end
            boostedMonstersCount = boostedMonstersCount + 1
        end
    end
    print(generateBoostedMonstersText())
end

local global = GlobalEvent("globalEvent_boostedMonsters")

function global.onStartup()
    addEvent(chooseBoostedMonsters, 0)
    return true
end

global:register()


local loginEvent = CreatureEvent("onLogin_boostedMonsters")
loginEvent:type("login")

function loginEvent.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, generateBoostedMonstersText())
    return true
end

loginEvent:register()
 
Last edited:
@AbraxasCal @Loney

I spent more time then I care to admit trying to increase the monster loot chance..

BUT I FINALLY FIGURED OUT A WAY TO DO IT!
Fuck yeah.

Alright. xD

So this script will choose X amount of monsters and 'boost' them.
Boosted monsters can give extra experience, and can give extra loot chance percent.

View attachment 54765

Install instructions.

Inside data\events\scripts\player.lua
Find this function function Player:onGainExperience(source, exp, rawExp)
Paste the code from below above this line
return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
LUA:
    if source:isMonster() and table.contains(boostedMonsters, source:getName():lower()) then
        exp = exp * boostedMonstersExperienceMultiplier
    end

Inside data\lib\core\container.lua
Find this function function Container.createLootItem(self, item)

Replace this section of code
LUA:
function Container.createLootItem(self, item)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    if randvalue < item.chance then
        if ItemType(item.itemId):isStackable() then
            itemCount = randvalue % item.maxCount + 1
        else
            itemCount = 1
        end
    end

    if itemCount > 0 then
With this code
LUA:
function Container.createLootItem(self, item, creatureName)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    local chance = item.chance
    if creatureName ~= nil and table.contains(boostedMonsters, creatureName:lower()) then
        chance = chance * boostedMonstersLootChanceMultiplier
        if chance > MAX_LOOTCHANCE then
            chance = MAX_LOOTCHANCE
        end
    end
    if randvalue < chance then

Inside data\scripts\eventcallbacks\monster\default_onDropLoot.lua
Find this line local item = corpse:createLootItem(monsterLoot[i])
Replace with the code below
LUA:
local item = corpse:createLootItem(monsterLoot[i], self:getName())

And finally create a new lua file inside data\scripts
I called mine boostedMonsters.lua
Paste the following code.
LUA:
boostedMonsters = {}
boostedMonstersExperienceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double experience)
boostedMonstersLootChanceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double chance of loot.) (1.36% -> 2.72%)(88% -> 100%)

local boostedMonstersAmount = 2 -- how many arrays from boostedMonstersList will be chosen
-- NOTE: Ensure that this amount does not exceed the amount of arrays in boostedMonstersList.. or your server will crash.

local boostedMonstersList = {
    {"rat", "cave rat"}, -- setup like this, so an entire monster race can become boosted
    {"troll"},
    {"cyclops"}, -- don't put the same monster twice.. or bad things might happen. xP
    {"demon"},
    {"fire elemental"}
}

local function generateBoostedMonstersText()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            if i == #boostedMonsters then
                text = text .. " and "
            else
                text = text .. ", "
            end
        end
        text = text .. boostedMonsters[i]
    end
    text = "Today's boosted monsters are " .. text .. "."
    return text
end

local function chooseBoostedMonsters()
    local boostedMonstersCount = 0
    while boostedMonstersCount < boostedMonstersAmount do
        local randomMonster = math.random(#boostedMonstersList)
        if not table.contains(boostedMonsters, boostedMonstersList[randomMonster][1]:lower()) then
            for i = 1, #boostedMonstersList[randomMonster] do
                table.insert(boostedMonsters, boostedMonstersList[randomMonster][i]:lower())
            end
            boostedMonstersCount = boostedMonstersCount + 1
        end
    end
    print(generateBoostedMonstersText())
end

local global = GlobalEvent("globalEvent_boostedMonsters")

function global.onStartup()
    addEvent(chooseBoostedMonsters, 0)
    return true
end

global:register()


local loginEvent = CreatureEvent("onLogin_boostedMonsters")
loginEvent:type("login")

function loginEvent.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, generateBoostedMonstersText())
    return true
end

loginEvent:register()
Wow. Testing this tomorrow into my server.

Thank you very much @Xikini! Really appreciated.
 
@nefinoo your "Monster Arena Lever (x amount of waves, complete all waves, teleport appears)" is finished.

I was semi-absent for awhile soo... sorry if you no longer need this

View attachment 54695

LUA:
--[[
____  ___.__ __   .__       .__
\   \/  /|__|  | _|__| ____ |__|
\     / |  |  |/ /  |/    \|  |
/     \ |  |    <|  |   |  \  |
/___/\  \|__|__|_ \__|___|  /__|
      \_/        \/       \/   

]]--

local event = {
    monsters = {
        {"rat", "rat", "rat"},                  -- wave 1
        {"cave rat", "cave rat", "cave rat"},   -- wave 2 -- you can add infinite waves.
        {"troll", "troll", "troll"},            -- wave 3
        {"cyclops", "cyclops", "cyclops smith"} -- wave final. (boss?)
    },
    spawnArea = {Position(259, 233, 7), Position(269, 237, 7)}, -- {top_Left_Corner, bottom_Right_Corner}
    leverIds = {1945, 1946}, -- left, right
    leverActionId = 45000,
    teleportTimer = 30, -- how long the teleport stays
    teleportDestination = Position(264, 230, 7),
  
    creatures = {}, -- don't touch
    currentWave = 0 -- don't touch
}

local function verifyEventCreatures()
    if #event.creatures > 0 then
        local creature = nil
        for pid = #event.creatures, 1, -1 do
            creature = Creature(event.creatures[pid][1])
            if not creature then
                table.remove(event.creatures, pid)
            end
        end
    end
end

local function spawnEventCreatures(wave, indexTracker)
    local attempts = 0
    local randomPosition = nil
    local creature = nil
    while attempts < 20 do
        randomPosition = Position(math.random(event.spawnArea[1].x, event.spawnArea[2].x), math.random(event.spawnArea[1].y, event.spawnArea[2].y), math.random(event.spawnArea[1].z, event.spawnArea[2].z))
        creature = Game.createMonster(event.monsters[wave][indexTracker], randomPosition, false, false)
        if not creature then
            tile = Tile(randomPosition)
            if tile and tile:isWalkable() and not Creature(tile:getTopCreature()) then
                creature = Game.createMonster(event.monsters[wave][indexTracker], randomPosition, false, true)
            end
        end
        if creature then
            indexTracker = indexTracker + 1
            table.insert(event.creatures, {creature:getId()})
            break
        end
        attempts = attempts + 1
    end
    if indexTracker <= #event.monsters[wave] then
        addEvent(spawnEventCreatures, 333, wave, indexTracker)
    end
end

local function flopLever(position, leverId, transformTo)
    Tile(position):getItemById(leverId):transform(transformTo)
end

local function removeLever(position, leverId)
    Tile(position):getItemById(leverId):remove()
end

local function createLever(position, leverId, actionId)
    local lever = Game.createItem(leverId, 1, position)
    lever:setActionId(actionId)
end

local function removeMagicForcefield(position)
    Tile(position):getItemById(1387):remove()
end

local function createMagicForcefield(position, destination)
    local magicForcefield = Game.createItem(1387, 1, position)
    magicForcefield:setDestination(destination)
end

local function countDown(timer, position)
    if timer % 5 == 0 and timer ~= 0 then
        for _, creature in pairs(Game.getPlayers()) do
            creature:say(timer, TALKTYPE_MONSTER_SAY, false, nil, position)
            break
        end
    end
    if timer > 0 then
        addEvent(countDown, 1000, timer - 1, position)
    end
end

local function monitorEvent(leverPosition)
    verifyEventCreatures()
    if #event.creatures > 0 then
        addEvent(monitorEvent, 1000, leverPosition)
        return
    end
    addEvent(Position.sendMagicEffect, 500, leverPosition, CONST_ME_POFF)
    addEvent(Position.sendMagicEffect, 1500, leverPosition, CONST_ME_POFF)
    addEvent(createLever, 2500, leverPosition, event.leverIds[1], event.leverActionId)
    addEvent(Position.sendMagicEffect, 2500, leverPosition, CONST_ME_MORTAREA)
end

local function eventManager(leverPosition)
    flopLever(leverPosition, event.leverIds[1], event.leverIds[2])
    addEvent(Position.sendMagicEffect, 500, leverPosition, CONST_ME_POFF)
    addEvent(Position.sendMagicEffect, 1500, leverPosition, CONST_ME_POFF)
    addEvent(removeLever, 2500, leverPosition, event.leverIds[2])
    if event.currentWave + 1 > #event.monsters then
        addEvent(createMagicForcefield, 2500, leverPosition, event.teleportDestination)
        addEvent(countDown, 2500, event.teleportTimer, leverPosition)
        addEvent(removeMagicForcefield, (1000 * event.teleportTimer) + 2500, leverPosition)
        addEvent(createLever, (1000 * event.teleportTimer) + 2500, leverPosition, event.leverIds[1], event.leverActionId)
        addEvent(Position.sendMagicEffect, (1000 * event.teleportTimer) + 2500, leverPosition, CONST_ME_MORTAREA)
        event.creatures = {}
        event.currentWave = 0
        return
    end
    event.currentWave = event.currentWave + 1
    addEvent(Position.sendMagicEffect, 2500, leverPosition, CONST_ME_FIREAREA)
    addEvent(spawnEventCreatures, 5000, event.currentWave, 1)
    addEvent(monitorEvent, 7500, leverPosition)
end


local monsterWaveEvent = Action()

function monsterWaveEvent.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if item.itemid == event.leverIds[1] then
        eventManager(toPosition)
    end
    return true
end

monsterWaveEvent:aid(event.leverActionId)
monsterWaveEvent:register()
hello, could you put in to earn rewards?
 
hello, could you put in to earn rewards?
I specifically didn't add rewards, because it limits the scope of the script.

Getting the teleport to go somewhere, is the reward.

You could have it go to a reward room.
You could have it give a storage value.
You could get access to a hidden library.
It could send you back to town. (maybe previously you fell down a hole, and this room is the only way out)

--
However, if you explain what kind of reward system you want to implement, I can definitely help with that.
 
I specifically didn't add rewards, because it limits the scope of the script.

Getting the teleport to go somewhere, is the reward.

You could have it go to a reward room.
You could have it give a storage value.
You could get access to a hidden library.
It could send you back to town. (maybe previously you fell down a hole, and this room is the only way out)

--
However, if you explain what kind of reward system you want to implement, I can definitely help with that.
could you use id 2160 as a reward, could you also take the time to click the lever again? thanks
 
could you use id 2160 as a reward, could you also take the time to click the lever again? thanks
What do you mean.. click the lever again?

--
Well whichever. xD

Here's the simple reward chest.
LUA:
local storage = 45001 -- is also the actionId to put on chest in remere's
local reward = {2160, 1} -- {itemid, amount}

local actions_crystalCoinReward = Action()

function actions_crystalCoinReward.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(storage) ~= -1 then
        fromPosition:sendMagicEffect(CONST_ME_POFF)
        player:sendTextMessage(MESSAGE_INFO_DESCR, "The chest is empty.")
        return true
    end
    player:addItem(reward[1], reward[2], true)
    player:setStorageValue(storage, 1)
    return true
end

actions_crystalCoinReward:id(storage)
actions_crystalCoinReward:register()
 
Last edited:
1. Click on something and get reward easy and clean to configure
example
click on tree and get full hunter outfit, 15 platinum coins, 500 experience, dragon scale mail or
click on wall and get panda mount, 30 cc, 100 experience and some items

2. Working task npc easy to configure aswell
not exactly like Grizzly Addams, just simple to configure (task done=reward experience and money)

i looking for those scripts beacuse i trying a lot from threads from our forum and no one working good.

anyway u need to know, u doing great job, thanks
 
Last edited:
What do you mean.. click the lever again?

--
Well whichever. xD

Here's the simple reward chest.
LUA:
local storage = 45001 -- is also the actionId to put on chest in remere's
local reward = {2160, 1} -- {itemid, amount}

local actions_crystalCoinReward = Action()

function actions_crystalCoinReward.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(storage) ~= -1 then
        fromPosition:sendMagicEffect(CONST_ME_POFF)
        player:sendTextMessage(MESSAGE_INFO_DESCR, "The chest is empty.")
        return true
    end
    player:addItem(reward[1], reward[2], true)
    player:setStorageValue(storage, 1)
    return true
end

actions_crystalCoinReward:id(storage)
actions_crystalCoinReward:register()
thanks.
hello, could you make me a boss points system? killing a boss (configurable) earns one point, when the player has 20 points he gains 10% exp for 12 hours. thanks
 
@AbraxasCal @Loney

I spent more time then I care to admit trying to increase the monster loot chance..

BUT I FINALLY FIGURED OUT A WAY TO DO IT!
Fuck yeah.

Alright. xD

So this script will choose X amount of monsters and 'boost' them.
Boosted monsters can give extra experience, and can give extra loot chance percent.

View attachment 54765

Install instructions.

Inside data\events\scripts\player.lua
Find this function function Player:onGainExperience(source, exp, rawExp)
Paste the code from below above this line
return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
LUA:
    if source:isMonster() and table.contains(boostedMonsters, source:getName():lower()) then
        exp = exp * boostedMonstersExperienceMultiplier
    end

Inside data\lib\core\container.lua
Find this function function Container.createLootItem(self, item)

Replace this section of code
LUA:
function Container.createLootItem(self, item)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    if randvalue < item.chance then
With this code
LUA:
function Container.createLootItem(self, item, creatureName)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    local chance = item.chance
    if creatureName ~= nil and table.contains(boostedMonsters, creatureName:lower()) then
        chance = chance * boostedMonstersLootChanceMultiplier
        if chance > MAX_LOOTCHANCE then
            chance = MAX_LOOTCHANCE
        end
    end
    if randvalue < chance then

Inside data\scripts\eventcallbacks\monster\default_onDropLoot.lua
Find this line local item = corpse:createLootItem(monsterLoot[i])
Replace with the code below
LUA:
local item = corpse:createLootItem(monsterLoot[i], self:getName())

And finally create a new lua file inside data\scripts
I called mine boostedMonsters.lua
Paste the following code.
LUA:
boostedMonsters = {}
boostedMonstersExperienceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double experience)
boostedMonstersLootChanceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double chance of loot.) (1.36% -> 2.72%)(88% -> 100%)

local boostedMonstersAmount = 2 -- how many arrays from boostedMonstersList will be chosen
-- NOTE: Ensure that this amount does not exceed the amount of arrays in boostedMonstersList.. or your server will crash.

local boostedMonstersList = {
    {"rat", "cave rat"}, -- setup like this, so an entire monster race can become boosted
    {"troll"},
    {"cyclops"}, -- don't put the same monster twice.. or bad things might happen. xP
    {"demon"},
    {"fire elemental"}
}

local function generateBoostedMonstersText()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            if i == #boostedMonsters then
                text = text .. " and "
            else
                text = text .. ", "
            end
        end
        text = text .. boostedMonsters[i]
    end
    text = "Today's boosted monsters are " .. text .. "."
    return text
end

local function chooseBoostedMonsters()
    local boostedMonstersCount = 0
    while boostedMonstersCount < boostedMonstersAmount do
        local randomMonster = math.random(#boostedMonstersList)
        if not table.contains(boostedMonsters, boostedMonstersList[randomMonster][1]:lower()) then
            for i = 1, #boostedMonstersList[randomMonster] do
                table.insert(boostedMonsters, boostedMonstersList[randomMonster][i]:lower())
            end
            boostedMonstersCount = boostedMonstersCount + 1
        end
    end
    print(generateBoostedMonstersText())
end

local global = GlobalEvent("globalEvent_boostedMonsters")

function global.onStartup()
    addEvent(chooseBoostedMonsters, 0)
    return true
end

global:register()


local loginEvent = CreatureEvent("onLogin_boostedMonsters")
loginEvent:type("login")

function loginEvent.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, generateBoostedMonstersText())
    return true
end

loginEvent:register()

is it working random or from top of the list to the bottom of the monsters list?
 
@AbraxasCal @Loney

I spent more time then I care to admit trying to increase the monster loot chance..

BUT I FINALLY FIGURED OUT A WAY TO DO IT!
Fuck yeah.

Alright. xD

So this script will choose X amount of monsters and 'boost' them.
Boosted monsters can give extra experience, and can give extra loot chance percent.

View attachment 54765

Install instructions.

Inside data\events\scripts\player.lua
Find this function function Player:onGainExperience(source, exp, rawExp)
Paste the code from below above this line
return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
LUA:
    if source:isMonster() and table.contains(boostedMonsters, source:getName():lower()) then
        exp = exp * boostedMonstersExperienceMultiplier
    end

Inside data\lib\core\container.lua
Find this function function Container.createLootItem(self, item)

Replace this section of code
LUA:
function Container.createLootItem(self, item)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    if randvalue < item.chance then
With this code
LUA:
function Container.createLootItem(self, item, creatureName)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    local chance = item.chance
    if creatureName ~= nil and table.contains(boostedMonsters, creatureName:lower()) then
        chance = chance * boostedMonstersLootChanceMultiplier
        if chance > MAX_LOOTCHANCE then
            chance = MAX_LOOTCHANCE
        end
    end
    if randvalue < chance then

Inside data\scripts\eventcallbacks\monster\default_onDropLoot.lua
Find this line local item = corpse:createLootItem(monsterLoot[i])
Replace with the code below
LUA:
local item = corpse:createLootItem(monsterLoot[i], self:getName())

And finally create a new lua file inside data\scripts
I called mine boostedMonsters.lua
Paste the following code.
LUA:
boostedMonsters = {}
boostedMonstersExperienceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double experience)
boostedMonstersLootChanceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double chance of loot.) (1.36% -> 2.72%)(88% -> 100%)

local boostedMonstersAmount = 2 -- how many arrays from boostedMonstersList will be chosen
-- NOTE: Ensure that this amount does not exceed the amount of arrays in boostedMonstersList.. or your server will crash.

local boostedMonstersList = {
    {"rat", "cave rat"}, -- setup like this, so an entire monster race can become boosted
    {"troll"},
    {"cyclops"}, -- don't put the same monster twice.. or bad things might happen. xP
    {"demon"},
    {"fire elemental"}
}

local function generateBoostedMonstersText()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            if i == #boostedMonsters then
                text = text .. " and "
            else
                text = text .. ", "
            end
        end
        text = text .. boostedMonsters[i]
    end
    text = "Today's boosted monsters are " .. text .. "."
    return text
end

local function chooseBoostedMonsters()
    local boostedMonstersCount = 0
    while boostedMonstersCount < boostedMonstersAmount do
        local randomMonster = math.random(#boostedMonstersList)
        if not table.contains(boostedMonsters, boostedMonstersList[randomMonster][1]:lower()) then
            for i = 1, #boostedMonstersList[randomMonster] do
                table.insert(boostedMonsters, boostedMonstersList[randomMonster][i]:lower())
            end
            boostedMonstersCount = boostedMonstersCount + 1
        end
    end
    print(generateBoostedMonstersText())
end

local global = GlobalEvent("globalEvent_boostedMonsters")

function global.onStartup()
    addEvent(chooseBoostedMonsters, 0)
    return true
end

global:register()


local loginEvent = CreatureEvent("onLogin_boostedMonsters")
loginEvent:type("login")

function loginEvent.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, generateBoostedMonstersText())
    return true
end

loginEvent:register()
What about people that dont have data\scripts\eventcallbacks\monster\default_onDropLoot.lua (revscripts)
where it should go then? And wouldnt it be more convient to have it on talkaction? if its even possible
 
What about people that dont have data\scripts\eventcallbacks\monster\default_onDropLoot.lua (revscripts)
where it should go then?
If people are using an outdated version of TFS 1.3 that do not have the necessary files / updates.. There's not much I can do.

The only thing I can suggest is for developers using work-in-progress TFS versions like 1.3, is to maintain their distribution with necessary updates.

And wouldnt it be more convient to have it on talkaction? if its even possible
No part of the script currently requires a talkaction?
You'd have to explain what you mean.
 

Xikini

I need a script that when killing a monster near the boss takes life away or rather reduces life to the boss as long as it is close to or in range
 
@AbraxasCal @Loney

I spent more time then I care to admit trying to increase the monster loot chance..

BUT I FINALLY FIGURED OUT A WAY TO DO IT!
Fuck yeah.

Alright. xD

So this script will choose X amount of monsters and 'boost' them.
Boosted monsters can give extra experience, and can give extra loot chance percent.

View attachment 54765

Install instructions.

Inside data\events\scripts\player.lua
Find this function function Player:onGainExperience(source, exp, rawExp)
Paste the code from below above this line
return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
LUA:
    if source:isMonster() and table.contains(boostedMonsters, source:getName():lower()) then
        exp = exp * boostedMonstersExperienceMultiplier
    end

Inside data\lib\core\container.lua
Find this function function Container.createLootItem(self, item)

Replace this section of code
LUA:
function Container.createLootItem(self, item)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    if randvalue < item.chance then
With this code
LUA:
function Container.createLootItem(self, item, creatureName)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom()
    local chance = item.chance
    if creatureName ~= nil and table.contains(boostedMonsters, creatureName:lower()) then
        chance = chance * boostedMonstersLootChanceMultiplier
        if chance > MAX_LOOTCHANCE then
            chance = MAX_LOOTCHANCE
        end
    end
    if randvalue < chance then

Inside data\scripts\eventcallbacks\monster\default_onDropLoot.lua
Find this line local item = corpse:createLootItem(monsterLoot[i])
Replace with the code below
LUA:
local item = corpse:createLootItem(monsterLoot[i], self:getName())

And finally create a new lua file inside data\scripts
I called mine boostedMonsters.lua
Paste the following code.
LUA:
boostedMonsters = {}
boostedMonstersExperienceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double experience)
boostedMonstersLootChanceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double chance of loot.) (1.36% -> 2.72%)(88% -> 100%)

local boostedMonstersAmount = 2 -- how many arrays from boostedMonstersList will be chosen
-- NOTE: Ensure that this amount does not exceed the amount of arrays in boostedMonstersList.. or your server will crash.

local boostedMonstersList = {
    {"rat", "cave rat"}, -- setup like this, so an entire monster race can become boosted
    {"troll"},
    {"cyclops"}, -- don't put the same monster twice.. or bad things might happen. xP
    {"demon"},
    {"fire elemental"}
}

local function generateBoostedMonstersText()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            if i == #boostedMonsters then
                text = text .. " and "
            else
                text = text .. ", "
            end
        end
        text = text .. boostedMonsters[i]
    end
    text = "Today's boosted monsters are " .. text .. "."
    return text
end

local function chooseBoostedMonsters()
    local boostedMonstersCount = 0
    while boostedMonstersCount < boostedMonstersAmount do
        local randomMonster = math.random(#boostedMonstersList)
        if not table.contains(boostedMonsters, boostedMonstersList[randomMonster][1]:lower()) then
            for i = 1, #boostedMonstersList[randomMonster] do
                table.insert(boostedMonsters, boostedMonstersList[randomMonster][i]:lower())
            end
            boostedMonstersCount = boostedMonstersCount + 1
        end
    end
    print(generateBoostedMonstersText())
end

local global = GlobalEvent("globalEvent_boostedMonsters")

function global.onStartup()
    addEvent(chooseBoostedMonsters, 0)
    return true
end

global:register()


local loginEvent = CreatureEvent("onLogin_boostedMonsters")
loginEvent:type("login")

function loginEvent.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, generateBoostedMonstersText())
    return true
end

loginEvent:register()

Well done
Using it for my server aswell
Thanks and have a great day
 
@Loney doesn't have a server save every 24 hours, so onStartUp wasn't a good option for them.

Discussed in private, we decided to have it update the monsters at midnight every night, instead of onStartUp.

Here's with that update.

LUA:
boostedMonsters = {}
boostedMonstersExperienceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double experience)
boostedMonstersLootChanceMultiplier = 2 -- 1 = default, 2 = 200% (aka, double chance of loot.) (1.36% -> 2.72%)(88% -> 100%)

local boostedMonstersAmount = 2 -- how many arrays from boostedMonstersList will be chosen
-- NOTE: Ensure that this amount does not exceed the amount of arrays in boostedMonstersAmount.. or your server will crash.

local boostedMonstersList = {
    {"rat", "cave rat"}, -- setup like this, so an entire monster race can become boosted
    {"troll"},
    {"cyclops"}, -- don't put the same monster twice.. or bad things might happen. xP
    {"demon"},
    {"fire elemental"}
}

local function generateBoostedMonstersText()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            if i == #boostedMonsters then
                text = text .. " and "
            else
                text = text .. ", "
            end
        end
        text = text .. boostedMonsters[i]
    end
    text = "Today's boosted monsters are " .. text .. "."
    return text
end

local function chooseBoostedMonsters()
    local boostedMonstersCount = 0
    while boostedMonstersCount < boostedMonstersAmount do
        local randomMonster = math.random(#boostedMonstersList)
        if not table.contains(boostedMonsters, boostedMonstersList[randomMonster][1]:lower()) then
            for i = 1, #boostedMonstersList[randomMonster] do
                table.insert(boostedMonsters, boostedMonstersList[randomMonster][i]:lower())
            end
            boostedMonstersCount = boostedMonstersCount + 1
        end
    end
end

local function splitWithComma(inputstring)
    local array = {}
    for str in string.gmatch(inputstring, "[^,]+") do
        table.insert(array, str)
    end
    return array
end

local function writeBoostedMonstersToFile()
    local text = ""
    for i = 1, #boostedMonsters do
        if text ~= "" then
            text = text ..  ","
        end
        text = text .. boostedMonsters[i]
    end
    local file = io.open("data\\logs\\boostedMonsters.txt", "w+")
    file:write(text)
    file:close()
end

local function updateBoostedMonstersFromFile()
    local file = io.open("data\\logs\\boostedMonsters.txt", "r")
    local text = file:read()
    boostedMonsters = splitWithComma(text)
    file:close()
end

local onStartup_boostedMonsters = GlobalEvent("onStartup_boostedMonsters")

function onStartup_boostedMonsters.onStartup()
    local file = io.open("data\\logs\\boostedMonsters.txt", "r")
    if file ~= nil then
        file:close()
        updateBoostedMonstersFromFile()
    else
        chooseBoostedMonsters()
        writeBoostedMonstersToFile()
    end
    local text = generateBoostedMonstersText()
    addEvent(print, 0, text)
    return true
end

onStartup_boostedMonsters:register()


local onTime_boostedMonsters = GlobalEvent("onTime_boostedMonsters")

function onTime_boostedMonsters.onTime()
    boostedMonsters = {}
    chooseBoostedMonsters()
    writeBoostedMonstersToFile()
    local text = generateBoostedMonstersText()
    print(text)
    Game.broadcastMessage(text)
    return true
end

onTime_boostedMonsters:time("00:00:00")
onTime_boostedMonsters:register()


local loginEvent = CreatureEvent("onLogin_boostedMonsters")
loginEvent:type("login")

function loginEvent.onLogin(player)
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, generateBoostedMonstersText())
    return true
end

loginEvent:register()
 
Status
Not open for further replies.
Back
Top