Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3011da6
Feat: Spell-Learning-System
Paco161315 Jan 20, 2026
6dc8e62
Lua code format - (Stylua)
github-actions[bot] Jan 20, 2026
1f0bd68
Update: Added toggle in config.lua
Paco161315 Jan 23, 2026
abb5b0d
Code format - (Clang-format)
github-actions[bot] Jan 23, 2026
87dad43
Fix: Keyword order fix
Paco161315 Jan 25, 2026
690bed6
Lua code format - (Stylua)
github-actions[bot] Jan 25, 2026
1be692f
Fix: Added New Spells + Keyword Fix
Paco161315 Jan 27, 2026
23ea90f
Merge branch 'feat-spell-learning-system' of https://github.com/Paco1…
Paco161315 Jan 27, 2026
0d2799c
Fix: Chained Penance
Paco161315 Jan 27, 2026
9c2018b
Fix: Spells update
Paco161315 Jan 27, 2026
808f3ce
Fix: NPC Rune Spells and Invisibility
Paco161315 Jan 29, 2026
da6ee84
Lua code format - (Stylua)
github-actions[bot] Jan 29, 2026
816c4ff
Fix: More Keyword Arrange
Paco161315 Jan 30, 2026
c41539d
Merge branch 'feat-spell-learning-system' of https://github.com/Paco1…
Paco161315 Jan 30, 2026
6cec462
Lua code format - (Stylua)
github-actions[bot] Jan 30, 2026
8d9bc19
Remove wrong name spells
Paco161315 Jan 30, 2026
35aff68
Merge branch 'feat-spell-learning-system' of https://github.com/Paco1…
Paco161315 Jan 30, 2026
42b1a40
Fix: Monk Spell update. NPC Eliza and keyword fixes.
Paco161315 Feb 2, 2026
9a903f5
Fix: NPC Keywords + Spell Fix + New NPCs
Paco161315 Feb 2, 2026
3ecc759
Update: Added Lesser Ethereal Spear
Paco161315 Feb 8, 2026
212ee3d
Lua code format - (Stylua)
github-actions[bot] Feb 8, 2026
8e90ba1
Update Gundralph
Paco161315 Feb 9, 2026
b36da29
Update: Dawnport Vocation Trial
Paco161315 Feb 11, 2026
1dbf18b
Update: Chained Penance
Paco161315 Feb 25, 2026
9db627d
Update: All Tibia NPCs
Paco161315 Mar 10, 2026
9e8f885
Lua code format - (Stylua)
github-actions[bot] Mar 10, 2026
2a7c620
Fix: Handle House Spells
Paco161315 Mar 11, 2026
70877b4
Merge branch 'feat-spell-learning-system' of https://github.com/Paco1…
Paco161315 Mar 11, 2026
e669cb7
Lua code format - (Stylua)
github-actions[bot] Mar 11, 2026
20e2737
Restore eremo code for merge.
Paco161315 Mar 19, 2026
738ae85
Lua code format - (Stylua)
github-actions[bot] Mar 19, 2026
ee4589e
Merge branch 'main' into feat-spell-learning-system
jprzimba Mar 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.lua.dist
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ combatChainSkillFormulaMissile = 0.9
combatChainSkillFormulaWandsAndRods = 1.0

-- Spells
toggleLearnSpells = true
emoteSpells = false
spellNameInsteadOfWords = false

Expand Down
95 changes: 95 additions & 0 deletions data-global/npc/asrak.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,101 @@ npcType.onCloseChannel = function(npc, creature)
npcHandler:onCloseChannel(npc, creature)
end

local node1 = keywordHandler:addKeyword({ "arrow call" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {arrow call} magic spell for free?" })
node1:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "arrow call", vocation = { 3, 7 }, price = 0, level = 1 })

local node2 = keywordHandler:addKeyword({ "bruise bane" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {bruise bane} magic spell for free?" })
node2:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "bruise bane", vocation = { 4, 8 }, price = 0, level = 1 })

local node3 = keywordHandler:addKeyword({ "conjure explosive arrow" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {conjure explosive arrow} magic spell for 1000 gold?" })
node3:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "conjure explosive arrow", vocation = { 3, 7 }, price = 1000, level = 25 })

local node4 = keywordHandler:addKeyword({ "conjure arrow" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {conjure arrow} magic spell for 450 gold?" })
node4:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "conjure arrow", vocation = { 3, 7 }, price = 450, level = 13 })

local node5 = keywordHandler:addKeyword({ "cure poison" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {cure poison} magic spell for 150 gold?" })
node5:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "cure poison", vocation = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, price = 150, level = 10 })

local node6 = keywordHandler:addKeyword({ "destroy field" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {Destroy Field} Rune spell for 700 gold?" })
node6:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "destroy field rune", vocation = { 1, 2, 3, 5, 6, 7, 9, 10 }, price = 700, level = 17 })

local node7 = keywordHandler:addKeyword({ "divine healing" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {divine healing} magic spell for 3000 gold?" })
node7:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "divine healing", vocation = { 3, 7 }, price = 3000, level = 35 })

local node8 = keywordHandler:addKeyword({ "find fiend" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {find fiend} magic spell for 1000 gold?" })
node8:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "find fiend", vocation = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, price = 1000, level = 25 })

local node9 = keywordHandler:addKeyword({ "find person" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {find person} magic spell for 80 gold?" })
node9:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "find person", vocation = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, price = 80, level = 8 })

local node10 = keywordHandler:addKeyword({ "great light" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {great light} magic spell for 500 gold?" })
node10:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "great light", vocation = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, price = 500, level = 13 })

local node11 = keywordHandler:addKeyword({ "intense healing" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {intense healing} magic spell for 350 gold?" })
node11:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "intense healing", vocation = { 1, 2, 3, 5, 6, 7, 9, 10 }, price = 350, level = 20 })

local node12 = keywordHandler:addKeyword({ "lesser ethereal spear" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {lesser ethereal spear} magic spell for free?" })
node12:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "lesser ethereal spear", vocation = { 3, 7 }, price = 0, level = 1 })

local node13 = keywordHandler:addKeyword({ "lesser front sweep" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {lesser front sweep} magic spell for free?" })
node13:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "lesser front sweep", vocation = { 4, 8 }, price = 0, level = 1 })

local node14 = keywordHandler:addKeyword({ "light healing" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {light healing} magic spell for free?" })
node14:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "light healing", vocation = { 1, 2, 3, 5, 6, 7, 9, 10 }, price = 0, level = 8 })

local node15 = keywordHandler:addKeyword({ "light" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {light} magic spell for free?" })
node15:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "light", vocation = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, price = 0, level = 8 })

local node16 = keywordHandler:addKeyword({ "magic patch" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {magic patch} magic spell for free?" })
node16:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "magic patch", vocation = { 1, 2, 3, 5, 6, 7 }, price = 0, level = 1 })

local node17 = keywordHandler:addKeyword({ "wound cleansing" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Would you like to learn {wound cleansing} magic spell for free?" })
node17:addChildKeyword({ "yes" }, StdModule.learnSpell, { npcHandler = npcHandler, premium = false, spellName = "wound cleansing", vocation = { 4, 8 }, price = 0, level = 8 })

keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "I'm the overseer of the pits and a paladin trainer, but I also know some knight spells." })
keywordHandler:addKeyword({ "gladiators" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Those wannabe fighters are weak and most of them are unable to comprehend a higher concept like the Mooh'Tah." })
keywordHandler:addKeyword({ "help" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "I teach worthy warriors the way of the knight." })
keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "I'm known as Asrak the Ironhoof." })
keywordHandler:addKeyword({ "king", "tibianus" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "I pledge no allegiance to any king, be it human or minotaurean." })
keywordHandler:addKeyword({ "army" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Your human army might be big but without skills. They are nothing than sheep to be slaughtered." })
keywordHandler:addKeyword({ "general" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "The human generals are like their warriors. They lack the focus to be true warriors." })
keywordHandler:addKeyword({ "dungeon" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "The dungeons of your desires and fears are not only the solely ones you have to fear but also the only ones you have to conquer." })
keywordHandler:addKeyword({ "gods" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "They implanted the rage in us that almost cost our existence. They used us as pawns in wars that were not ours." })
keywordHandler:addKeyword({ "monsters" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Inferior creatures of rage, driven by their primitive urges. They are only useful to test one's skills." })
keywordHandler:addKeyword({ "ferumbras" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "To rely on magic is like cheating fate. All cheaters will get their just punishment one day, and so will he." })
keywordHandler:addKeyword({ "excalibug" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "If it's truly a weapon to slay gods, it might be worth searching for it." })
keywordHandler:addKeyword({ "venore" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "The city pays me well and those undisciplined gladiators need my skills and guidance badly." })
keywordHandler:addKeyword({ "mintwallin" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "The city is only a shadow of what we could have accomplished without that curse of rage that the gods bestowed upon us." })
keywordHandler:addKeyword({ "minotaur" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "In the ancient wars we lost many things due to our rage. The only good thing is that we lost our trust in the gods, too." })
keywordHandler:addKeyword({ "mooh'tah" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "The Mooh'Tah teaches control. It provides you with weapon, armor, and shield. It teaches you harmony and focus." })
keywordHandler:addKeyword({ "rage" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Rage is the legacy of Blog, the beast. It is our primary goal to overcome this rage. The Mooh'Tah is our only hope of salvation and perfection." })
keywordHandler:addKeyword({ "harmony" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "There is harmony in everything that is done correctly. If you feel the harmony of an action, you can sing its song." })
keywordHandler:addKeyword({ "song", "sing" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Each harmonic action has it own song. If you can sing it, you are in harmony with that action. This is where the minotaurean battle songs come from." })
keywordHandler:addKeyword({ "battlesongs" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Each Mooh'Tah master focuses his skills on the harmony of battle. He is one with the song that he's singing with his voice or at least his heart." })
keywordHandler:addKeyword({ "weapon" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Make your will your weapon, and your enemies will perish." })
keywordHandler:addKeyword({ "armor" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Courage is the only armor that shields you against rage and fear, the greatest dangers you are facing." })
keywordHandler:addKeyword({ "shield" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Your confidence shall be your shield. Nothing can penetrate that defence." })

keywordHandler:addKeyword({ "spells" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "I can teach you {healing}, {support}, {conjure} and {runes} spells. I can also tell you which spells are available at your {level}." })
keywordHandler:addKeyword({ "healing" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Healing spells: {Bruise Bane}, {Cure Poison}, {Divine Healing}, {Intense Healing}, {Light Healing}, {Magic Patch}, {Wound Cleansing}." })
keywordHandler:addKeyword({ "support" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Support spells: {Arrow Call}, {Find Fiend}, {Find Person}, {Great Light}, {Lesser Ethereal Spear}, {Lesser Front Sweep}, {Light}." })
keywordHandler:addKeyword({ "conjure" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Conjure spells: {Conjure Arrow}, {Conjure Explosive Arrow}." })
keywordHandler:addKeyword({ "runes" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "Rune spells: {Destroy Field} Rune." })

local nodeLevels = keywordHandler:addKeyword({ "level" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "I have spells for level {1}, {8}, {10}, {13}, {17}, {20}, {25} and {35}." })

nodeLevels:addChildKeyword({ "1" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 1 I have {Arrow Call} for free, {Bruise Bane} for free, {Lesser Ethereal Spear} for free, {Lesser Front Sweep} for free and {Magic Patch} for free." })
nodeLevels:addChildKeyword({ "8" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 8 I have {Find Person} for 80 gold, {Light} for free, {Light Healing} for free and {Wound Cleansing} for free." })
nodeLevels:addChildKeyword({ "10" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 10 I have {Cure Poison} for 150 gold." })
nodeLevels:addChildKeyword({ "13" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 13 I have {Conjure Arrow} for 450 gold and {Great Light} for 500 gold." })
nodeLevels:addChildKeyword({ "17" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 17 I have {Destroy Field} Rune for 700 gold." })
nodeLevels:addChildKeyword({ "20" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 20 I have {Intense Healing} for 350 gold." })
nodeLevels:addChildKeyword({ "25" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 25 I have {Conjure Explosive Arrow} for 1000 gold and {Find Fiend} for 1000 gold." })
nodeLevels:addChildKeyword({ "35" }, StdModule.say, { npcHandler = npcHandler, onlyFocus = true, text = "For level 35 I have {Divine Healing} for 3000 gold." })

npcHandler:setMessage(MESSAGE_GREET, "I welcome you, |PLAYERNAME|! If you need paladin or knight spells, you've come to the right place.")
npcHandler:setMessage(MESSAGE_FAREWELL, "May your path be as straight as an arrow.")

npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true)

-- npcType registering the npcConfig table
Expand Down
Loading
Loading