• 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.4.2

Xikini

I whore myself out for likes
Senator
Joined
Nov 17, 2010
Messages
6,838
Solutions
585
Reaction score
5,433
Request whatever you want, within reason.

Please do not request for things that require source editing or database queries.

------------------------------------
If I've reacted to your post, it means I've read it. 👍😍🤣😲🙁😡🤔😉

------------------------------------
Completed Requests

A boss that randomly creates effects on tiles, that when stepped on, gives the player increased damage/mitigation to that boss.
Kill monster and gain X% extra loot chance or Y% extra experience for Z minutes
A pack of 6 useful simple scripts.
-> (1) Simple quest npc
-> (2,3,4,5) use levers in specific order / stand with 4 players / use 4 objects / place items -> to open wall
-> (6) use lever to add/remove/replace objects
Wave type spell, with multiple effects
-> Same spell, but with default combat system
House market system. (owner places price on blackboard and object on the ground, other players buy with a lever)
Respawn System (closest anchor (like darks souls bonfire) / tavern / temple)
Vocation Death Protection (protect the noobs!)
Spell that shows area it will damage, before it strikes.
RAID SYSTEM - rebuilt in Lua, with some more features.
Modal Window - Teleport Item with saving/deleting of positions
Show top 3 Online Players (outfit, name, level) (as monsters, in set positions)
onLook function showing kill count of player.
Modal Window - Use Item -> choose reward.
Talkaction - !backpacks - to buy backpacks (or single items) anywhere. uses bank & current money on players
Quest/Event? Turn a bunch of objects with a monster, spawn portal.
Spawn Monsters, after they've all been killed, give global increased experience/loot in specific area's
Evolving Weapons - Kill X amount of specific creatures, evolve weapon and gain extra damage to those creatures.
Random Portals spawn at XX:XX time(s). (can exit 'off' portals, if you have the storage.)
Monster that adjusts speed based on target
Monster that increases damage output based on # of players nearby
Experience recovery Item. Die -> Use Item -> gain % of lost experience
Character Snapshot - Keeps track of all skills & level, for resetting later.
Fire Dagger - Physical Damage Melee Weapon, with % added damage
Players in specific level ranges don't lose skills/loot/experience, when they die.
Multiclient Limit Check - with admin account not being counted towards limit
Capacity Increasing Items
Upgradeable Protection Amulet - 10% to all elements
-> upgrade amulet, but for all items.
onKill - give reward to all players who dealt damage
-> example: give reward based on damage contribution
Quest Book - Record your quest progress into a book.
Stat System, using modal windows
Holy Tible (POI) - Require Item to use teleport tiles
Item Upgrade System
Skill Stages
-> individual stages for each skill type
-> talkaction to check rates (by @Extrodus)
Random Reward Item - gives different rewards based on vocation
Bounty Hunter System
NPC & Player Walk System (Follow Nodes to destination)
Health/Mana gain permanent - limited use items

------------------------------------
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 necessary information it's impossible to help you.

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

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.

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 publicly, 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
---------

P.S.
I've been doing free scripting service's on/off for awhile.
And if you want to see the previous threads, go check them here.

 
Last edited by a moderator:
Xikini,
I tried to make it myself but to no avail.

So here goes:

I have 10 different teleports in different places.
I would like it to always at 24:00, change access randomly.
E.g..
Teleport 1/2/3
Teleport 2/3/5
Teleport 4/2/1

In addition, if the player has the necessary storage (for each teleport different, then regardless of whether the teleport is open he will be able to use it.
I hope you understood.

It would also be extra if, for example, it would be possible to use an item that shows in the text of the book what teleports are active at a given time.

Without storing the information somewhere (aka: database query) there isn't a way to keep the same random teleports open when server save comes around.

So the only way I can script this is one of these 4 ways..

1) random portals spawn when server starts
2) no portals by default, but at 00:00 (midnight) the 3 random portals spawn
3) random portals spawn when server starts and at midnight the portals swap to new random locations
4) pseudo-random.. where we choose a 'seed' (the date) in advance to randomize with.
(Pseudo-random refers to numbers that appear random but are actually generated by a deterministic process.)

If your server save is at midnight, then option 1 technically works as you want.

--
Let me know what works for you.
 
Last edited:
Hi!

I had the idea to store the data in GLOBALSTROAGE.

Global event at 00:00 would change the value of this storage ?
From 2 to 3 from 4 to 8 etc ?
If this is imposible, maybe:

(2) no portals by default, but at 00:00 (midnight) the 3 random portals spawn.
 
Last edited:
Hi!

I had the idea to store the data in GLOBALSTROAGE.

Global event at 00:00 would change the value of this storage ?
From 2 to 3 from 4 to 8 etc ?
If this is imposible, maybe:

(2) no portals by default, but at 00:00 (midnight) the 3 random portals spawn.
globalstorage resets every time you restart the server.
It's not permanent.
It's literally just a global array. xD

and alright, we'll do #2
 
I want to request a script when you enter from the teleport, your skills and level change to x (modifiable) according to the vocation and when you go back out, you return to your normal level and skill.
 
This is the Boss Checker, used to check if the boss is alive or dead, and also to display the time remaining until the next boss respawn. If a player chooses the boss "Troll", they will only monitor the Troll to know when the respawn is due or if the boss has already been defeated. If the player does not want to monitor the Troll for information, they can reset the boss and choose another, like the "Dark Cleric", to see if the respawn is imminent. The modal window will indicate if the boss has appeared. Then, the player can go and defeat the boss. It's as simple as that. Did you understand? If not, we can drop the subject. Thank you for your attention.

why don't you use globalstorage to store the timestamp of the boss's death? and by checking whether the boss time is smaller or larger than the current os.time(), this way you can return whether he is alive according to the elapsed time or not.

1 - onkill to store the storage in globalstorage.
Lua:
if target:getName():lower == 'bossName' then
      Game.setStorageValue(storage, os.time())
end

2 - your own script returning this data.
Lua:
if Game.getStorageValue(storage) > os.time() then
      -- boss killed
      -- time to respawn = (storage - os.time()) to return the missing seconds and you transform them into hours
else
      -- boss spawned
end

Is this what you are looking for or did I misunderstand?
 
Hi!
Boosted creatures for 1.4.2?
I found this one (your job for 1.3).
This

But this script working onStartup.
Possibile to work onTime or Interval?
 
Is this what you are looking for

This is exactly what I needed; what you mentioned, I implemented and tested, but then I had a change of plans and no longer need to use 'Game.getStorageValue,' so I made adjustments to the source code. Subsequently, I created a script without using 'Game.getStorageValue' , allowing only the modal to check the boss's status, whether it is alive or deceased. In case of vitality, the modal is programmed to issue a broadcast notification. Currently, it effectively identifies the modal to check the boss's status, and the script is working well, but I will continue to improve it... hehe thank you.

I forgot to translate the script into English before recording the video hehe... so 'vivo,' which means alive in Portuguese, and 'morto,' which means dead, are correct.
 
Last edited:
The script you linked to is literally using onTime. lmao

I have this problem in console:

Code:
Lua Script Error: [Scripts Interface]
/var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:callback
/var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:62: attempt to index local 'file' (a nil value)
stack traceback:
        [C]: in function '__index'
        /var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:62: in function 'writeBoostedMonstersToFile'
        /var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:82: in function </var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:75>
 
Hi!

I had the idea to store the data in GLOBALSTROAGE.

Global event at 00:00 would change the value of this storage ?
From 2 to 3 from 4 to 8 etc ?
If this is imposible, maybe:

(2) no portals by default, but at 00:00 (midnight) the 3 random portals spawn.

tile under 5 coins, I have storage for.

bandicam2024-02-0802-30-24-544-ezgif.com-video-to-gif-converter.gif

data/scripts/randomPortals.lua
Lua:
local config = {
    spawnTimes = {"02:30:30", "02:30:40"},
    portalAmount = {min = 2, max = 4},
    portals = {
    --    [actionId & storage] = {spawnPosition, destination}
        [45038] = {spawnPosition = Position(1004, 1001, 7), destination = Position(1004, 1004, 7)},
        [45039] = {spawnPosition = Position(1005, 1001, 7), destination = Position(1005, 1004, 7)},
        [45040] = {spawnPosition = Position(1006, 1001, 7), destination = Position(1006, 1004, 7)},
        [45041] = {spawnPosition = Position(1007, 1001, 7), destination = Position(1007, 1004, 7)},
        [45042] = {spawnPosition = Position(1008, 1001, 7), destination = Position(1008, 1004, 7)}
    }
}

-- END OF CONFIG

local moveevent = MoveEvent()

function moveevent.onStepIn(creature, item, position, fromPosition)
    if not isPlayer(creature) then
        return true
    end
    local actionId = item:getActionId()
    local portal = Tile(config.portals[actionId].spawnPosition):getItemById(1387)
    if portal or creature:getStorageValue(actionId) == 1 then
        position:sendMagicEffect(CONST_ME_TELEPORT)
        creature:teleportTo(config.portals[actionId].destination)
        config.portals[actionId].destination:sendMagicEffect(CONST_ME_TELEPORT)
        return true
    end
    return true
end

for actionId, _ in pairs(config.portals) do
    moveevent:aid(actionId)
end
moveevent:register()


for _, spawnTime in pairs(config.spawnTimes) do
    local globalevent = GlobalEvent("randomPortals" .. spawnTime)
 
    function globalevent.onTime(interval)
        local rand = math.random(config.portalAmount.min, config.portalAmount.max)
        local portals = {}
        for k, v in pairs(config.portals) do
            local portal = Tile(v.spawnPosition):getItemById(1387)
            if portal then
                portal:remove()
            end
            portals[#portals + 1] = k
        end
        for i = 1, rand do
            rand = math.random(#portals)
            Game.createItem(1387, 1, config.portals[portals[rand]].spawnPosition)
            table.remove(portals, rand)
        end
        broadcastMessage("Random portals have spawned!", MESSAGE_STATUS_DEFAULT)
        return true
    end
 
    globalevent:time(spawnTime)
    globalevent:register()
end


local globalevent = GlobalEvent("onStartUp_randomPortals")

function globalevent.onStartup()
    for k, v in pairs(config.portals) do
        local tile = Tile(v.spawnPosition)
        if not tile then
            print("No tile at portal spawnPosition. (" .. k .. ")")
            return true
        end
        tile:getGround():setActionId(k)
    end
    return true
end

globalevent:register()
Post automatically merged:

----------------------

Request 2: A Creature that adjusts its speed according to the current target
As I have different chase scenes in an open-world game, it is a bit painful to adjust the monster's speed to the player level,
especially on lower-level players, this is troublesome.

  1. A creature that can adjust its speed to the speed of its current target player.​
  2. If a player is level 1 it should have the speed of a level 2.​
  3. If a player is level 2, it should have the speed of a level 3.​
(might be too easy)
------------------------


bandicam2024-02-0803-12-28-173-ezgif.com-video-to-gif-converter.gif

data/scripts/monsterSpeedAutoAdjust.lua
Lua:
local speedPerLevel = 1 -- (probably don't need to touch, it's just here in case your source gives more speed per level)
local monsterName = "valkyrie"

-- end of config

local function adjustSpeed(creatureId)
    local creature = Creature(creatureId)
    if not creature then
        return
    end
    local target = creature:getTarget()
    local targetSpeed = (target and target:isPlayer() and target:getBaseSpeed() or MonsterType(monsterName):baseSpeed()) + speedPerLevel
    local creatureSpeed = creature:getSpeed()
    local deltaSpeed = (creatureSpeed - targetSpeed) * -1
    if deltaSpeed ~= 0 then
        creature:changeSpeed(deltaSpeed)
    end
end


local creatureevent = CreatureEvent("onThink_monsterAdjustSpeedToTarget")

function creatureevent.onThink(creature, interval)
    local creatureId = creature:getId()
    adjustSpeed(creatureId)
    addEvent(adjustSpeed, 500, creatureId)
    return true
end

creatureevent:register()


local eventCallback = EventCallback

function eventCallback.onSpawn(creature, position, startup, artificial)
    if monsterName:lower() == creature:getName():lower() then
        creature:registerEvent("onThink_monsterAdjustSpeedToTarget")
    end
    return true
end

eventCallback:register(-666)
Post automatically merged:

I would like a script, probably in creatureScript format, that increases monster's damage according to the number of players in a certain range of that monster's current position, for example 4SQM.

bandicam2024-02-0804-00-56-658-ezgif.com-video-to-gif-converter.gif

data/scripts/monsterAdjustDamageBasedOnNearbyPlayers.lua

Lua:
local config = {
    ["valkyrie"] = {range = 4, increasePerPlayer = 1, damageChange = {flat = 0, percent = 200}}, -- flat adds first, then total damage increased by percent.
    ["orc berserker"] = {range = 4, increasePerPlayer = 1, damageChange = {flat = 1000, percent = 0}}     -- per 2 players
}

-- end of config


local function calculateDamage(damage, damageType, flat, percent, playerAmount)
    if damageType ~= 0 then
        flat = flat * playerAmount
        damage = damage + flat
        percent = percent * playerAmount
        return damage + (damage * (percent / 100))
    end
    return damage
end

local function damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    if attacker and attacker:isCreature() then
        local index = config[attacker:getName():lower()]
        if index then
            local spectators = Game.getSpectators(attacker:getPosition(), false, true, index.range, index.range, index.range, index.range)
            spectators = math.floor(#spectators / index.increasePerPlayer)
            primaryDamage = calculateDamage(primaryDamage, primaryType, index.damageChange.flat, index.damageChange.percent, spectators)
            secondaryDamage = calculateDamage(secondaryDamage, secondaryType, index.damageChange.flat, index.damageChange.percent, spectators)
        end
    end
    return primaryDamage, secondaryDamage
end

local healthChange = CreatureEvent("onHealthChange_monsterAdjustDamage")

function healthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

healthChange:register()


local manaChange = CreatureEvent("onManaChange_monsterAdjustDamage")

function manaChange.onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

manaChange:register()


local creatureevent = CreatureEvent("example")

function creatureevent.onLogin(player)
    player:registerEvent("onHealthChange_monsterAdjustDamage")
    player:registerEvent("onManaChange_monsterAdjustDamage")
    return true
end

creatureevent:register()

local eventCallback = EventCallback

function eventCallback.onSpawn(creature, position, startup, artificial)
    creature:registerEvent("onHealthChange_monsterAdjustDamage")
    return true
end

eventCallback:register(-666)
Post automatically merged:

[Script Request]
Recovery exp item, whenever character dies and uses this (item) will get back 70% of lost level.

Cumulative option added, so you can store multiple deaths worth of experience, or only the most recent death.

bandicam2024-02-0804-31-57-003-ezgif.com-video-to-gif-converter.gif

data/scripts/experienceRecoveryItem.lua
Lua:
local config = {
    itemId = 2344,
    percent = 70, -- 1-100
    cumulative = true,
    storageKeys = {experienceAtDeath = 45043, storedExperience = 45044}
}

-- END OF CONFIG

local action = Action()

function action.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local storedExperience = player:getStorageValue(config.storageKeys.storedExperience)
    if storedExperience <= 0 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "You have no stored experience to obtain.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF, player)
        return true
    end
    player:addExperience(storedExperience, true)
    player:setStorageValue(config.storageKeys.storedExperience, -1)
    player:getPosition():sendMagicEffect(CONST_ME_HEARTS)
    item:remove(1)
    return true
end

action:id(config.itemId)
action:register()


local creatureevent = CreatureEvent("onDeath_ExperienceRecoveryItem")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    creature:setStorageValue(config.storageKeys.experienceAtDeath, creature:getExperience())
    return true
end

creatureevent:register()


local creatureevent = CreatureEvent("onLogin_ExperienceRecoveryItem")

function creatureevent.onLogin(player)
    local experienceAtDeath = player:getStorageValue(config.storageKeys.experienceAtDeath)
    if experienceAtDeath ~= -1 then
        local storedExperience = math.floor((experienceAtDeath - player:getExperience()) * (config.percent / 100))
        if config.cumulative then
            storedExperience = storedExperience + math.max(player:getStorageValue(config.storageKeys.storedExperience, 0))
        end
        player:setStorageValue(config.storageKeys.storedExperience, storedExperience)
        player:setStorageValue(config.storageKeys.experienceAtDeath, -1)
    end
    player:registerEvent("onDeath_ExperienceRecoveryItem")
    return true
end

creatureevent:register()
Post automatically merged:

I have this problem in console:

Code:
Lua Script Error: [Scripts Interface]
/var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:callback
/var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:62: attempt to index local 'file' (a nil value)
stack traceback:
        [C]: in function '__index'
        /var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:62: in function 'writeBoostedMonstersToFile'
        /var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:82: in function </var/www/tfs_old/data/scripts/bosted/bosted_creature.lua:75>
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 necessary information it's impossible to help you.
 
Last edited:
I want to request a script when you enter from the teleport, your skills and level change to x (modifiable) according to the vocation and when you go back out, you return to your normal level and skill.

This could be scripted a lot better, but I can't be fucked. lmao
Looks like ass, but it works.

bandicam2024-02-0806-47-31-944-ezgif.com-video-to-gif-converter.gif

data/scripts/onStepIn_snapshotCharacter.lua
Lua:
local config = {
    teleportIn = { -- snapshots character
        actionId = 45045,
        destination = Position(981, 1001, 7)
    },
    teleportOut = { -- resets character
        actionId = 45046,
        destination = Position(985, 1001, 7)
    },
    storageKeys = {
        level          = 45047,
        magic          = 45048,
        magicTries     = 45049,
        fist           = 45050,
        fistTries      = 45051,
        club           = 45052,
        clubTries      = 45053,
        sword          = 45054,
        swordTries     = 45055,
        axe            = 45056,
        axeTries       = 45057,
        distance       = 45058,
        distanceTries  = 45059,
        shielding      = 45060,
        shieldingTries = 45061,
        fishing        = 45062,
        fishingTries   = 45063,
    },
    setValue = {
        [{1, 5, 2, 6}] = { -- mages
            level     = 200,
            magic     = 65,
            fist      = 20,
            club      = 20,
            sword     = 20,
            axe       = 20,
            distance  = 20,
            shielding = 20,
            fishing   = 50
        },
        [{3, 7}] = { -- paladins
            level     = 200,
            magic     = 25,
            fist      = 25,
            club      = 25,
            sword     = 25,
            axe       = 25,
            distance  = 50,
            shielding = 25,
            fishing   = 50
        },
        [{4, 8}] = { -- knights
            level     = 200,
            magic     = 5,
            fist      = 50,
            club      = 50,
            sword     = 50,
            axe       = 50,
            distance  = 25,
            shielding = 50,
            fishing   = 70
        }
    }
}


local moveevent = MoveEvent()

function moveevent.onStepIn(creature, item, position, fromPosition)
    if not creature:isPlayer() then
        return true
    end
    
    local actionId = item:getActionId()
    
    if config.teleportIn.actionId == actionId then
        if creature:getStorageValue(config.storageKeys.level) ~= -1 then
            creature:sendTextMessage(MESSAGE_STATUS_SMALL, "This character already has a snapshot.")
            creature:teleportTo(fromPosition)
            return true
        end
        
        local vocationId = creature:getVocation():getId()
        for k, v in pairs(config.setValue) do
            if table.contains(k, vocationId) then
                creature:setStorageValue(config.storageKeys.level, creature:getExperience())
                creature:addLevel(v.level - creature:getLevel(), true)
                
                creature:setStorageValue(config.storageKeys.magic, creature:getMagicLevel())
                creature:setStorageValue(config.storageKeys.magicTries, creature:getManaSpent())
                creature:addMagicLevel(v.magic - creature:getMagicLevel())
                
                creature:setStorageValue(config.storageKeys.fist, creature:getSkillLevel(SKILL_FIST))
                creature:setStorageValue(config.storageKeys.fistTries, creature:getSkillTries(SKILL_FIST))
                creature:addSkillLevel(SKILL_FIST, v.fist - creature:getSkillLevel(SKILL_FIST))
                
                creature:setStorageValue(config.storageKeys.club, creature:getSkillLevel(SKILL_CLUB))
                creature:setStorageValue(config.storageKeys.clubTries, creature:getSkillTries(SKILL_CLUB))
                creature:addSkillLevel(SKILL_CLUB, v.club - creature:getSkillLevel(SKILL_CLUB))
                
                creature:setStorageValue(config.storageKeys.sword, creature:getSkillLevel(SKILL_SWORD))
                creature:setStorageValue(config.storageKeys.swordTries, creature:getSkillTries(SKILL_SWORD))
                creature:addSkillLevel(SKILL_SWORD, v.sword - creature:getSkillLevel(SKILL_SWORD))
                
                creature:setStorageValue(config.storageKeys.axe, creature:getSkillLevel(SKILL_AXE))
                creature:setStorageValue(config.storageKeys.axeTries, creature:getSkillTries(SKILL_AXE))
                creature:addSkillLevel(SKILL_AXE, v.axe - creature:getSkillLevel(SKILL_AXE))
                
                creature:setStorageValue(config.storageKeys.distance, creature:getSkillLevel(SKILL_DISTANCE))
                creature:setStorageValue(config.storageKeys.distanceTries, creature:getSkillTries(SKILL_DISTANCE))
                creature:addSkillLevel(SKILL_DISTANCE, v.distance - creature:getSkillLevel(SKILL_DISTANCE))
                
                creature:setStorageValue(config.storageKeys.shielding, creature:getSkillLevel(SKILL_SHIELD))
                creature:setStorageValue(config.storageKeys.shieldingTries, creature:getSkillTries(SKILL_SHIELD))
                creature:addSkillLevel(SKILL_SHIELD, v.shielding - creature:getSkillLevel(SKILL_SHIELD))
                
                creature:setStorageValue(config.storageKeys.fishing, creature:getSkillLevel(SKILL_FISHING))
                creature:setStorageValue(config.storageKeys.fishingTries, creature:getSkillTries(SKILL_FISHING))
                creature:addSkillLevel(SKILL_FISHING, v.fishing - creature:getSkillLevel(SKILL_FISHING))
                
                creature:sendTextMessage(MESSAGE_STATUS_SMALL, "Character has received a snapshot.")
                creature:teleportTo(config.teleportIn.destination)
                return true
            end
        end
        
        creature:sendTextMessage(MESSAGE_STATUS_SMALL, "Vocation snapshot information unable to be gathered. Contact Admin.") -- table not setup with this vocation
        creature:teleportTo(fromPosition)
        return true
        
    else
        if creature:getStorageValue(config.storageKeys.level) == -1 then
            creature:sendTextMessage(MESSAGE_STATUS_SMALL, "This character does not have a snapshot.")
            creature:teleportTo(fromPosition)
            return true
        end
        
        local experienceAmount = creature:getStorageValue(config.storageKeys.level) - creature:getExperience()
        creature:setStorageValue(config.storageKeys.level, -1)
        if experienceAmount > 0 then
            creature:addExperience(experienceAmount)
        else
            experienceAmount = experienceAmount * -1
            creature:removeExperience(experienceAmount)
        end
        
        local magicLevel = creature:getStorageValue(config.storageKeys.magic) - creature:getMagicLevel()
        creature:addMagicLevel(magicLevel)
        
        local manaSpentAmount = creature:getStorageValue(config.storageKeys.magicTries) - creature:getManaSpent()
        creature:setStorageValue(config.storageKeys.magicTries, -1)
        if manaSpentAmount > 0 then
            creature:addManaSpent(manaSpentAmount)
        else
            manaSpentAmount = manaSpentAmount * -1
            creature:removeManaSpent(manaSpentAmount)
        end
        
        local fistingLevel = creature:getStorageValue(config.storageKeys.fist) - creature:getSkillLevel(SKILL_FIST)
        creature:addSkillLevel(SKILL_FIST, fistingLevel)
        
        local fistTriesAmount = creature:getStorageValue(config.storageKeys.fistTries) - creature:getSkillTries(SKILL_FIST)
        creature:setStorageValue(config.storageKeys.fistTries, -1)
        if fistTriesAmount > 0 then
            creature:addSkillTries(SKILL_FIST, fistTriesAmount)
        else
            fistTriesAmount = fistTriesAmount * -1
            creature:removeSkillTries(SKILL_FIST, fistTriesAmount)
        end
        
        local clubingLevel = creature:getStorageValue(config.storageKeys.club) - creature:getSkillLevel(SKILL_CLUB)
        creature:addSkillLevel(SKILL_CLUB, clubingLevel)
        
        local clubTriesAmount = creature:getStorageValue(config.storageKeys.clubTries) - creature:getSkillTries(SKILL_CLUB)
        creature:setStorageValue(config.storageKeys.clubTries, -1)
        if clubTriesAmount > 0 then
            creature:addSkillTries(SKILL_CLUB, clubTriesAmount)
        else
            clubTriesAmount = clubTriesAmount * -1
            creature:removeSkillTries(SKILL_CLUB, clubTriesAmount)
        end
        
        local swordingLevel = creature:getStorageValue(config.storageKeys.sword) - creature:getSkillLevel(SKILL_SWORD)
        creature:addSkillLevel(SKILL_SWORD, swordingLevel)
        
        local swordTriesAmount = creature:getStorageValue(config.storageKeys.swordTries) - creature:getSkillTries(SKILL_SWORD)
        creature:setStorageValue(config.storageKeys.swordTries, -1)
        if swordTriesAmount > 0 then
            creature:addSkillTries(SKILL_SWORD, swordTriesAmount)
        else
            swordTriesAmount = swordTriesAmount * -1
            creature:removeSkillTries(SKILL_SWORD, swordTriesAmount)
        end
        
        local axeingLevel = creature:getStorageValue(config.storageKeys.axe) - creature:getSkillLevel(SKILL_AXE)
        creature:addSkillLevel(SKILL_AXE, axeingLevel)
        
        local axeTriesAmount = creature:getStorageValue(config.storageKeys.axeTries) - creature:getSkillTries(SKILL_AXE)
        creature:setStorageValue(config.storageKeys.axeTries, -1)
        if axeTriesAmount > 0 then
            creature:addSkillTries(SKILL_AXE, axeTriesAmount)
        else
            axeTriesAmount = axeTriesAmount * -1
            creature:removeSkillTries(SKILL_AXE, axeTriesAmount)
        end
        
        local distanceLevel = creature:getStorageValue(config.storageKeys.distance) - creature:getSkillLevel(SKILL_DISTANCE)
        creature:addSkillLevel(SKILL_DISTANCE, distanceLevel)
        
        local distanceTriesAmount = creature:getStorageValue(config.storageKeys.distanceTries) - creature:getSkillTries(SKILL_DISTANCE)
        creature:setStorageValue(config.storageKeys.distanceTries, -1)
        if distanceTriesAmount > 0 then
            creature:addSkillTries(SKILL_DISTANCE, distanceTriesAmount)
        else
            distanceTriesAmount = distanceTriesAmount * -1
            creature:removeSkillTries(SKILL_DISTANCE, distanceTriesAmount)
        end
        
        local shieldingLevel = creature:getStorageValue(config.storageKeys.shielding) - creature:getSkillLevel(SKILL_SHIELD)
        creature:addSkillLevel(SKILL_SHIELD, shieldingLevel)
        
        local shieldingTriesAmount = creature:getStorageValue(config.storageKeys.shieldingTries) - creature:getSkillTries(SKILL_SHIELD)
        creature:setStorageValue(config.storageKeys.shieldingTries, -1)
        if shieldingTriesAmount > 0 then
            creature:addSkillTries(SKILL_SHIELD, shieldingTriesAmount)
        else
            shieldingTriesAmount = shieldingTriesAmount * -1
            creature:removeSkillTries(SKILL_SHIELD, shieldingTriesAmount)
        end
        
        local fishingLevel = creature:getStorageValue(config.storageKeys.fishing) - creature:getSkillLevel(SKILL_FISHING)
        creature:addSkillLevel(SKILL_FISHING, fishingLevel)
        
        local fishingTriesAmount = creature:getStorageValue(config.storageKeys.fishingTries) - creature:getSkillTries(SKILL_FISHING)
        creature:setStorageValue(config.storageKeys.fishingTries, -1)
        if fishingTriesAmount > 0 then
            creature:addSkillTries(SKILL_FISHING, fishingTriesAmount)
        else
            fishingTriesAmount = fishingTriesAmount * -1
            creature:removeSkillTries(SKILL_FISHING, fishingTriesAmount)
        end
        
        creature:teleportTo(config.teleportOut.destination)
        return true
    end
    
    
    return true
end

moveevent:aid(config.teleportIn.actionId, config.teleportOut.actionId)
moveevent:register()
 
tile under 5 coins, I have storage for.

View attachment 81939

data/scripts/randomPortals.lua
Lua:
local config = {
    spawnTimes = {"02:30:30", "02:30:40"},
    portalAmount = {min = 2, max = 4},
    portals = {
    --    [actionId & storage] = {spawnPosition, destination}
        [45038] = {spawnPosition = Position(1004, 1001, 7), destination = Position(1004, 1004, 7)},
        [45039] = {spawnPosition = Position(1005, 1001, 7), destination = Position(1005, 1004, 7)},
        [45040] = {spawnPosition = Position(1006, 1001, 7), destination = Position(1006, 1004, 7)},
        [45041] = {spawnPosition = Position(1007, 1001, 7), destination = Position(1007, 1004, 7)},
        [45042] = {spawnPosition = Position(1008, 1001, 7), destination = Position(1008, 1004, 7)}
    }
}

-- END OF CONFIG

local moveevent = MoveEvent()

function moveevent.onStepIn(creature, item, position, fromPosition)
    if not isPlayer(creature) then
        return true
    end
    local actionId = item:getActionId()
    local portal = Tile(config.portals[actionId].spawnPosition):getItemById(1387)
    if portal or creature:getStorageValue(actionId) == 1 then
        position:sendMagicEffect(CONST_ME_TELEPORT)
        creature:teleportTo(config.portals[actionId].destination)
        config.portals[actionId].destination:sendMagicEffect(CONST_ME_TELEPORT)
        return true
    end
    return true
end

for actionId, _ in pairs(config.portals) do
    moveevent:aid(actionId)
end
moveevent:register()


for _, spawnTime in pairs(config.spawnTimes) do
    local globalevent = GlobalEvent("randomPortals" .. spawnTime)
   
    function globalevent.onTime(interval)
        local rand = math.random(config.portalAmount.min, config.portalAmount.max)
        local portals = {}
        for k, v in pairs(config.portals) do
            local portal = Tile(v.spawnPosition):getItemById(1387)
            if portal then
                portal:remove()
            end
            portals[#portals + 1] = k
        end
        for i = 1, rand do
            rand = math.random(#portals)
            Game.createItem(1387, 1, config.portals[portals[rand]].spawnPosition)
            table.remove(portals, rand)
        end
        broadcastMessage("Random portals have spawned!", MESSAGE_STATUS_DEFAULT)
        return true
    end
   
    globalevent:time(spawnTime)
    globalevent:register()
end


local globalevent = GlobalEvent("onStartUp_randomPortals")

function globalevent.onStartup()
    for k, v in pairs(config.portals) do
        local tile = Tile(v.spawnPosition)
        if not tile then
            print("No tile at portal spawnPosition. (" .. k .. ")")
            return true
        end
        tile:getGround():setActionId(k)
    end
    return true
end

globalevent:register()
Post automatically merged:



View attachment 81941

data/scripts/monsterSpeedAutoAdjust.lua
Lua:
local speedPerLevel = 1 -- (probably don't need to touch, it's just here in case your source gives more speed per level)
local monsterName = "valkyrie"

-- end of config

local function adjustSpeed(creatureId)
    local creature = Creature(creatureId)
    if not creature then
        return
    end
    local target = creature:getTarget()
    local targetSpeed = (target and target:isPlayer() and target:getBaseSpeed() or MonsterType(monsterName):baseSpeed()) + speedPerLevel
    local creatureSpeed = creature:getSpeed()
    local deltaSpeed = (creatureSpeed - targetSpeed) * -1
    if deltaSpeed ~= 0 then
        creature:changeSpeed(deltaSpeed)
    end
end


local creatureevent = CreatureEvent("onThink_monsterAdjustSpeedToTarget")

function creatureevent.onThink(creature, interval)
    local creatureId = creature:getId()
    adjustSpeed(creatureId)
    addEvent(adjustSpeed, 500, creatureId)
    return true
end

creatureevent:register()


local eventCallback = EventCallback

function eventCallback.onSpawn(creature, position, startup, artificial)
    if monsterName:lower() == creature:getName():lower() then
        creature:registerEvent("onThink_monsterAdjustSpeedToTarget")
    end
    return true
end

eventCallback:register(-666)
Post automatically merged:



View attachment 81942

data/scripts/monsterAdjustDamageBasedOnNearbyPlayers.lua

Lua:
local config = {
    ["valkyrie"] = {range = 4, increasePerPlayer = 1, damageChange = {flat = 0, percent = 200}}, -- flat adds first, then total damage increased by percent.
    ["orc berserker"] = {range = 4, increasePerPlayer = 2, damageChange = {flat = 500, percent = 0}}     -- per 2 players
}

-- end of config


local function calculateDamage(damage, damageType, flat, percent, playerAmount)
    if damageType ~= 0 then
        flat = flat * playerAmount
        damage = damage + flat
        percent = percent * playerAmount
        return damage + (damage * ((percent + 100) / 100))
    end
    return damage
end

local function damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    local index = config[attacker:getName():lower()]
    if index then
        local spectators = Game.getSpectators(attacker:getPosition(), false, true, index.range, index.range, index.range, index.range)
        spectators = math.floor(#spectators / index.increasePerPlayer)
        primaryDamage = calculateDamage(primaryDamage, primaryType, index.damageChange.flat, index.damageChange.percent, spectators)
        secondaryDamage = calculateDamage(secondaryDamage, secondaryType, index.damageChange.flat, index.damageChange.percent, spectators)
    end
    return primaryDamage, secondaryDamage
end

local healthChange = CreatureEvent("onHealthChange_monsterAdjustDamage")

function healthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

healthChange:register()


local manaChange = CreatureEvent("onManaChange_monsterAdjustDamage")

function manaChange.onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

manaChange:register()


local creatureevent = CreatureEvent("example")

function creatureevent.onLogin(player)
    player:registerEvent("onHealthChange_monsterAdjustDamage")
    player:registerEvent("onManaChange_monsterAdjustDamage")
    return true
end

creatureevent:register()

local eventCallback = EventCallback

function eventCallback.onSpawn(creature, position, startup, artificial)
    creature:registerEvent("onHealthChange_monsterAdjustDamage")
    return true
end

eventCallback:register(-666)


NICE!
Nobody outruns the Black Riders now muahaha
 
Hey @Xikini , since i've seen you testing and learning few things on your streaming, what about damageMap?
Lets say a script that calculates damage done per second (DPS) of all the players who attack the target and after it dies or certain amount of time, a window pops up and show names and damage done.

I've never learned how damageMap works so far lol.
You can combine it with modalWindows for better or different outputs.

Thanks, awesome job for the community as always! thanks!
 
Lua:
local config = {
    ["valkyrie"] = {range = 4, increasePerPlayer = 1, damageChange = {flat = 0, percent = 200}}, -- flat adds first, then total damage increased by percent.
    ["orc berserker"] = {range = 4, increasePerPlayer = 2, damageChange = {flat = 500, percent = 0}}     -- per 2 players
}

-- end of config


local function calculateDamage(damage, damageType, flat, percent, playerAmount)
    if damageType ~= 0 then
        flat = flat * playerAmount
        damage = damage + flat
        percent = percent * playerAmount
        return damage + (damage * ((percent + 100) / 100))
    end
    return damage
end

local function damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    local index = config[attacker:getName():lower()]
    if index then
        local spectators = Game.getSpectators(attacker:getPosition(), false, true, index.range, index.range, index.range, index.range)
        spectators = math.floor(#spectators / index.increasePerPlayer)
        primaryDamage = calculateDamage(primaryDamage, primaryType, index.damageChange.flat, index.damageChange.percent, spectators)
        secondaryDamage = calculateDamage(secondaryDamage, secondaryType, index.damageChange.flat, index.damageChange.percent, spectators)
    end
    return primaryDamage, secondaryDamage
end

local healthChange = CreatureEvent("onHealthChange_monsterAdjustDamage")

function healthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

healthChange:register()


local manaChange = CreatureEvent("onManaChange_monsterAdjustDamage")

function manaChange.onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

manaChange:register()


local creatureevent = CreatureEvent("example")

function creatureevent.onLogin(player)
    player:registerEvent("onHealthChange_monsterAdjustDamage")
    player:registerEvent("onManaChange_monsterAdjustDamage")
    return true
end

creatureevent:register()

local eventCallback = EventCallback

function eventCallback.onSpawn(creature, position, startup, artificial)
    creature:registerEvent("onHealthChange_monsterAdjustDamage")
    return true
end

eventCallback:register(-666)
Post automatically merged:
Code:
Lua Script Error: [Scripts Interface]
C:\TestOTVM\data\scripts\BossExtraDamage.lua:callback
C:\TestOTVM\data\scripts\BossExtraDamage.lua:20: attempt to index local 'attacker' (a nil value)
stack traceback:
        [C]: in function '__index'
        C:\TestOTVM\data\scripts\BossExtraDamage.lua:20: in function 'damageCalculator'
        C:\TestOTVM\data\scripts\BossExtraDamage.lua:43: in function <C:\TestOTVM\data\scripts\BossExtraDamage.lua:42>
        [C]: in function 'doTargetCombatMana'
        data/actions/scripts/others/consumables/potions.lua:100: in function <data/actions/scripts/others/consumables/potions.lua:67>
 
Code:
Lua Script Error: [Scripts Interface]
C:\TestOTVM\data\scripts\BossExtraDamage.lua:callback
C:\TestOTVM\data\scripts\BossExtraDamage.lua:20: attempt to index local 'attacker' (a nil value)
stack traceback:
        [C]: in function '__index'
        C:\TestOTVM\data\scripts\BossExtraDamage.lua:20: in function 'damageCalculator'
        C:\TestOTVM\data\scripts\BossExtraDamage.lua:43: in function <C:\TestOTVM\data\scripts\BossExtraDamage.lua:42>
        [C]: in function 'doTargetCombatMana'
        data/actions/scripts/others/consumables/potions.lua:100: in function <data/actions/scripts/others/consumables/potions.lua:67>
Should be fixed. 👍
Post automatically merged:

A script for custom weapon the fire dagger.
If player hits target it add 5% fire damage of the last hit.
Hey, I don't really understand what you're requesting here.

Are we only tracking the damage and hits of the fire dagger?
Does the fire dagger deal only fire damage? Or does it do a mix of fire and physical?

If it's mixed damage, is it only the fire damage we add 5% of?

Sorry, there's just 3-4 different ways to interpret your request and I want to do it correctly.
Post automatically merged:

Hey @Xikini , since i've seen you testing and learning few things on your streaming, what about damageMap?
Lets say a script that calculates damage done per second (DPS) of all the players who attack the target and after it dies or certain amount of time, a window pops up and show names and damage done.

I've never learned how damageMap works so far lol.
You can combine it with modalWindows for better or different outputs.

Thanks, awesome job for the community as always! thanks!
I actually worked with damage maps recently, so I know how they work. :D
 
Last edited:
Should be fixed. 👍
When I use any potion I get this error:
Code:
Lua Script Error: [Scripts Interface]
C:\TestOTVM\data\scripts\BossExtraDamage.lua:callback
C:\TestOTVM\data\scripts\BossExtraDamage.lua:20: attempt to index local 'attacker' (a nil value)
stack traceback:
        [C]: in function '__index'
        C:\TestOTVM\data\scripts\BossExtraDamage.lua:20: in function 'damageCalculator'
        C:\TestOTVM\data\scripts\BossExtraDamage.lua:35: in function <C:\TestOTVM\data\scripts\BossExtraDamage.lua:34>
        [C]: in function 'doTargetCombatHealth'
        data/actions/scripts/others/consumables/potions.lua:97: in function <data/actions/scripts/others/consumables/potions.lua:68>

Potion.lua line 68 and 97:
Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if type(target) ~= "userdata" then
        return false
    end
------------
    if potion.health or potion.mana or potion.combat then
        if potion.health then
            doTargetCombatHealth(0, target, COMBAT_HEALING, potion.health[1], potion.health[2], CONST_ME_MAGIC_BLUE)
        end
 
Back
Top