• 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 [TFS 1.3] Free Scripting Service 📝

Status
Not open for further replies.

Sarah Wesker

ƐƖєgαηт Sуηтαx ❤
Staff member
TFS Developer
Support Team
Joined
Mar 16, 2017
Messages
1,408
Solutions
154
Reaction score
1,958
Location
London
GitHub
MillhioreBT
Twitch
millhiorebt
I am bored, and I have some days in which I will not have much to do, if you need a script you can post here what you want and if it meets the requirements below, I will do it for you

🗒 Requirements:
🔶 TFS engine 1.3+
🔶 That does not include changes in the sources (if you don't know what this is, you can still ask💬)
🔶 I'll only do one script per person so don't spam🔇too much, until a second chance ...
🔶 It depends on what you ask, I will make the decision to accept or not to do it👀
🔶 I know that several people have posted threads similar to this one, but to add more variety, also not all can be available at the same time👌

Don't be afraid to ask 🤗

👍 If I like your post it means that I have taken the task! 👍
 
Last edited:
Hello if you have time, and do you want to create something like this...

[Automatic MultiPromotion System with bonuses]

on level 1 we start as a druid on level 20 automatically transforms us into an elder druid then at 50 into Royal Druid
20 lvl bonus +150hp and +500mp and new outfit druid (with 2 addons)
50 lvl bonus +25speed and 500mp and new outfit summoner (with 2 addons)
 
Hello Sarah.
I need EXP online players bonus
5 - 19EXP +5%
20 - 49EXP +10%
50 - 99EXP +15%
100 - 249EXP +20%
250 - 399EXP +25%
400+EXP +30%
tfs 1.3
 
Last edited:
Hi, thanks for doing this! much appreciated!

So i would like to ask for a spell, that does so:
-Summons a creature
-Summon can be killed by players and monsters
-If the summon is killed by player or monster he explodes and doesnt deal any damage to the surrounding players (but does to the monsters)(area of explosion is 1 sqm around the summon)
-Summon upon reaching the target explodes(dies) and deals x amount of dmg (monsters and targeted player(only to targeted player) )
-Summon doesnt deal any other damage than explosion upon dying.
-Damage calculated based on player level and magic lvl.

If you decide to even create this spells, here are some additional, probably more time consuming features of this spell, perhaps u would be so kind to also add them , if not then its all good and im grateful anyway.
-Summons health is the % health of the player that summons it.
-Summons movement speed is 1.5x greater than the player that summons it.
-Summon follows u even if u change floor
-Summon teleports back to the player if he lost the player from the screen.

Thank you in advance.
Hi @Sopago
It's probably not exactly what you wanted, I don't know if I understood you correctly, but here is the script as I could understand it

data/scripts/yourscriptname.lua
Lua:
local summonSpellConfig = {
    ["Rat"] = {
        area = createCombatArea(AREA_CIRCLE2X2),
        formula = {
            level = 3,
            magLvl = 2,
            minDmg = 1.2,
            maxDmg = 1.5,
            speed = 1.5
        },
        effect = CONST_ME_FIREAREA,
        combat = COMBAT_FIREDAMAGE
    },
    ["Rotworm"] = {
        area = createCombatArea(AREA_CIRCLE2X2),
        formula = {
            level = 4,
            magLvl = 4,
            minDmg = 1.2,
            maxDmg = 1.5,
            speed = 1.5
        },
        effect = CONST_ME_FIREAREA,
        combat = COMBAT_FIREDAMAGE
    }
}

local cExplosionSummonDie = CreatureEvent("ExplosionSummonDie")
function cExplosionSummonDie.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local prop = summonSpellConfig[creature:getName()]
    if prop then
        local master = creature:getMaster()
        if master then
            local min = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.minDmg
            local max = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.maxDmg
            doAreaCombatHealth(master:getId(), prop.combat, creature:getPosition(), prop.area, -min, -max, prop.effect, ORIGIN_SPELL)
        end
    end
    return true
end
cExplosionSummonDie:register()

local cExplosionSummonThink = CreatureEvent("ExplosionSummonThink")
function cExplosionSummonThink.onThink(creature, interval, item, position, lastPosition, fromPosition, toPosition)
    local prop = summonSpellConfig[creature:getName()]
    if prop then
        local master = creature:getMaster()
        if master then
            local target = master:getTarget()
            local masterPos = master:getPosition()
            local creaturePos = creature:getPosition()
            if target and target:getPosition():getDistance(creaturePos) <= 1 then
                local min = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.minDmg
                local max = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.maxDmg
                doAreaCombatHealth(master:getId(), prop.combat, creature:getPosition(), prop.area, -min, -max, prop.effect, ORIGIN_SPELL)
                creature:remove()
            elseif creaturePos:getDistance(masterPos) > 7 or creaturePos.z ~= masterPos.z then
                creaturePos:sendMagicEffect(CONST_ME_POFF)
                creature:teleportTo(masterPos)
                masterPos:sendMagicEffect(CONST_ME_TELEPORT)
            end
        end
    end
    return true
end
cExplosionSummonThink:register()

local spell = Spell(SPELL_INSTANT)

function spell.onCastSpell(creature, variant)
    local summons = creature:getSummons()
    if #summons >= 2 then
        creature:sendCancelMessage("You can only have 2 summons maximum.")
        return false
    end
    local monsterName = variant:getString()
    local prop = summonSpellConfig[monsterName]
    if prop then
        local monster = Game.createMonster(monsterName, creature:getPosition())
        if monster then
            monster:registerEvent("ExplosionSummonDie")
            monster:registerEvent("ExplosionSummonThink")
            monster:changeSpeed(creature:getBaseSpeed() * prop.formula.speed)
            local maxHp = creature:getMaxHealth()
            monster:setMaxHealth(maxHp)
            monster:addHealth(maxHp)
            creature:addSummon(monster)
            return true
        end
        creature:sendCancelMessage(RETURNVALUE_NOTENOUGHROOM)
        return false
    end
    creature:sendCancelMessage("Summon name does not exist.")
    return false
end

spell:name("Summon Bomb Spell")
spell:words("make bomb")
spell:hasParams(true)
spell:group("attack")
spell:vocation("sorcerer", "master sorecerer")
spell:id(1)
spell:cooldown(1000)
spell:level(200)
spell:range(6)
spell:manaPercent(13)
spell:isPremium(true)
spell:register()
In this example I used a Rat and a Rotworm as explosive summons, but you must have your own custom monsters which will use this script.
You can try executing the spell make bomb" Rat or make bomb" Rotworm, in the configuration each one of them has different properties, such as the formula of the damage and the affected area and or effects.

GIF 03-02-2021 04-26-22 p. m..gifGIF 03-02-2021 04-29-48 p. m..gif
 
Hello Sarah, good scripts you doing here ^^.
Can you make one for outfit and mounts bonuses? Each full outfit/mount obtained you gain some bonuses like +hp, +mana, +skills, they being in intervals: First mount/outfit: +1%hp, Second mount/outfit: +1%mp, third mount/outfit: +1skills (sword,axe,club,ml), Fourth mount/outfit: +1%hp and so on
 
Hi

I would like to request a spell which is based mostly on random direction

The spell will cast 4 distance effect in a row with small delays with random direction

1612385733988.png
 
Hi Sarah, I don't know if you read me or not you can help me but I wanted a door scripts with storage since the one I have is bugeada ..
I just want a scrits .. that in order to open the door you have the quest done
 
Hi Sarah, I don't know if you read me or not you can help me but I wanted a door scripts with storage since the one I have is bugeada ..
I just want a scrits .. that in order to open the door you have the quest done
you'd be better off posting in support for this, and post your data/scripts/other/doors.lua script
 
Normally what would be expected of a miniboss is that it has: name, damage and other different properties, but without changes in the sources it is not possible, only the health per default, I hope this script will help you, or at least as an example, maybe for the next round you can imagine something that is more within reach ;)
I'd like to say that's not true.

You could use these to create boss MonsterTypes in batches:
C++:
registerMethod("Game", "getMonsterTypes", LuaScriptInterface::luaGameGetMonsterTypes);
registerMethod("Game", "createMonsterType", LuaScriptInterface::luaGameCreateMonsterType);

Then you could use all of these to make a copy of the monsters and buff them:
C++:
    // MonsterType
    registerClass("MonsterType", "", LuaScriptInterface::luaMonsterTypeCreate);
    registerMetaMethod("MonsterType", "__eq", LuaScriptInterface::luaUserdataCompare);

    registerMethod("MonsterType", "isAttackable", LuaScriptInterface::luaMonsterTypeIsAttackable);
    registerMethod("MonsterType", "isConvinceable", LuaScriptInterface::luaMonsterTypeIsConvinceable);
    registerMethod("MonsterType", "isSummonable", LuaScriptInterface::luaMonsterTypeIsSummonable);
    registerMethod("MonsterType", "isIllusionable", LuaScriptInterface::luaMonsterTypeIsIllusionable);
    registerMethod("MonsterType", "isHostile", LuaScriptInterface::luaMonsterTypeIsHostile);
    registerMethod("MonsterType", "isPushable", LuaScriptInterface::luaMonsterTypeIsPushable);
    registerMethod("MonsterType", "isHealthHidden", LuaScriptInterface::luaMonsterTypeIsHealthHidden);
    registerMethod("MonsterType", "isBoss", LuaScriptInterface::luaMonsterTypeIsBoss);

    registerMethod("MonsterType", "canPushItems", LuaScriptInterface::luaMonsterTypeCanPushItems);
    registerMethod("MonsterType", "canPushCreatures", LuaScriptInterface::luaMonsterTypeCanPushCreatures);

    registerMethod("MonsterType", "name", LuaScriptInterface::luaMonsterTypeName);

    registerMethod("MonsterType", "nameDescription", LuaScriptInterface::luaMonsterTypeNameDescription);

    registerMethod("MonsterType", "health", LuaScriptInterface::luaMonsterTypeHealth);
    registerMethod("MonsterType", "maxHealth", LuaScriptInterface::luaMonsterTypeMaxHealth);
    registerMethod("MonsterType", "runHealth", LuaScriptInterface::luaMonsterTypeRunHealth);
    registerMethod("MonsterType", "experience", LuaScriptInterface::luaMonsterTypeExperience);
    registerMethod("MonsterType", "skull", LuaScriptInterface::luaMonsterTypeSkull);

    registerMethod("MonsterType", "combatImmunities", LuaScriptInterface::luaMonsterTypeCombatImmunities);
    registerMethod("MonsterType", "conditionImmunities", LuaScriptInterface::luaMonsterTypeConditionImmunities);

    registerMethod("MonsterType", "getAttackList", LuaScriptInterface::luaMonsterTypeGetAttackList);
    registerMethod("MonsterType", "addAttack", LuaScriptInterface::luaMonsterTypeAddAttack);

    registerMethod("MonsterType", "getDefenseList", LuaScriptInterface::luaMonsterTypeGetDefenseList);
    registerMethod("MonsterType", "addDefense", LuaScriptInterface::luaMonsterTypeAddDefense);

    registerMethod("MonsterType", "getElementList", LuaScriptInterface::luaMonsterTypeGetElementList);
    registerMethod("MonsterType", "addElement", LuaScriptInterface::luaMonsterTypeAddElement);

    registerMethod("MonsterType", "getVoices", LuaScriptInterface::luaMonsterTypeGetVoices);
    registerMethod("MonsterType", "addVoice", LuaScriptInterface::luaMonsterTypeAddVoice);

    registerMethod("MonsterType", "getLoot", LuaScriptInterface::luaMonsterTypeGetLoot);
    registerMethod("MonsterType", "addLoot", LuaScriptInterface::luaMonsterTypeAddLoot);

    registerMethod("MonsterType", "getCreatureEvents", LuaScriptInterface::luaMonsterTypeGetCreatureEvents);
    registerMethod("MonsterType", "registerEvent", LuaScriptInterface::luaMonsterTypeRegisterEvent);

    registerMethod("MonsterType", "eventType", LuaScriptInterface::luaMonsterTypeEventType);
    registerMethod("MonsterType", "onThink", LuaScriptInterface::luaMonsterTypeEventOnCallback);
    registerMethod("MonsterType", "onAppear", LuaScriptInterface::luaMonsterTypeEventOnCallback);
    registerMethod("MonsterType", "onDisappear", LuaScriptInterface::luaMonsterTypeEventOnCallback);
    registerMethod("MonsterType", "onMove", LuaScriptInterface::luaMonsterTypeEventOnCallback);
    registerMethod("MonsterType", "onSay", LuaScriptInterface::luaMonsterTypeEventOnCallback);

    registerMethod("MonsterType", "getSummonList", LuaScriptInterface::luaMonsterTypeGetSummonList);
    registerMethod("MonsterType", "addSummon", LuaScriptInterface::luaMonsterTypeAddSummon);

    registerMethod("MonsterType", "maxSummons", LuaScriptInterface::luaMonsterTypeMaxSummons);

    registerMethod("MonsterType", "armor", LuaScriptInterface::luaMonsterTypeArmor);
    registerMethod("MonsterType", "defense", LuaScriptInterface::luaMonsterTypeDefense);
    registerMethod("MonsterType", "outfit", LuaScriptInterface::luaMonsterTypeOutfit);
    registerMethod("MonsterType", "race", LuaScriptInterface::luaMonsterTypeRace);
    registerMethod("MonsterType", "corpseId", LuaScriptInterface::luaMonsterTypeCorpseId);
    registerMethod("MonsterType", "manaCost", LuaScriptInterface::luaMonsterTypeManaCost);
    registerMethod("MonsterType", "baseSpeed", LuaScriptInterface::luaMonsterTypeBaseSpeed);
    registerMethod("MonsterType", "light", LuaScriptInterface::luaMonsterTypeLight);

    registerMethod("MonsterType", "staticAttackChance", LuaScriptInterface::luaMonsterTypeStaticAttackChance);
    registerMethod("MonsterType", "targetDistance", LuaScriptInterface::luaMonsterTypeTargetDistance);
    registerMethod("MonsterType", "yellChance", LuaScriptInterface::luaMonsterTypeYellChance);
    registerMethod("MonsterType", "yellSpeedTicks", LuaScriptInterface::luaMonsterTypeYellSpeedTicks);
    registerMethod("MonsterType", "changeTargetChance", LuaScriptInterface::luaMonsterTypeChangeTargetChance);
    registerMethod("MonsterType", "changeTargetSpeed", LuaScriptInterface::luaMonsterTypeChangeTargetSpeed);
 
I want an NPC which a player can face against on a combat of trivial pursuit
Because the information you provided was very limited, I had to search the internet a bit, and use a bit of my imagination, this is the result:

data/npc/Trivial.xml
XML:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Trivial" script="trivial.lua" walkinterval="2000" speed="0" floorchange="0">
    <health now="100" max="100" />
    <look type="472" head="114" body="95" legs="76" feet="19" addons="3"/>
</npc>

data/npc/scripts/trivial.lua
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 function irandom_prefix(from, to, prefix)
    return string.format("%d %s", math.random(from, to), prefix)
end

local talkHppc = {
    player = 100,
    npc = 100,
    damage = function() return math.random(10, 20) end
}
local rewards = {
    exp = 1000000,
    items = {
        {2160, 100},
        {2160, 100}
    }
}

local questions = {
    {
        type = "select",
        name = "How far is the earth from the moon?",
        options = {
            irandom_prefix(1, 100, "km"),
            irandom_prefix(5000, 9999, "km"),
            irandom_prefix(1, 999, "km"),
            "384400 km"
        },
        answer = 4
    },
    {
        type = "select",
        name = "Who is the president of the united states?",
        options = {
            "Kamala Harris",
            "Donald Trump",
            "Joe Biden",
            "Barack Obama"
        },
        answer = 3
    },
    {
        type = "select",
        name = "Which is the vocation that has more magic damage?",
        options = {
            "Knight",
            "Sorcerer",
            "Paladin",
            "No Vocation"
        },
        answer = 2
    },
    {
        type = "math",
        name = "What is the result of %d %s %d?",
        options = 4
    }
}

local function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
end

local function delaySay(msg, interval, npcid, cid)
    addEvent(function(msg, npcid, cid)
        local npc = Npc(npcid)
        if npc then
            npc:say(msg, TALKTYPE_PRIVATE_NP, false, cid)
        end
    end, interval, msg, npcid, cid)
end

local talkPlayer = 0
local talkQuest = nil
local talkState = {}
local afterQuests = nil

local function getRandomQuest()
    local quest
    if not afterQuests then
        afterQuests = math.random(1, #questions)
        quest = questions[afterQuests]
    else
        local nrandom = math.random(1, #questions)
        quest = questions[nrandom]
        while afterQuests == nrandom do
            quest = questions[nrandom]
        end
        afterQuests = nrandom
    end
    if quest then
        if quest.type == "select" then
            local options = {}
            for i = 1, #quest.options do
                local option = quest.options[i]
                if type(option) == "function" then
                    options[#options +1] = option()
                elseif type(option) == "string" then
                    options[#options +1] = option
                end
            end
            shuffle(options)
            local answer = 1
            for i = 1, #options do
                if options[i] == quest.options[quest.answer] then
                    answer = i
                    break
                end
            end
            return {
                name = quest.name,
                options = options,
                answer = answer
            }
        elseif quest.type == "math" then
            local operator = ({'+','-','/','*'})[math.random(1, 4)]
            local n1, n2 = math.random(1, 100), math.random(1, 100)
            local o_result = loadstring(string.format("return %d%s%d", n1, operator, n2))()
            local name = string.format(quest.name, n1, operator, n2)
            local options = {o_result}
            for i = 1, quest.options -1 do
                options[#options +1] = math.random(1, 999)
            end
            shuffle(options)
            local answer = 1
            for i = 1, #options do
                if options[i] == o_result then
                    answer = i
                    break
                end
            end
            return {
                name = name,
                options = options,
                answer = answer
            }
        end
    end
end

local function sendNewQuest(cid, nid)
    talkQuest = getRandomQuest()
    local text = string.format("%s\nOptions: ", talkQuest.name)
    for i = 1, #talkQuest.options do
        text = string.format("%s[ {%d} ]: %s%s", text, i, talkQuest.options[i], (i ~= #talkQuest.options and " | " or ""))
    end
    delaySay(text, 1000, nid, cid)
end

local function sendRewards(player)
    local bag = Game.createItem(2002, 1)
    if bag then
        local description = "You rewards: "
        for _, reward in pairs(rewards.items) do
            bag:addItem(reward[1], reward[2], INDEX_WHEREEVER, FLAG_NOLIMIT)
            description = string.format("%s%d %s%s", description, reward[2], ItemType(reward[1]):getName(), (_ == #rewards.items and '.' or ', '))
        end
        local inbox = player:getInbox()
        if inbox then
            inbox:addItemEx(bag, INDEX_WHEREEVER, FLAG_NOLIMIT)
            player:sendTextMessage(MESSAGE_INFO_DESCR, description..'\nCheck your depot inbox.')
        end
    end
    if rewards.exp then
        player:addExperience(rewards.exp, true)
    end
end

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

    local nid = getNpcCid()
    local npc = Npc(nid)
    local npcPos = npc:getPosition()

    local player = Player(cid)
    local playerPos = player:getPosition()

    if not talkState[cid] then
        if msgcontains(msg, "yes") then
            selfSay("Here are some questions which you have to answer, I'll play too ;D", cid)
            sendNewQuest(cid, nid)
            npcPos:sendMagicEffect(CONST_ME_CRAPS)
            talkState[cid] = 1
        elseif msgcontains(msg, "no") then
            selfSay("Come back when you have the courage to face me.", cid)
            npcHandler:releaseFocus(cid)
        end
    elseif talkState[cid] == 1 then
        if talkQuest then
            local select_n = tonumber(msg)
            if select_n and select_n > 0 and select_n <= #talkQuest.options then
                local npc_correct = math.random(1, #talkQuest.options) == talkQuest.answer
                if select_n == talkQuest.answer then
                    if npc_correct then
                        selfSay("Your answer is correct, mine is also correct, so neither will take damage.", cid)
                        npcPos:sendMagicEffect(CONST_ME_POFF)
                        playerPos:sendMagicEffect(CONST_ME_POFF)
                    else
                        selfSay("Your answer is correct, mine is not, so I will take damage.", cid)
                        playerPos:sendMagicEffect(CONST_ME_POFF)
                        playerPos:sendDistanceEffect(npcPos, CONST_ANI_DEATH)
                        npcPos:sendMagicEffect(CONST_ME_MORTAREA)
                        talkHppc.npc = math.max(0, talkHppc.npc - talkHppc.damage())
                    end
                else
                    if npc_correct then
                        selfSay("Your answer is wrong, mine is correct, you will receive damage.", cid)
                        npcPos:sendMagicEffect(CONST_ME_POFF)
                        npcPos:sendDistanceEffect(playerPos, CONST_ANI_DEATH)
                        playerPos:sendMagicEffect(CONST_ME_MORTAREA)
                        talkHppc.player = math.max(0, talkHppc.player - talkHppc.damage())
                    else
                        selfSay("Your answer is wrong, I was wrong too, we both received damage.", cid)
                        playerPos:sendDistanceEffect(npcPos, CONST_ANI_DEATH)
                        npcPos:sendMagicEffect(CONST_ME_MORTAREA)
                        npcPos:sendDistanceEffect(playerPos, CONST_ANI_DEATH)
                        playerPos:sendMagicEffect(CONST_ME_MORTAREA)
                        talkHppc.player = math.max(0, talkHppc.player - talkHppc.damage())
                        talkHppc.npc = math.max(0, talkHppc.npc - talkHppc.damage())
                    end
                end
                delaySay(string.format("Current status:\nYour health: {%d}/100\nNpc health: {%d}/100", talkHppc.player, talkHppc.npc), 1000, nid, cid)
                if talkHppc.player <= 0 then
                    delaySay("You have been defeated, it was a good fight.", 1500, nid, cid)
                    npc:say("I have won the trivial battle hahahaha.", TALKTYPE_MONSTER_SAY)
                    npcHandler:releaseFocus(cid)
                elseif talkHppc.npc <= 0 then
                    delaySay("You're the winner, it was a good fight.", 1500, nid, cid)
                    player:say("I have won the trivial battle hahahaha.", TALKTYPE_MONSTER_SAY)
                    sendRewards(player)
                    playerPos:sendMagicEffect(CONST_ME_FIREWORK_YELLOW)
                    npcHandler:releaseFocus(cid)
                else
                    delaySay("Ready for the next round?", 1500, nid, cid)
                    talkState[cid] = 2
                end
            else
                selfSay(string.format("Please select one of the available options, for example: {%d}", math.random(1, #talkQuest.options)), cid)
            end
        end
    elseif talkState[cid] == 2 then
        if msgcontains(msg, "yes") then
            selfSay(({"Mmmmm...", "Ok...", "I Think..."})[math.random(1, 3)], cid)
            sendNewQuest(cid, nid)
            npcPos:sendMagicEffect(CONST_ME_CRAPS)
            talkState[cid] = 1
        elseif msgcontains(msg, "no") then
            selfSay("Come back when you have the courage to face me.", cid)
            npcHandler:releaseFocus(cid)
        end
    end

    return true
end

function creatureReleaseFocusCallback(cid)
    talkState[cid] = nil
    talkPlayer = 0
    talkHppc.player = 100
    talkHppc.npc = 100
    return true
end

function creatureGreetCallback(cid)
    local player = Player(talkPlayer)
    if not player then
        player = Player(cid)
        selfSay(string.format("Hello {%s}, would you like to answer some questions and earn rewards?", player:getName()), cid)
        talkPlayer = cid
        npcHandler:addFocus(cid)
    elseif player ~= Player(cid) then
        selfSay(string.format("Estoy ocupado jugando con {%s}, por favor espera tu turno.", player:getName()), cid)
        talkPlayer = 0
    end
    return false
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:setCallback(CALLBACK_GREET, creatureGreetCallback)
npcHandler:setCallback(CALLBACK_ONRELEASEFOCUS, creatureReleaseFocusCallback)
npcHandler:addModule(FocusModule:new())

GIF 04-02-2021 12-29-09 a. m..gif
If you win then you get a reward. 🤑
If you lose nothing happens, the npc will simply make fun of you for being a fool. 🤣

Note: it is worth mentioning that there are not many questions, this job is for you, enrich the npc with too many questions to make it very realistic and fun
I know it is not perfect, but I hope it will help you or an example for something you want to do
 
Hi @Sopago
It's probably not exactly what you wanted, I don't know if I understood you correctly, but here is the script as I could understand it

data/scripts/yourscriptname.lua
Lua:
local summonSpellConfig = {
    ["Rat"] = {
        area = createCombatArea(AREA_CIRCLE2X2),
        formula = {
            level = 3,
            magLvl = 2,
            minDmg = 1.2,
            maxDmg = 1.5,
            speed = 1.5
        },
        effect = CONST_ME_FIREAREA,
        combat = COMBAT_FIREDAMAGE
    },
    ["Rotworm"] = {
        area = createCombatArea(AREA_CIRCLE2X2),
        formula = {
            level = 4,
            magLvl = 4,
            minDmg = 1.2,
            maxDmg = 1.5,
            speed = 1.5
        },
        effect = CONST_ME_FIREAREA,
        combat = COMBAT_FIREDAMAGE
    }
}

local cExplosionSummonDie = CreatureEvent("ExplosionSummonDie")
function cExplosionSummonDie.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local prop = summonSpellConfig[creature:getName()]
    if prop then
        local master = creature:getMaster()
        if master then
            local min = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.minDmg
            local max = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.maxDmg
            doAreaCombatHealth(master:getId(), prop.combat, creature:getPosition(), prop.area, -min, -max, prop.effect, ORIGIN_SPELL)
        end
    end
    return true
end
cExplosionSummonDie:register()

local cExplosionSummonThink = CreatureEvent("ExplosionSummonThink")
function cExplosionSummonThink.onThink(creature, interval, item, position, lastPosition, fromPosition, toPosition)
    local prop = summonSpellConfig[creature:getName()]
    if prop then
        local master = creature:getMaster()
        if master then
            local target = master:getTarget()
            local masterPos = master:getPosition()
            local creaturePos = creature:getPosition()
            if target and target:getPosition():getDistance(creaturePos) <= 1 then
                local min = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.minDmg
                local max = ((master:getLevel() * prop.formula.level) + (master:getMagicLevel() * prop.formula.magLvl)) * prop.formula.maxDmg
                doAreaCombatHealth(master:getId(), prop.combat, creature:getPosition(), prop.area, -min, -max, prop.effect, ORIGIN_SPELL)
                creature:remove()
            elseif creaturePos:getDistance(masterPos) > 7 or creaturePos.z ~= masterPos.z then
                creaturePos:sendMagicEffect(CONST_ME_POFF)
                creature:teleportTo(masterPos)
                masterPos:sendMagicEffect(CONST_ME_TELEPORT)
            end
        end
    end
    return true
end
cExplosionSummonThink:register()

local spell = Spell(SPELL_INSTANT)

function spell.onCastSpell(creature, variant)
    local summons = creature:getSummons()
    if #summons >= 2 then
        creature:sendCancelMessage("You can only have 2 summons maximum.")
        return false
    end
    local monsterName = variant:getString()
    local prop = summonSpellConfig[monsterName]
    if prop then
        local monster = Game.createMonster(monsterName, creature:getPosition())
        if monster then
            monster:registerEvent("ExplosionSummonDie")
            monster:registerEvent("ExplosionSummonThink")
            monster:changeSpeed(creature:getBaseSpeed() * prop.formula.speed)
            local maxHp = creature:getMaxHealth()
            monster:setMaxHealth(maxHp)
            monster:addHealth(maxHp)
            creature:addSummon(monster)
            return true
        end
        creature:sendCancelMessage(RETURNVALUE_NOTENOUGHROOM)
        return false
    end
    creature:sendCancelMessage("Summon name does not exist.")
    return false
end

spell:name("Summon Bomb Spell")
spell:words("make bomb")
spell:hasParams(true)
spell:group("attack")
spell:vocation("sorcerer", "master sorecerer")
spell:id(1)
spell:cooldown(1000)
spell:level(200)
spell:range(6)
spell:manaPercent(13)
spell:isPremium(true)
spell:register()
In this example I used a Rat and a Rotworm as explosive summons, but you must have your own custom monsters which will use this script.
You can try executing the spell make bomb" Rat or make bomb" Rotworm, in the configuration each one of them has different properties, such as the formula of the damage and the affected area and or effects.

View attachment 54508View attachment 54509
I have checked the script and i think it works as intended , thank you very much!
 
Because the information you provided was very limited, I had to search the internet a bit, and use a bit of my imagination, this is the result:

data/npc/Trivial.xml
XML:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Trivial" script="trivial.lua" walkinterval="2000" speed="0" floorchange="0">
    <health now="100" max="100" />
    <look type="472" head="114" body="95" legs="76" feet="19" addons="3"/>
</npc>

data/npc/scripts/trivial.lua
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 function irandom_prefix(from, to, prefix)
    return string.format("%d %s", math.random(from, to), prefix)
end

local talkHppc = {
    player = 100,
    npc = 100,
    damage = function() return math.random(10, 20) end
}
local rewards = {
    exp = 1000000,
    items = {
        {2160, 100},
        {2160, 100}
    }
}

local questions = {
    {
        type = "select",
        name = "How far is the earth from the moon?",
        options = {
            irandom_prefix(1, 100, "km"),
            irandom_prefix(5000, 9999, "km"),
            irandom_prefix(1, 999, "km"),
            "384400 km"
        },
        answer = 4
    },
    {
        type = "select",
        name = "Who is the president of the united states?",
        options = {
            "Kamala Harris",
            "Donald Trump",
            "Joe Biden",
            "Barack Obama"
        },
        answer = 3
    },
    {
        type = "select",
        name = "Which is the vocation that has more magic damage?",
        options = {
            "Knight",
            "Sorcerer",
            "Paladin",
            "No Vocation"
        },
        answer = 2
    },
    {
        type = "math",
        name = "What is the result of %d %s %d?",
        options = 4
    }
}

local function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
end

local function delaySay(msg, interval, npcid, cid)
    addEvent(function(msg, npcid, cid)
        local npc = Npc(npcid)
        if npc then
            npc:say(msg, TALKTYPE_PRIVATE_NP, false, cid)
        end
    end, interval, msg, npcid, cid)
end

local talkPlayer = 0
local talkQuest = nil
local talkState = {}
local afterQuests = nil

local function getRandomQuest()
    local quest
    if not afterQuests then
        afterQuests = math.random(1, #questions)
        quest = questions[afterQuests]
    else
        local nrandom = math.random(1, #questions)
        quest = questions[nrandom]
        while afterQuests == nrandom do
            quest = questions[nrandom]
        end
        afterQuests = nrandom
    end
    if quest then
        if quest.type == "select" then
            local options = {}
            for i = 1, #quest.options do
                local option = quest.options[i]
                if type(option) == "function" then
                    options[#options +1] = option()
                elseif type(option) == "string" then
                    options[#options +1] = option
                end
            end
            shuffle(options)
            local answer = 1
            for i = 1, #options do
                if options[i] == quest.options[quest.answer] then
                    answer = i
                    break
                end
            end
            return {
                name = quest.name,
                options = options,
                answer = answer
            }
        elseif quest.type == "math" then
            local operator = ({'+','-','/','*'})[math.random(1, 4)]
            local n1, n2 = math.random(1, 100), math.random(1, 100)
            local o_result = loadstring(string.format("return %d%s%d", n1, operator, n2))()
            local name = string.format(quest.name, n1, operator, n2)
            local options = {o_result}
            for i = 1, quest.options -1 do
                options[#options +1] = math.random(1, 999)
            end
            shuffle(options)
            local answer = 1
            for i = 1, #options do
                if options[i] == o_result then
                    answer = i
                    break
                end
            end
            return {
                name = name,
                options = options,
                answer = answer
            }
        end
    end
end

local function sendNewQuest(cid, nid)
    talkQuest = getRandomQuest()
    local text = string.format("%s\nOptions: ", talkQuest.name)
    for i = 1, #talkQuest.options do
        text = string.format("%s[ {%d} ]: %s%s", text, i, talkQuest.options[i], (i ~= #talkQuest.options and " | " or ""))
    end
    delaySay(text, 1000, nid, cid)
end

local function sendRewards(player)
    local bag = Game.createItem(2002, 1)
    if bag then
        local description = "You rewards: "
        for _, reward in pairs(rewards.items) do
            bag:addItem(reward[1], reward[2], INDEX_WHEREEVER, FLAG_NOLIMIT)
            description = string.format("%s%d %s%s", description, reward[2], ItemType(reward[1]):getName(), (_ == #rewards.items and '.' or ', '))
        end
        local inbox = player:getInbox()
        if inbox then
            inbox:addItemEx(bag, INDEX_WHEREEVER, FLAG_NOLIMIT)
            player:sendTextMessage(MESSAGE_INFO_DESCR, description..'\nCheck your depot inbox.')
        end
    end
    if rewards.exp then
        player:addExperience(rewards.exp, true)
    end
end

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

    local nid = getNpcCid()
    local npc = Npc(nid)
    local npcPos = npc:getPosition()

    local player = Player(cid)
    local playerPos = player:getPosition()

    if not talkState[cid] then
        if msgcontains(msg, "yes") then
            selfSay("Here are some questions which you have to answer, I'll play too ;D", cid)
            sendNewQuest(cid, nid)
            npcPos:sendMagicEffect(CONST_ME_CRAPS)
            talkState[cid] = 1
        elseif msgcontains(msg, "no") then
            selfSay("Come back when you have the courage to face me.", cid)
            npcHandler:releaseFocus(cid)
        end
    elseif talkState[cid] == 1 then
        if talkQuest then
            local select_n = tonumber(msg)
            if select_n and select_n > 0 and select_n <= #talkQuest.options then
                local npc_correct = math.random(1, #talkQuest.options) == talkQuest.answer
                if select_n == talkQuest.answer then
                    if npc_correct then
                        selfSay("Your answer is correct, mine is also correct, so neither will take damage.", cid)
                        npcPos:sendMagicEffect(CONST_ME_POFF)
                        playerPos:sendMagicEffect(CONST_ME_POFF)
                    else
                        selfSay("Your answer is correct, mine is not, so I will take damage.", cid)
                        playerPos:sendMagicEffect(CONST_ME_POFF)
                        playerPos:sendDistanceEffect(npcPos, CONST_ANI_DEATH)
                        npcPos:sendMagicEffect(CONST_ME_MORTAREA)
                        talkHppc.npc = math.max(0, talkHppc.npc - talkHppc.damage())
                    end
                else
                    if npc_correct then
                        selfSay("Your answer is wrong, mine is correct, you will receive damage.", cid)
                        npcPos:sendMagicEffect(CONST_ME_POFF)
                        npcPos:sendDistanceEffect(playerPos, CONST_ANI_DEATH)
                        playerPos:sendMagicEffect(CONST_ME_MORTAREA)
                        talkHppc.player = math.max(0, talkHppc.player - talkHppc.damage())
                    else
                        selfSay("Your answer is wrong, I was wrong too, we both received damage.", cid)
                        playerPos:sendDistanceEffect(npcPos, CONST_ANI_DEATH)
                        npcPos:sendMagicEffect(CONST_ME_MORTAREA)
                        npcPos:sendDistanceEffect(playerPos, CONST_ANI_DEATH)
                        playerPos:sendMagicEffect(CONST_ME_MORTAREA)
                        talkHppc.player = math.max(0, talkHppc.player - talkHppc.damage())
                        talkHppc.npc = math.max(0, talkHppc.npc - talkHppc.damage())
                    end
                end
                delaySay(string.format("Current status:\nYour health: {%d}/100\nNpc health: {%d}/100", talkHppc.player, talkHppc.npc), 1000, nid, cid)
                if talkHppc.player <= 0 then
                    delaySay("You have been defeated, it was a good fight.", 1500, nid, cid)
                    npc:say("I have won the trivial battle hahahaha.", TALKTYPE_MONSTER_SAY)
                    npcHandler:releaseFocus(cid)
                elseif talkHppc.npc <= 0 then
                    delaySay("You're the winner, it was a good fight.", 1500, nid, cid)
                    player:say("I have won the trivial battle hahahaha.", TALKTYPE_MONSTER_SAY)
                    sendRewards(player)
                    playerPos:sendMagicEffect(CONST_ME_FIREWORK_YELLOW)
                    npcHandler:releaseFocus(cid)
                else
                    delaySay("Ready for the next round?", 1500, nid, cid)
                    talkState[cid] = 2
                end
            else
                selfSay(string.format("Please select one of the available options, for example: {%d}", math.random(1, #talkQuest.options)), cid)
            end
        end
    elseif talkState[cid] == 2 then
        if msgcontains(msg, "yes") then
            selfSay(({"Mmmmm...", "Ok...", "I Think..."})[math.random(1, 3)], cid)
            sendNewQuest(cid, nid)
            npcPos:sendMagicEffect(CONST_ME_CRAPS)
            talkState[cid] = 1
        elseif msgcontains(msg, "no") then
            selfSay("Come back when you have the courage to face me.", cid)
            npcHandler:releaseFocus(cid)
        end
    end

    return true
end

function creatureReleaseFocusCallback(cid)
    talkState[cid] = nil
    talkPlayer = 0
    talkHppc.player = 100
    talkHppc.npc = 100
    return true
end

function creatureGreetCallback(cid)
    local player = Player(talkPlayer)
    if not player then
        player = Player(cid)
        selfSay(string.format("Hello {%s}, would you like to answer some questions and earn rewards?", player:getName()), cid)
        talkPlayer = cid
        npcHandler:addFocus(cid)
    elseif player ~= Player(cid) then
        selfSay(string.format("Estoy ocupado jugando con {%s}, por favor espera tu turno.", player:getName()), cid)
        talkPlayer = 0
    end
    return false
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:setCallback(CALLBACK_GREET, creatureGreetCallback)
npcHandler:setCallback(CALLBACK_ONRELEASEFOCUS, creatureReleaseFocusCallback)
npcHandler:addModule(FocusModule:new())

View attachment 54517
If you win then you get a reward. 🤑
If you lose nothing happens, the npc will simply make fun of you for being a fool. 🤣

Note: it is worth mentioning that there are not many questions, this job is for you, enrich the npc with too many questions to make it very realistic and fun
I know it is not perfect, but I hope it will help you or an example for something you want to do
Great work Sarah. Very clean code, cheers mate :)
 
Hello if you have time, and do you want to create something like this...

[Automatic MultiPromotion System with bonuses]

on level 1 we start as a druid on level 20 automatically transforms us into an elder druid then at 50 into Royal Druid
20 lvl bonus +150hp and +500mp and new outfit druid (with 2 addons)
50 lvl bonus +25speed and 500mp and new outfit summoner (with 2 addons)

Hi @Avandia

data/scripts/yourscriptname.lua
Lua:
local storage = 777666 -- make sure the storage is unique and is not being used on another system
local advanceConfig = {
    {
        level = 20,
        nextVocation = "Elder Druid",
        extraHp = 150,
        extraMp = 500,
        outfit = {148, 144, 3} -- Druid for male and female with 2 addons
    },
    {
        level = 50,
        nextVocation = "Royal Druid",
        extraMp = 500,
        extraSpeed = 25,
        outfit = {141, 133, 3} -- Summoner for male and female with 2 addons
    }
}

local cAdvanceEvent = CreatureEvent("AdvanceRewardByLvl")
function cAdvanceEvent.onAdvance(player, skill, oldLevel, newLevel)
    if skill == SKILL_LEVEL then
        local load_level = player:getStorageValue(storage)
        for i, info in pairs(advanceConfig) do
            if newLevel >= info.level and load_level < info.level then
                player:setStorageValue(storage, info.level)
                local description = ""
                if info.nextVocation then
                    local newVocation = Vocation(info.nextVocation)
                    if newVocation then
                        player:setVocation(newVocation)
                        description = string.format("You have been promoted to %s.", info.nextVocation)
                    end
                end
                if info.extraHp then
                    local maxHp = player:getMaxHealth()
                    player:setMaxHealth(maxHp + info.extraHp)
                    description = string.format("%s\nYour max health has increased by %d points.", description, info.extraHp)
                end
                if info.extraMp then
                    local maxMp = player:getMaxMana()
                    player:setMaxMana(maxMp + info.extraMp)
                    description = string.format("%s\nYour max mana has increased by %d points.", description, info.extraMp)
                end
                if info.extraSpeed then
                    local baseSpeed = player:getBaseSpeed()
                    player:changeSpeed(baseSpeed + info.extraSpeed)
                    description = string.format("%s\nYour speed has increased by %d.", description, info.extraSpeed)
                end
                if info.outfit then
                    if not player:hasOutfit(info.outfit[1], info.outfit[3]) or not player:hasOutfit(info.outfit[2], info.outfit[3]) then
                        player:addOutfitAddon(info.outfit[1], info.outfit[3])
                        player:addOutfitAddon(info.outfit[2], info.outfit[3])
                        description = string.format("%s\nYou now have got %s outfit.", description, Outfit(info.outfit[1]).name)
                    end
                end
                player:sendTextMessage(MESSAGE_INFO_DESCR, description)
            end
        end
    end
    return true
end
cAdvanceEvent:register()

local cLoginEvent = CreatureEvent("AdvanceRewardLogin")
function cLoginEvent.onLogin(player)
    player:registerEvent("AdvanceRewardByLvl")
    local load_level = player:getStorageValue(storage)
    for i, info in pairs(advanceConfig) do
        if load_level >= info.level then
            if info.extraSpeed then
                local baseSpeed = player:getBaseSpeed()
                player:changeSpeed(baseSpeed + info.extraSpeed)
            end
        end
    end
    return true
end
cLoginEvent:register()

GIF 04-02-2021 11-43-47 a. m..gif
 
Last edited:
Hi @Avandia

data/scripts/yourscriptname.lua
Lua:
local storage = 777666 -- make sure the storage is unique and is not being used on another system
local advanceConfig = {
    {
        level = 20,
        nextVocation = "Elder Druid",
        extraHp = 150,
        extraMp = 500,
        outfit = {148, 144, 3} -- Druid for male and female with 2 addons
    },
    {
        level = 50,
        nextVocation = "Royal Druid",
        extraMp = 500,
        extraSpeed = 25,
        outfit = {141, 133, 3} -- Summoner for male and female with 2 addons
    }
}

local cAdvanceEvent = CreatureEvent("AdvanceRewardByLvl")
function cAdvanceEvent.onAdvance(player, skill, oldLevel, newLevel)
    if skill == SKILL_LEVEL then
        local load_level = player:getStorageValue(storage)
        for i, info in pairs(advanceConfig) do
            if newLevel >= info.level and load_level < info.level then
                player:setStorageValue(storage, info.level)
                local description = ""
                if info.nextVocation then
                    local newVocation = Vocation(info.nextVocation)
                    if newVocation then
                        player:setVocation(newVocation)
                        description = string.format("You have been promoted to %s.", info.nextVocation)
                    end
                end
                if info.extraHp then
                    local maxHp = player:getMaxHealth()
                    player:setMaxHealth(maxHp + info.extraHp)
                    description = string.format("%s\nYour max health has increased by %d points.", description, info.extraHp)
                end
                if info.extraMp then
                    local maxMp = player:getMaxMana()
                    player:setMaxMana(maxMp + info.extraMp)
                    description = string.format("%s\nYour max mana has increased by %d points.", description, info.extraMp)
                end
                if info.extraSpeed then
                    local baseSpeed = player:getBaseSpeed()
                    player:changeSpeed(baseSpeed + info.extraSpeed)
                    description = string.format("%s\nYour speed has increased by %d.", description, info.extraSpeed)
                end
                if info.outfit then
                    if not player:hasOutfit(info.outfit[1], info.outfit[3]) or not player:hasOutfit(info.outfit[2], info.outfit[3]) then
                        player:addOutfitAddon(info.outfit[1], info.outfit[3])
                        player:addOutfitAddon(info.outfit[2], info.outfit[3])
                        description = string.format("%s\nYou now have got %s outfit.", description, Outfit(info.outfit[1]).name)
                    end
                end
                player:sendTextMessage(MESSAGE_INFO_DESCR, description)
            end
        end
    end
    return true
end
cAdvanceEvent:register()

local cLoginEvent = CreatureEvent("AdvanceRewardLogin")
function cLoginEvent.onLogin(player)
    player:registerEvent("AdvanceRewardByLvl")
    return true
end
cLoginEvent:register()

View attachment 54535
Speed isn't saved, once player logs out/dies, speed is lost.
 
Speed isn't saved, once player logs out/dies, speed is lost.
Thanks for your review, the problem is solved!
Post automatically merged:

Hello Sarah.
I need EXP online players bonus
5 - 19EXP +5%
20 - 49EXP +10%
50 - 99EXP +15%
100 - 249EXP +20%
250 - 399EXP +25%
400+EXP +30%
tfs 1.3
Hi @robert100

OPTION 1 (eventcallbacks):
open the file: data/scripts/eventcallbacks/player/default_onGainExperience.lua

look for this code: local ev = EventCallback
now above this code you are going to paste the following:
Lua:
local expOnlineBonus = {
    [{5, 19}] = 5,
    [{20, 49}] = 10,
    [{50, 99}] = 15,
    [{100, 249}] = 20,
    [{250, 399}] = 25,
    [{400}] = 30
}
table.sort(expOnlineBonus, function(a, b) return a > b end)

look for this code: return exp is most likely at the end of this file.
now above this code you are going to paste the following:
Lua:
    local players = #Game.getPlayers()
    for range, bonus in pairs(expOnlineBonus) do
        if players >= range[1] and (players <= (range[2] or math.huge)) then
            exp = exp * (1 + (bonus / 100))
            break
        end
    end

OPTION 2 (classic events):
open the file: data/events/scripts/player.lua
look for this code: function Player:onGainExperience(source, exp, rawExp) is most likely at the end of this file.
now above this code you are going to paste the following:
Lua:
local expOnlineBonus = {
    [{5, 19}] = 5,
    [{20, 49}] = 10,
    [{50, 99}] = 15,
    [{100, 249}] = 20,
    [{250, 399}] = 25,
    [{400}] = 30
}
table.sort(expOnlineBonus, function(a, b) return a > b end)
look for this code: return exp is most likely at the end of this file.
1612455844043.png
now above this code you are going to paste the following:
Lua:
    local players = #Game.getPlayers()
    for range, bonus in pairs(expOnlineBonus) do
        if players >= range[1] and (players <= (range[2] or math.huge)) then
            exp = exp * (1 + (bonus / 100))
            break
        end
    end

GIF 04-02-2021 12-25-25 p. m..gif
Post automatically merged:

Hello Sarah, good scripts you doing here ^^.
Can you make one for outfit and mounts bonuses? Each full outfit/mount obtained you gain some bonuses like +hp, +mana, +skills, they being in intervals: First mount/outfit: +1%hp, Second mount/outfit: +1%mp, third mount/outfit: +1skills (sword,axe,club,ml), Fourth mount/outfit: +1%hp and so on
Hi @jacqen

data/scripts/yourscriptname.lua
Lua:
local outfitBonus = {
    [137] = { -- Hunter
        addons = 3, -- Require Addon
        [370] = {
            hp = 1,
            mp = 1,
            skill = {CONDITION_PARAM_SKILL_AXE, 1}
        },
        [368] = {
            hp = 2,
            mp = 2,
            skill = {CONDITION_PARAM_SKILL_AXE, 2}
        }
    },
    [138] = { -- Mage
        addons = 3, -- Require Addon
        [368] = {
            hp = 1, -- in %
            mp = 1, -- in %
            skill = {CONDITION_PARAM_SKILL_SWORD, 1}
        }
    }
}

local ev = EventCallback
function ev.onChangeOutfit(creature, outfit)
    local currentOutfit = creature:getOutfit()
    local bonus = outfitBonus[currentOutfit.lookType]
    if bonus and currentOutfit.lookAddons >= bonus.addons then
        local mount = bonus[currentOutfit.lookMount]
        if mount then
            creature:removeCondition(CONDITION_ATTRIBUTES, CONDITIONID_COMBAT, 500 + currentOutfit.lookMount, true)
            creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
        end
    end
    local bonus = outfitBonus[outfit.lookType]
    if bonus and outfit.lookAddons >= bonus.addons then
        local mount = bonus[outfit.lookMount]
        if mount then
            local condition = Condition(CONDITION_ATTRIBUTES)
            condition:setParameter(CONDITION_PARAM_TICKS, -1)
            condition:setParameter(CONDITION_PARAM_SUBID, 500 + outfit.lookMount)
            if mount.hp then
                condition:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, 100 + mount.hp)
            end
            if mount.mp then
                condition:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, 100 + mount.mp)
            end
            if mount.skill then
                condition:setParameter(mount.skill[1], mount.skill[2])
            end
            creature:addCondition(condition)
            creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
        end
    end
    return true
end

Next I will show you a visual example of how it looks when you get the bonus and when you lose it due to lack of requirements
GIF 04-02-2021 01-10-49 p. m..gif

In the configuration table you can configure bonuses for each outfit, and each outfit can have its combination with a different mount, in such a way that each mount in conjunction with your outfit can give you different bonuses
 
Last edited:
hi Sarah sorry but I don't know if you can create a script ..
I would like you to create 2 mosters as you pass through the floor, but to have time. For example, when passing over it, it will create the 2 mosters and when it happens again, it does not create anything since you have to wait 1 hour for you to pass again .. I don't know if you understand me

it's for a quest

yes no then at least answer me with a (no, or a yes)
since you are ignoring me now to know and not bother if it is too much to ask thanks
 
hi Sarah sorry but I don't know if you can create a script ..
I would like you to create 2 mosters as you pass through the floor, but to have time. For example, when passing over it, it will create the 2 mosters and when it happens again, it does not create anything since you have to wait 1 hour for you to pass again .. I don't know if you understand me

it's for a quest

yes no then at least answer me with a (no, or a yes)
since you are ignoring me now to know and not bother if it is too much to ask thanks
Hello @Kabo Flow you do not cause me any discomfort, if I did not answer the previous messages it is for the simple fact that they did not meet the requirements that I mentioned in the main post.

When I like your post, it will mean that I am working on it, wait your turn patiently
 
Hello @Sarah Wesker I need script that will upgrade item's with atk/def/arm in percent but not like normal one from OTland. Lets call it "Multi Upgrade System"
Example: I have magic sword that wanna to upgrade so I use itemid 1111 on it and upgrade it one by one up to +15 then when I have +15 magic sword I use itemid 2222 on it to upgrade it further up to +30 and then next itemid 3333 upgrade it up to +50.

Awesome work btw, most of those scripts bring me some new content already :)
 
Status
Not open for further replies.
Back
Top