spell
The spells of Magery: what a spell is, the spellbook, and casting.
Source: src/Moongate.Server.Ultima/Modules/SpellModule.cs
Functions
Section titled “Functions”spell.add(book, spell_ref) -> booleanWrites the spell, by number or key, in the spellbook, as a scroll dropped on it does, and shows the book again. False, with nothing changed, for an item that is no spellbook, an unknown spell or one the book holds already.
Writes a spell in a book, as a scroll dropped on it does; false when the book holds it already:
spell.add(book, "recall")spell.add(book, 32)| Parameter | Type | Default |
|---|---|---|
book | integer | |
spell_ref | any |
Returns boolean.
can_cast_at
Section titled “can_cast_at”spell.can_cast_at(caster, spell_ref) -> booleanWhether a cast of the spell, by number or key, would begin for the NPC now: the spell is known, enabled and has its script, and the NPC is alive, not casting, not frozen and has the mana of the spell. Nothing is said, spent or started, so a script may ask for each spell it can choose from. False for a player. The circle an NPC may use is the script's rule (npc.spell_circles), not asked here.
Whether spell.cast_at would begin now, with nothing said or spent; a script asks for each spell it may choose from and takes the first that answers true:
for _, key in ipairs({ "flame_strike", "fireball", "magic_arrow" }) do if spell.can_cast_at(serial, key) then spell.cast_at(serial, key, target)
break endend| Parameter | Type | Default |
|---|---|---|
caster | integer | |
spell_ref | any |
Returns boolean.
can_use_from_afar
Section titled “can_use_from_afar”spell.can_use_from_afar(player, item) -> booleanWhether the player could use the item from afar, as the Telekinesis spell does: it has an on_use in its script, or is a container the player carries or that lies on the ground, and a double click would not be refused (a bank that is not open, an inventory kept shut). False for a player or an item that is none, an NPC, or an item another mobile carries.
Whether Telekinesis may use an item, before anything is spent:
function telekinesis.check(caster, target, info) if not spell.can_use_from_afar(caster, target.serial) then return 501857 -- This spell won't work on that! endend| Parameter | Type | Default |
|---|---|---|
player | integer | |
item | integer |
Returns boolean.
cancel
Section titled “cancel”spell.cancel(caster) -> booleanEnds the cast of the mobile, if it has one, with no message, and takes its target cursor away. The recovery that the end of the delay already set stays, so a cancel at the cursor still leaves the short wait before the next cast.
Ends the cast with no message, such as when a player is teleported away. The short wait that the end of the delay set stays, so a cancel at the target cursor still leaves it:
spell.cancel(user)| Parameter | Type | Default |
|---|---|---|
caster | integer |
Returns boolean.
spell.cast(caster, spell_ref) -> booleanBegins the cast of a spell, by number or key, as the player's own request does: it must have the spell in a spellbook it wears or carries in its backpack, and the usual checks tell it why not (dead, casting, frozen, not recovered, no mana). True when the cast began; then the words, the delay, the target cursor, the reagents, the mana and the skill check follow.
Begins the cast of a spell the mobile has in a book it carries, by key or by number; the usual checks tell it why not:
if spell.cast(user, "magic_arrow") then -- the words, the delay and the target cursor followend| Parameter | Type | Default |
|---|---|---|
caster | integer | |
spell_ref | any |
Returns boolean.
cast_at
Section titled “cast_at”spell.cast_at(caster, spell_ref, target?) -> booleanBegins the cast of a spell, by number or key, for an NPC at the mobile with the serial target, as a creature of the classic game casts: no book, no scroll, no reagents and no words, the mana of the spell paid when it takes effect, a fizzle by its Magery, the delay of the circle with its gestures during which the NPC does not move, and no disturbance by damage. At the end of the delay the target is looked up again: out of the world, dead, hidden from a harmful spell, farther than 12 tiles or out of sight, the cast ends and spends nothing. target is left out for a spell that needs none. False for a player, a spell that is unknown, disabled or has no script, one that asks for an item, a target that is none, and any refusal of the cast (casting already, frozen, not enough mana).
What a creature’s script does to cast at who it fights: no book, no reagents and no words, the mana and the delay of the circle as for a player. The target is looked up again when the delay ends, so one that left, died, hid or got out of range or sight costs nothing:
if spell.can_cast_at(serial, "energy_bolt") then spell.cast_at(serial, "energy_bolt", target)endA spell that needs no target leaves it out: spell.cast_at(serial, "create_food").
| Parameter | Type | Default |
|---|---|---|
caster | integer | |
spell_ref | any | |
target (optional) | integer | 0 |
Returns boolean.
cast_scroll
Section titled “cast_scroll”spell.cast_scroll(caster, scroll) -> booleanBegins the cast of the spell of a scroll the mobile carries in its backpack, as a double click does: no reagents, a skill window two circles easier, and one scroll used up when it succeeds. True when the cast began; false for a mobile or an item that is none, or a scroll that is no spell.
What a double click on a scroll does, from the script of the scroll:
function spell_scroll.on_use(serial, user) spell.cast_scroll(user, serial)
return trueend| Parameter | Type | Default |
|---|---|---|
caster | integer | |
scroll | integer |
Returns boolean.
disturb
Section titled “disturb”spell.disturb(caster) -> booleanDisturbs the cast of the mobile as damage does: a player's spell above the first circle, while its delay runs, is ruined (the player is told so and waits to cast again); nothing for a first circle spell, an NPC, a cast waiting for its target or a mobile that is not casting. A curse uses it on its target.
A curse may ruin the spell its target is casting, as damage does:
spell.disturb(target)| Parameter | Type | Default |
|---|---|---|
caster | integer |
Returns boolean.
find_book
Section titled “find_book”spell.find_book(mobile, spell_ref) -> integer?The serial of a spellbook the mobile wears or carries in its backpack (not in a bag inside it) that holds the spell, by number or key, the one a cast would use; nil when it has none, for an unknown spell or a mobile that is not in the world.
The spellbook a mobile wears or carries that holds a spell, as a cast would find it; nil when it has none:
local book = spell.find_book(user, "recall")
if not book then mobile.message_cliloc(user, 1042404) -- You don't have that spell!end| Parameter | Type | Default |
|---|---|---|
mobile | integer | |
spell_ref | any |
Returns integer?.
spell.has(book, spell_ref) -> booleanWhether the spellbook holds the spell, by number or key. False for an item that is no spellbook.
if not spell.has(book, "heal") then mobile.message(user, "Your book does not hold Heal.")end| Parameter | Type | Default |
|---|---|---|
book | integer | |
spell_ref | any |
Returns boolean.
spell.info(spell_ref) -> table?What data/spells.toml says of a spell, by number or key, as a table: id, key, name, circle, mantra, mana, target ('none', 'mobile', 'item' or 'location'), harmful, resistable, reflectable, scroll (the template), enabled. Nil for an unknown spell.
What the data says of a spell:
local arrow = spell.info("magic_arrow")
mobile.message(user, arrow.name .. " costs " .. arrow.mana .. " mana")| Parameter | Type | Default |
|---|---|---|
spell_ref | any |
Returns table?.
is_casting
Section titled “is_casting”spell.is_casting(caster) -> booleanWhether the mobile is casting a spell, its delay running or its target cursor waiting.
if spell.is_casting(user) then return falseend| Parameter | Type | Default |
|---|---|---|
caster | integer |
Returns boolean.
of_scroll
Section titled “of_scroll”spell.of_scroll(scroll) -> integer?The number of the spell a scroll item holds; nil for an item that is no scroll of a spell.
local id = spell.of_scroll(serial)
if id then mobile.message(user, "A scroll of " .. spell.info(id).name)end| Parameter | Type | Default |
|---|---|---|
scroll | integer |
Returns integer?.
open_book
Section titled “open_book”spell.open_book(player, book) -> booleanOpens a spellbook for a player, showing the spells it holds, as a double click does. The player must wear it or carry it in its backpack (and not in a bag inside it): else it is told so. False for a player, an item or a spellbook that is none, or a book not carried.
What a double click on a spellbook does:
function spellbook.on_use(serial, user) spell.open_book(user, serial)
return trueend| Parameter | Type | Default |
|---|---|---|
player | integer | |
book | integer |
Returns boolean.
spells
Section titled “spells”spell.spells(book) -> table?The numbers of the spells the spellbook holds, in order, as a list; nil for an item that is no spellbook.
The numbers of the spells a book holds:
for _, id in ipairs(spell.spells(book)) do log.info(spell.info(id).name)end| Parameter | Type | Default |
|---|---|---|
book | integer |
Returns table?.
use_from_afar
Section titled “use_from_afar”spell.use_from_afar(player, item) -> booleanUses the item for the player as a double click would, but from any distance and with no reach check: the on_use of its script runs, or a container is shown open. True when something was done; false for a player or an item that is none, an NPC (it has no client to show a container to), or an item that cannot be used from afar.
Uses an item as a double click would, from any distance: its script’s on_use runs, or a container is shown open:
spell.use_from_afar(caster, target.serial)| Parameter | Type | Default |
|---|---|---|
player | integer | |
item | integer |
Returns boolean.
Made with ❤️ by Tom
