Forcing the players to learn spells before using them.
Re: Forcing the players to learn spells before using them.
That's a pretty cool idea.
Re: Forcing the players to learn spells before using them.
How am I supposed to finish my mod if you guys keep developing useful functions?! Stop it!
Currently conspiring with many modders on the "Legends of the Northern Realms"project.
"You have been captured by a psychopathic diety who needs a new plaything to torture."
Hotel Hades
"You have been captured by a psychopathic diety who needs a new plaything to torture."
Hotel Hades
Re: Forcing the players to learn spells before using them.
OK here's my take on a working setup using Grimwold's scripts as a base (I'd have no idea how to accomplish this without those - he's the real hero here, not me), that covers all the standard spells and adds the missing spell scrolls to the collection.
The way it works is, you find a scroll, put it in the inventory of a mage, then right-click it. A sound plays and the mage "learns" the spell and is able to cast it from then on.
First, in your dungeon place a script_entity and name it "spellbook_script." Add to it the following code.
I've commented out the line that plays a sound since you don't have the nice scribbling sound I found. It's easy to put in one of the default sounds ("discover_spell" for example) or quickly Google for a proper scribbling sound.
Next, open your items.lua and add the following.
In case you want to put in your own custom sound, you'll want to place that in the mod_assets/sounds folder of your dungeon, then add the following to your sounds.lua. If your file isn't named scribble.wav, change accordingly. I believe both WAV and OGG formats should work.
I made a few choices on how the system works:
- Scrolls don't disappear on use. Reasons being so the player can continue to use them as reference as well as distribute them amongst multiple mages.
- Requirement for learning a scroll is the same as for casting the spell. I think that makes sense in a lot of ways
- Nobody knows any spells initially. Done to make the early scrolls useful. One might imagine mages know some cheap parlour tricks that aren't relevant to the dungeon.
- Fluffwise, the spells are scribed into an abstract spellbook held by the individual mage. Reasons being D&D is cool.
If you want scrolls to be consumed, just add a "return true" statement to the learnSpellFunction when a spell is learned.
If you want some spells to be known initially by everyone, simply put =1 in place of =0 at the spellbook array in the script_entity after the relevant spells.
The way it works is, you find a scroll, put it in the inventory of a mage, then right-click it. A sound plays and the mage "learns" the spell and is able to cast it from then on.
First, in your dungeon place a script_entity and name it "spellbook_script." Add to it the following code.
Code: Select all
spellbook = {darkness = 0, enchant_fire_arrow = 0, enchant_frost_arrow = 0, enchant_shock_arrow = 0,
enchant_poison_arrow = 0, fire_shield = 0, fireball = 0, fireburst = 0, frost_shield = 0, frostbolt = 0,
ice_shards = 0, invisibility = 0, light = 0, lightning_bolt = 0, poison_bolt = 0, poison_cloud = 0,
poison_shield = 0, shock = 0, shock_shield = 0}
spellNames = {darkness = "Darkness", enchant_fire_arrow = "Enchant Fire Arrow",
enchant_frost_arrow = "Enchant Frost Arrow", enchant_shock_arrow = "Enchant Lightning Arrow",
enchant_poison_arrow = "Enchant Poison Arrow", fire_shield = "Fire Shield", fireball = "Fireball",
fireburst = "Fireburst", frost_shield = "Frost Shield", frostbolt = "Frostbolt",
ice_shards = "Ice Shards", invisibility = "Invisibility", light = "Light",
lightning_bolt = "Lightning Bolt", poison_bolt = "Poison Bolt", poison_cloud = "Poison Cloud",
poison_shield = "Poison Shield", shock="Shock", shock_shield = "Shock Shield"}
function checkSpellbook(caster, spell)
if spellbook[spell] == 1 then
return true
elseif spellbook[spell] == 0 then
hudPrint(caster:getName() .. " must learn that spell before casting it.")
return false
end
end
function learnSpell(champ, spell, skill, reqSkill)
if champ:getSkillLevel(skill) >= reqSkill then
if (spellbook[spell] == 0) then
if spellNames[spell] ~= nil then
spellbook[spell] = 1
-- playSound("scribble")
hudPrint(champ:getName() .. " scribes the spell \"" .. spellNames[spell] .. ".\"")
else
hudPrint(champ:getName() .. " does not know what the spell " .. spell .. " is.")
end
else
hudPrint(champ:getName() .. " already knows that spell.")
end
else
hudPrint(champ:getName() .. " isn't skilled enough to learn that spell.")
end
end
Next, open your items.lua and add the following.
Code: Select all
cloneObject {
name = "scroll_darkness",
baseObject = "scroll_darkness",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "darkness", "spellcraft", 5)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Darkness.\""
}
cloneObject {
name = "scroll_enchant_fire_arrow",
baseObject = "scroll_enchant_fire_arrow",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "enchant_fire_arrow", "fire_magic", 7)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Enchant Fire Arrow.\""
}
defineObject {
name = "scroll_enchant_frost_arrow",
class = "Item",
uiName = "Scroll of Enchant Frost Arrow",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "enchant_frost_arrow",
weight = 0.3,
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "enchant_frost_arrow", "ice_magic", 7)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Enchant Frost Arrow.\""
}
defineObject {
name = "scroll_enchant_lightning_arrow",
class = "Item",
uiName = "Scroll of Enchant Lightning Arrow",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "enchant_shock_arrow",
weight = 0.3,
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "enchant_shock_arrow", "air_magic", 9)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Enchant Lightning Arrow.\""
}
defineObject {
name = "scroll_enchant_poison_arrow",
class = "Item",
uiName = "Scroll of Enchant Poison Arrow",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "enchant_poison_arrow",
weight = 0.3,
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "enchant_poison_arrow", "earth_magic", 11)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Enchant Poison Arrow.\""
}
cloneObject {
name = "scroll_fire_shield",
baseObject = "scroll_fire_shield",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "fire_shield", "fire_magic", 16)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Fire Shield.\""
}
cloneObject {
name = "scroll_fireball",
baseObject = "scroll_fireball",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "fireball", "fire_magic", 13)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Fireball.\""
}
cloneObject {
name = "scroll_fireburst",
baseObject = "scroll_fireburst",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "fireburst", "fire_magic", 2)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Fireburst.\""
}
cloneObject {
name = "scroll_frost_shield",
baseObject = "scroll_frost_shield",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "frost_shield", "ice_magic", 19)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Frost Shield.\""
}
cloneObject {
name = "scroll_frostbolt",
baseObject = "scroll_frostbolt",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "frostbolt", "ice_magic", 13)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Frostbolt.\""
}
cloneObject {
name = "scroll_ice_shards",
baseObject = "scroll_ice_shards",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "ice_shards", "ice_magic", 3)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Ice Shards.\""
}
cloneObject {
name = "scroll_invisibility",
baseObject = "scroll_invisibility",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "invisibility", "air_magic", 19)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Invisibility.\""
}
cloneObject {
name = "scroll_light",
baseObject = "scroll_light",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "light", "spellcraft", 5)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Light.\""
}
cloneObject {
name = "scroll_lightning_bolt",
baseObject = "scroll_lightning_bolt",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "lightning_bolt", "air_magic", 14)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Lightning Bolt.\""
}
cloneObject {
name = "scroll_poison_bolt",
baseObject = "scroll_poison_bolt",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "poison_bolt", "earth_magic", 7)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Poison Bolt.\""
}
cloneObject {
name = "scroll_poison_cloud",
baseObject = "scroll_poison_cloud",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "poison_cloud", "earth_magic", 3)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Poison Cloud.\""
}
cloneObject {
name = "scroll_poison_shield",
baseObject = "scroll_poison_shield",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "poison_shield", "earth_magic", 13)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Poison Shield.\""
}
cloneObject {
name = "scroll_shock",
baseObject = "scroll_shock",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "shock", "air_magic", 4)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Shock.\""
}
cloneObject {
name = "scroll_shock_shield",
baseObject = "scroll_shock_shield",
onUseItem = function(self, champion)
return spellbook_script.learnSpell(champion, "shock_shield", "air_magic", 22)
end,
description = "A properly trained mage may scribe spells for personal use by copying the inscriptions written upon magic scrolls. This particular scroll contains a spell called \"Shock Shield.\""
}
Code: Select all
defineSound {
name = "scribble",
filename = "mod_assets/sounds/scribble.wav",
loop = false,
volume = 1,
minDistance = 1,
maxDistance = 4
}
- Scrolls don't disappear on use. Reasons being so the player can continue to use them as reference as well as distribute them amongst multiple mages.
- Requirement for learning a scroll is the same as for casting the spell. I think that makes sense in a lot of ways
- Nobody knows any spells initially. Done to make the early scrolls useful. One might imagine mages know some cheap parlour tricks that aren't relevant to the dungeon.
- Fluffwise, the spells are scribed into an abstract spellbook held by the individual mage. Reasons being D&D is cool.
If you want scrolls to be consumed, just add a "return true" statement to the learnSpellFunction when a spell is learned.
If you want some spells to be known initially by everyone, simply put =1 in place of =0 at the spellbook array in the script_entity after the relevant spells.
Last edited by Ixnatifual on Wed Dec 26, 2012 10:19 am, edited 2 times in total.
Re: Forcing the players to learn spells before using them.
Really nice work expanding on my initial idea... I couldn't have spent anymore time on it on Christmas Eve because, as it was, I went to bed at 3am!
I would suggest creating an array for the "nice" spell names, so you don't have to use multiple if statements and it's easier to add custom spells.
e.g.
note - I've not had chance to test this.
I would suggest creating an array for the "nice" spell names, so you don't have to use multiple if statements and it's easier to add custom spells.
e.g.
Code: Select all
local spellName = {darkness = "Darkness",enchant_fire_arrow = "Enchant Fire Arrow",enchant_frost_arrow="Enchant Frost Arrow",enchant_shock_arrow="Enchant Lightning Arrow", enchant_poison_arrow="Enchant Poison Arrow",fire_shield="Fire Shield",fireball="Fireball",fireburst="Fireburst",frost_shield="Frost Shield",frostbolt="Frostbolt",ice_shards="Ice Shards", invisibility="Invisibility",light="Light",lightning_bolt="Lightning Bolt",poison_bolt="Poison Bolt",poison_cloud="Poison Cloud",poison_shield="Poison Shield",shock="Shock", shock_shield="Shock Shield"}
if spellName[spell] ~= nil then
hudPrint(champ:getName() .. " scribes the spell " .. spellName .. ".")
else
hudPrint(champ:getName() .. " does not know what the spell " .. spell .. " is.")
end
Puzzle Frameworks - http://www.grimrock.net/forum/viewtopic.php?f=14&t=4564
Magic Pack - https://www.nexusmods.com/grimrock/mods/70
Area of Effect Spell System - http://www.grimrock.net/forum/viewtopic ... 150#p44382
Magic Pack - https://www.nexusmods.com/grimrock/mods/70
Area of Effect Spell System - http://www.grimrock.net/forum/viewtopic ... 150#p44382
Re: Forcing the players to learn spells before using them.
I didn't go that route since I figured it'd be slower to initialise the whole array every time, but I could be wrong. Or maybe it's so fast that it doesn't matter one bit.
Re: Forcing the players to learn spells before using them.
Why should it be local and initialized every time? just put the whole spellName array out of checkSpellBook...
BTW, thanks both for fleshing out my suggestion in such a complete script!
BTW, thanks both for fleshing out my suggestion in such a complete script!
Re: Forcing the players to learn spells before using them.
Exactly what I just did. I also tested it on all scrolls it looks like it's working perfectly. Post updated.Diarmuid wrote:Why should it be local and initialized every time? just put the whole spellName array out of checkSpellBook...
Re: Forcing the players to learn spells before using them.
Great stuff. And I agree it really didn't need to be local.Ixnatifual wrote:Exactly what I just did. I also tested it on all scrolls it looks like it's working perfectly. Post updated.Diarmuid wrote:Why should it be local and initialized every time? just put the whole spellName array out of checkSpellBook...
Puzzle Frameworks - http://www.grimrock.net/forum/viewtopic.php?f=14&t=4564
Magic Pack - https://www.nexusmods.com/grimrock/mods/70
Area of Effect Spell System - http://www.grimrock.net/forum/viewtopic ... 150#p44382
Magic Pack - https://www.nexusmods.com/grimrock/mods/70
Area of Effect Spell System - http://www.grimrock.net/forum/viewtopic ... 150#p44382
Re: Forcing the players to learn spells before using them.
This is a damn fine idea Thank you!!
Labyrinth of Lies (viewtopic.php?f=14&t=4400)
Legacy of Lies (viewtopic.php?f=22&t=12983&hilit=+legacy)
Legacy of Lies (viewtopic.php?f=22&t=12983&hilit=+legacy)
Re: Forcing the players to learn spells before using them.
thanks for this script!
very useful!!!
very useful!!!