• 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.x] Printer's Free Coding Help and Request Service

Printer

if Printer then print("LUA") end
Senator
Premium User
Joined
Dec 27, 2009
Messages
5,781
Solutions
31
Reaction score
2,293
Location
Sweden?
Hello,

well i would like to make new thread. To help people make good and readable codes. I can also help you optimize your old codes and explain, if you post them here.

Here is some example of optimizations:

Usually what is see what people do:

Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if item.itemid == 2148 then
        print("This is a gold coin.")
    elseif item.itemid == 2152 then
        print("This is a platium coin.")
    elseif item.itemid == 2160 then
        print("This is a crystal coin.")
    end

    return true
end

How i would do:
Code:
local config = {
    [2148] = "This is a gold coin.",
    [2152] = "This is a platium coin.",
    [2160] = "This is a crystal coin."
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    print(config[item.itemid])
end

or

Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    print("This is a ".. ItemType(item.itemid):getName() ..".")
end

Some useful codes:

Cheers everyone!
 
Last edited:
Code:
function onDeath(monster, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    -- Disable Loot
    monster:setDropLoot(false)

    -- Handle Loot Manually
    local lootText = ""
    local random = math.random
    local loot = MonsterType(monster:getName()):getLoot()
    for k, v in ipairs(loot) do
        local randomValue = random(v.chance) / configManager.getNumber(configKeys.RATE_LOOT)
        if randomValue < v.chance then
            local count = random(v.maxCount)
            local item = Game.createItem(v.itemId, count)
            if item then
                if v.actionId then
                    item:setAttribute(ITEM_ATTRIBUTE_ACTIONID, v.actionId)
                end

                if v.text then
                    item:setAttribute(ITEM_ATTRIBUTE_TEXT, v.text)
                end

                corpse:addItemEx(item)
                lootText = string.format("%s%s%s ", lootText, count > 1 and string.format("%d %s", count, item:getPluralName()) or item:getName(), (#loot > k and "," or "."))
            end
        end
    end

    killer:sendTextMessage(MESSAGE_INFO_DESCR, string.format("Loot of %s: %s", monster:getName():lower(), lootText ~= "" and lootText or "nothing."))
    return true
end
 
Yes! finally!

I have the following script for an oracleish NPC, he only assigns 2 vocations, Squire and Archer, but the script is now working, could you please help me? I've added some notes for clarifying purposes

Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)


function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end
function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end
function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end
function onThink() npcHandler:onThink() end

local Topic = {}
local vocStr = {Squire, Archer}
local vocNum = {4, 6}
local voc = 0

--[[function thinkCallback(cid)
if math.random(300) == 1 then
npcHandler:say("Join the Guard today!")
end
return true
end]]

function creatureSayCallback(cid, type, msg)
   if getPlayerVocation(cid) == 0 then -- checks if player has no vocation and offers enrollment
        npcHandler:say("Ah! Hiho! |PLAYERNAME|, I see you haven't chosen a career path, the royal guard has open positions, would you like to {enroll}?", cid)
        npcHandler:addFocus(cid)
        Topic[cid] = 0
        while Topic[cid] == 0 do
            if msgcontains(msg, "enroll") or msgcontains(msg, "yes") and Topic[cid] == 0 then
                npcHandler:say ("Oh, so you want to enroll to the guard, yes?", cid)
                if msgcontains (msg, "yes") then
                    Topic[cid] = 1
                elseif msgcontains (msg, "no") then
                    npcHandler:say ("That's a shame!", cid)
                else
                    npcHandler:say ("What was that?", cid)
                end
            elseif Topic[cid] == 1 then
                npcHandler:say ("Very well. Here at the guard we have two branches, {melee} fighters and {distance} fighters; What would you like to specialize in?", cid)
                if msgcontains (msg, "melee") then
                    voc = 1
                    assgnvoc(cid)
                elseif msgcontains (msg, "distance") then
                    voc = 2
                    assgnvoc(cid)
                    else
                    npcHandler:say ("What was that?", cid)
                    Topic[cid] = 0
                end                   
            elseif Topic[cid] == 0 then
                npcHandler:say ("So, how may I help you?", cid)
            end       
        end   
    elseif getPlayerVocation(cid) ~= 4 or 6 then -- gives custom greet to those who do not belong to the guard
        npcHandler:say("Oh, hi, |PLAYERNAME|. Welcome to the Guard HQ. How may I help you?", cid)
        npcHandler:addFocus(cid)
    elseif getPlayerVocation(cid) == 4 or 6 and Topic[cid] == 0 then  -- welcomes back to members of the guard
        npcHandler:say("Ah! Hello, welcome back |PLAYERNAME|.", cid)
        npcHandler:addFocus(cid)
    end
end

-- Set the greeting message.
npcHandler:setMessage(MESSAGE_GREET, 'Hey! Who is this?! Identify yourself!')
-- Set the greeting callback function
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)

function assgnvoc(cid)
    doPlayerSetVocation(cid, vocNum[voc])
    npcHandler:say ("Alright, you are now a "..vocStr[voc].." for the guard.", cid)
    npcHandler:say ("There's some more stuff I should teach you before you leave, do you want me to give you a short tutorial?", cid)
    if msgcontains (msg, "yes") then
        npcHandler:say ("Great! let's begin!", cid)
        if voc == 1 then
            tutorial(cid)
            tutorialmelee(cid)
            tutorialheal(cid)
        else
            tutorial(cid)
            tutorialheal(cid)
        end
        npcHandler:say ("From now on you can ask for {missions} to me or Warden Finduin.", cid)
    else
        npcHandler:say ("Are you sure? This information is quite important...", cid)
        if msgcontains (msg, "yes") then
            npcHandler:say ("That's a shame, but as you wish. From now on you can ask for {missions} to me or Warden Finduin.", cid)
            Topic[cid] = 0
        else
            npcHandler:say ("Great! let's begin!", cid)
            tutorial(cid)
        end   
    end
end

function tutorial(cid)
    npcHandler:say("Very well. First of all, if you want to walk faster, you just need to {<dash>}, got it?", cid)
        if msgcontains(msg, "yes") then
            npcHandler:say("Good! moving on...", cid)
        elseif msgcontains(msg, "no") then
            npcHandler:say("No worries, just say {<dash>} to focus your energy and you'll walk faster. Ok?", cid)
        end
end
   
function tutorialmelee(cid)
    npcHandler:say("Now that you've learnt how to focus your energy to dash, let's see how you {<strike>}, got it?", cid)
        if msgcontains(msg, "yes") then
            npcHandler:say("Excellent! You're a fast learner!", cid)
        elseif msgcontains(msg, "no") then
            npcHandler:say("I see. Just like dashing, to make a good hit, you need to focus by saying {<strike>} and your target will receive a good blow! Alrite?", cid)
        end
end

function tutorialheal(cid)
     npcHandler:say("We're almost done so hang in there with me. Last but not least, I'm gonna show you how can you regain health. You can either {<apply bandage>}, but that will obviously require that you are carrying bandages with you; or you can pray to our Almighty 'El' to heal you, just repeat after me {I placito gratia habituali sanante}, Ok?", cid)
        if msgcontains(msg, "yes") then
            npcHandler:say("Nice! We're done now, it wasn't so bad, was it? You can keep coming to me to show you new techniqes, you just need to get {experience}", cid)
        elseif msgcontains(msg, "no") then
            npcHandler:say("It's OK, to be able to {<apply bandage>} you must be sure you have an available bandage in your backpack, else it won't work. For the prayer, you have to say {I placito gratia habituali sanante}, but you must have the required energy to do so, Alright? See? it didn't take me so long after all! Haha!")
        end
end

-- npc answer to keyword "job"
local jobNode = keywordHandler:addKeyword({'job'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I\'m the commander of the royal guard, my job is to overlook the safety of our citizens and {enroll} new recruits to man the guard.'})
   
-- npc answer to keyword "information"
local infoNode = keywordHandler:addKeyword({'information'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Here at the guard we employ {Melee} and {Distance} fighters only.'})

-- npc answer to keyword "mission"
local missionNode = keywordHandler:addKeyword ({'mission'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'There are no new missions at this moment, come back later.'})


npcHandler:addModule(FocusModule:new())
 
Last edited by a moderator:
@Printer I use TFS 1.1

1. I'd like that the NPC gives a custom greet depending on the players vocation (that's what the first 'if' in the
creatureSayCallback function is for).
2. If the player doesn't have a vocation that the NPC offers him/her to join the NPC's faction (The Guard in this case)
3. If the player do joins the Guard, the NPC's must ask if the player want's to receive a small tutorial on how to use some custom spells for his/her vocation.
 
Last edited:
@Printer I use TFS 1.1

1. I'd like that the NPC gives a custom greet depending on the players vocation (that's what the first 'if' in the
creatureSayCallback function is for).
2. If the player doesn't have a vocation that the NPC offers him/her to join the NPC's faction (The Guard in this case)
3. If the player do joins the Guard, the NPC's must ask if the player want's to receive a small tutorial on how to use some custom spells for his/her vocation.
Ill, help you tomorrow.

-- Double Post Merged --

Request: https://otland.net/threads/how-to-prevent-a-players-death.238729/

Code:
local config = {
    dropCorpse = true,
    dropLoot = true
}

local conditionList = {CONDITION_POISON, CONDITION_FIRE, CONDITION_ENERGY}
function onPrepareDeath(player, killer)
    -- Corpse drop
    if config.dropCorpse then
        local corpse = Game.createItem(player:getSex() == PLAYERSEX_FEMALE and 3065 or 3058, 1, player:getPosition())
        if corpse then
            -- Set corpse description
            local killerName = "undefined"
            if killer then
                if killer:isPlayer() then
                    killerName = killer:getName()
                elseif killer:isMonster() then
                    local master = killer:getMaster()
                    if master and master:isPlayer() then
                        killer = master
                        isPlayer = true
                    else
                        killerName = killer:getName():lower()
                    end
                end
            else
                killerName = "field item"
            end

            corpse:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, string.format("You recognize %s. %s was killed by %s.", player:getName(), player:getSex() == PLAYERSEX_FEMALE and "She" or "He", killerName))          

            -- Loot drop
            if config.dropLoot then
                player:dropLoot(corpse)
            end
        end
    end

    -- Remove conditions
    for i = 1, #conditionList do
        player:removeCondition(conditionList[i])
    end
  
    -- Teleport to town temple and heal
    local templePosition = player:getTown():getTemplePosition()
    player:teleportTo(templePosition)
    templePosition:sendMagicEffect(CONST_ME_TELEPORT)
    player:addHealth(player:getMaxHealth())
    player:addMana(player:getMaxMana())
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are dead.")
    return false
end

function Player.dropLoot(self, corpse)
    if getPlayerFlagValue(self, PlayerFlag_NotGenerateLoot) or self:getVocation():getId() == VOCATION_NONE then
        return
    end

    local amulet = self:getSlotItem(CONST_SLOT_NECKLACE)
    if amulet and amulet.itemid == ITEM_AMULETOFLOSS and not isInArray({SKULL_RED, SKULL_BLACK}, self:getSkull()) then
        local isPlayer = false
        if killer then
            if killer:isPlayer() then
                isPlayer = true
            else
                local master = killer:getMaster()
                if master and master:isPlayer() then
                    isPlayer = true
                end
            end
        end

        if not isPlayer or not player:hasBlessing(6) then
            self:removeItem(ITEM_AMULETOFLOSS, 1, -1, false)
        end
    else
        for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
            local item = self:getSlotItem(i)
            if item then
                if isInArray({SKULL_RED, SKULL_BLACK}, self:getSkull()) or math.random(item:isContainer() and 100 or 1000) <= 100 then
                    if not item:moveTo(corpse) then
                        item:remove()
                    end
                end
            end
        end
    end

    if not self:getSlotItem(CONST_SLOT_BACKPACK) then
        self:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK)
    end
end
 
Last edited by a moderator:
Hi printer!
Well i need some stuff for my server very simple stuff.

1) NPC checks if you are level 8-9, if you do, it gives you the option to travel to a NEW TOWN or stay here forever and be a ROOKSTAYER.
if player choose rookstayer, oracle will say go to "x" person, and give your SERVICES and give storageid.

2) NPC will check if there is storage of rookstayer, if not npc says im not receiving anybody for the moment, if it does have storage, NPC now that you are capable, will you give me your services? yes and provides new vocation rookstayer.

_____________________
3) NPC that teleports to new town, but doesnt teleport if you dont have a vocation.

4) NPC GIVES X VOCATION
 
@Printer - I saw you released a "Gambler" NPC script which is in relation to a "Casino" Event.

In the following thread we have a code built for 1.0 by cbrm for a "Slots" Casino Event.
https://otland.net/threads/1-row-slot-machine-tfs-0-3-0-4-1-0.114783/

My request is to update this to 1.2 due to the current known errors:

  • mayNotMove event does not function properly.
Code:
data/actions/scripts/slot.lua:onUse
data/actions/scripts/slot.lua:189: attempt to call global 'mayNotMove' (a nil value)
stack traceback:
[C]: in function 'mayNotMove'
data/actions/scripts/slot.lua:189: in function <data/actions/scripts/slot.lua:136>

  • When removing "mayNotMove", a new error arises. My areas for the script should be x: 1023 y: 1040 z: 9 to x: 1025 y: 1040 z: 9 - but instead the script tries to place the items on x: 116 y: 321 z: 7 - x: 118 y: 321 z: 7 which it can't because there are no tiles.

The following error repeats for positions 116, 117 and 118.
Code:
data/actions/scripts/slots.lua:onUse
LuaScriptInterface::luaDoTileAddItemEx(). ( 00116 / 00321 / 007 ) Tile not found

stack traceback:
  [C]: in function 'doTileAddItemEx'
  data/actions/scripts/slots.lua:165: in function 'doFruit'
  data/actions/scripts/slots.lua:192: in function <data/actions/scripts/sl
ots.lua:136>

I haven't seen any changes to the doTileAddItemEx function in atleast 8+ months judging from sources.
So, figured I'd post this here! :) Have a good day Printer, happy holidays!
 
Hi printer!
Well i need some stuff for my server very simple stuff.

1) NPC checks if you are level 8-9, if you do, it gives you the option to travel to a NEW TOWN or stay here forever and be a ROOKSTAYER.
if player choose rookstayer, oracle will say go to "x" person, and give your SERVICES and give storageid.

2) NPC will check if there is storage of rookstayer, if not npc says im not receiving anybody for the moment, if it does have storage, NPC now that you are capable, will you give me your services? yes and provides new vocation rookstayer.

_____________________
3) NPC that teleports to new town, but doesnt teleport if you dont have a vocation.

4) NPC GIVES X VOCATION
I see no diffrence between your request and The Oracle npc:
https://otland.net/threads/perfect-the-oracle-for-tfs-1-0.218327/
@Printer - I saw you released a "Gambler" NPC script which is in relation to a "Casino" Event.

In the following thread we have a code built for 1.0 by cbrm for a "Slots" Casino Event.
https://otland.net/threads/1-row-slot-machine-tfs-0-3-0-4-1-0.114783/

My request is to update this to 1.2 due to the current known errors:

  • mayNotMove event does not function properly.
Code:
data/actions/scripts/slot.lua:onUse
data/actions/scripts/slot.lua:189: attempt to call global 'mayNotMove' (a nil value)
stack traceback:
[C]: in function 'mayNotMove'
data/actions/scripts/slot.lua:189: in function <data/actions/scripts/slot.lua:136>

  • When removing "mayNotMove", a new error arises. My areas for the script should be x: 1023 y: 1040 z: 9 to x: 1025 y: 1040 z: 9 - but instead the script tries to place the items on x: 116 y: 321 z: 7 - x: 118 y: 321 z: 7 which it can't because there are no tiles.

The following error repeats for positions 116, 117 and 118.
Code:
data/actions/scripts/slots.lua:onUse
LuaScriptInterface::luaDoTileAddItemEx(). ( 00116 / 00321 / 007 ) Tile not found

stack traceback:
  [C]: in function 'doTileAddItemEx'
  data/actions/scripts/slots.lua:165: in function 'doFruit'
  data/actions/scripts/slots.lua:192: in function <data/actions/scripts/sl
ots.lua:136>

I haven't seen any changes to the doTileAddItemEx function in atleast 8+ months judging from sources.
So, figured I'd post this here! :) Have a good day Printer, happy holidays!
mayNotMove does not exsist, should make onStepOut event to return false.
 
@Printer
Could you help me in making this script summoning only one kind of monsters?

Code:
local maxsummons = 3

function onCastSpell(creature, var)
   if not creature:getMaster() then
     local summoncount = creature:getSummons()
     if #summoncount < 3 then
       for i = 1, maxsummons - #summoncount do
         local mid = Game.createMonster("Fire Elemental", creature:getPosition())
         if mid then
           mid:setMaster(creature)
         end
       end
     end
   end
   return true
end
I've been trying to remake it to summon one kind of monsters, but it's hard to check whether it has summoned fire elemental or dragon hatching, since it's summoning 3 at once. It was summoning like 2 fe and 1 dragon hatchling not that I wanted. :/ So I decided to put original script.

First kind is Fire Elemental and second is Dragon Hatching, so for the first time it should summon 3 monsters of one kind at once ex. Fire Elementals, then if one or two of the summons are dead(there's still one summon) script should check what summon is it and summon 2 more summons of same kind, in this case those are Fire Elementals. If there are no summons then it should summon random monsters between Fire Elemental and Dragon Hatching.
Hope you get me. :)

Thanks in advance.
 
@Printer
Naah, can't make it work.. I am not that good hehe. This is where I went so far.
Code:
local maxsummons = 3
local summons = {'fire elemental', 'dragon hatchling'}

function onCastSpell(creature, var)
    if not creature:getMaster() then
        local summoncount = creature:getSummons()
        for i = 1, maxsummons - #summoncount do
            if #summoncount < 1 then
                local mid = Game.createMonster(summons[math.random(#summons)], creature:getPosition())
                if #summoncount > 1 and mid:getName():lower() ~= 'fire elemental' then
                    local mid = Game.createMonster('fire elemental', creature:getPosition())
                elseif #summoncount > 1 and mid:getName():lower() ~= 'dragon hatchling' then
                    local mid = Game.createMonster('dragon hatchling', creature:getPosition())
                end
            end
            if mid then
                mid:setMaster(creature)
            end
        end
    end
return true
end
 
Hard to code from Phone:
Code:
local maxSummon = 3

function onCastSpell(creature, var)
    for i = 1, maxSummon do
        if #creature:getSummons() >= maxSummon then
            break
        end

        local monster = Game.createMonster("Fire Elemental", creature:getPosition()) then
        if monster then
            monster:setMaster(creature)
        end
    end

    return true
end
 
Hard to code from Phone:
Code:
local maxSummon = 3

function onCastSpell(creature, var)
    for i = 1, maxSummon do
        if #creature:getSummons() >= maxSummon then
            break
        end

        local monster = Game.createMonster("Fire Elemental", creature:getPosition()) then
        if monster then
            monster:setMaster(creature)
        end
    end

    return true
end
Yeah, it's for fire elemental, but it don't summon dragon hatchling. Script should work like that:
* Summon 3 monsters of one kind(fire elemental or dragon hatchling)
* If you already have summons, it should check if these are fire elementals or dragon hatchlings
* If you have less than 3 summons it should summon monsters depending on if it's fire elemental or dragon hatchling
* It shouldn't be possible to summon for example dragon hatchling if you have already one or more fire elementals

Hope now you get me. :)
 

Similar threads

Back
Top