Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(content): add Lua bindings for spell types #5851

Merged
merged 19 commits into from
Dec 30, 2024

Conversation

karxi
Copy link
Contributor

@karxi karxi commented Dec 29, 2024

Checklist

Required

Purpose of change

Further work on expanding what Lua scripts are capable of in Cataclysm~

Describe the solution

This is a set of Lua bindings that allow spells to be cast through Lua. While there's room for expansion, it means that the varied and powerful effects spells offer are now possible to invoke through Lua! (They still need a spell defined through JSON; this isn't quite that magical.)

Describe alternatives you've considered

Binding every single type that spells touch and modify so people don't need to work through spells.
To be clear, that's still my ideal end goal for Lua; spells are (in my humble opinion) clunky and annoying to work with. But they allow a range of effects that simply aren't possible with the current tools (such as spawning items), so this seemed like the natural next step.

Testing

Here are some basic tests:

avvy = gapi.get_avatar(); pos = avvy:get_pos_ms()
spid = SpellTypeId.new("lava_bomb_main")            -- A disruptive, painful, and possibly lethal spell
SpellSimple.prompt_cast(spid, pos)                  -- Blow ourselves up

image

The longer form invocation makes it clearer what's going on here, and allows more control:

spid = SpellTypeId.new("invisibility")              -- Get a spell's ID
spobj = SpellSimple.new(spid, true)                 -- Set up 'Invisibility' to be cast on self
spobj:cast(avvy, pos, spobj:max_level())            -- Cast Invisibility from us, on us, at max level

A list of all spells can be retrieved via SpellTypeRaw, e.g.:

for k,v in pairs(SpellTypeRaw.get_all()) do print(k, ': ', v) end

...so go nuts~

image
image

Additional context

Two things of import:

  1. The first example uses an AoE spell that can hit the player. This is intentional—it's easiest to use the player as a test dummy, but a lot of spells refuse to let the player select themself as a target. If you have an NPC (or monster) to bully, your options expand significantly—just plug another Creature's get_pos_ms() into :cast. (Or plug another Creature in as the first argument, and the player's position—both should work.)
  2. The C++ code behind spells is strange and arcane and I do not particularly care for it. It's not the worst thing in Cataclysm, not by a wide margin, but I wish things were neater.

@github-actions github-actions bot added the src changes related to source code. label Dec 29, 2024
Copy link
Contributor

autofix-ci bot commented Dec 29, 2024

Autofix has formatted code style violation in this PR.

I edit commits locally (e.g: git, github desktop) and want to keep autofix
  1. Run git pull. this will merge the automated commit into your local copy of the PR branch.
  2. Continue working.
I do not want the automated commit
  1. Format your code locally, then commit it.
  2. Run git push --force to force push your branch. This will overwrite the automated commit on remote with your local one.
  3. Continue working.

If you don't do this, your following commits will be based on the old commit, and cause MERGE CONFLICT.

@RobbieNeko
Copy link
Collaborator

The C++ code behind spells is strange and arcane and I do not particularly care for it. It's not the worst thing in Cataclysm, not by a wide margin, but I wish things were neater.

Welcome to our (magic mods) world :)

Copy link
Collaborator

@RobbieNeko RobbieNeko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing on Linux:

  • It builds and loads!
  • The provided invisibility and lava bomb examples work
    image
    image
  • Summoning items works, and the water prompt actually popped up while still in the console lol
    image
    image
  • What I thought would be a curveball, pain split, also worked!
    image
  • What didn't work, however, was cure light wounds ("light_healing")

It clearly recognized the spell ID, but did not actually heal me for anything (test was done before pain split, but it didn't work after that either)
image

For reference, how I inputted the custom spell tests (literally just exchanging invisibility's ID for other spell ids in Magical Nights since I had an MN test world already)
image

@karxi
Copy link
Contributor Author

karxi commented Dec 29, 2024

Really? This worked fine for me:
image
image
This character was uninjured, then shot with a heavy rail rifle, then healed significantly (from yellow health to light green).
(Also, today I learned that heavy rail rifles can set things on fire.)

@RobbieNeko
Copy link
Collaborator

Additional findings:
Mind over pain ("recover_pain") doesn't appear to work either.
Phase door does work despite not even having a valid target in the first place in JSON

@RobbieNeko
Copy link
Collaborator

Really? This worked fine for me: image image This character was uninjured, then shot with a heavy rail rifle, then healed significantly (from yellow health to light green). (Also, today I learned that heavy rail rifles can set things on fire.)

huh, interesting. When using that method it does work, but when using the one used for invisibility it doesn't

@RobbieNeko
Copy link
Collaborator

And same with the recover_pain!
Evidently some spells only work with specific syntax?

@karxi
Copy link
Contributor Author

karxi commented Dec 29, 2024

For the record: If a spell has "valid_targets": [ "self" ], and you aren't in the square designated by pos by the time you cast it, it may break. If you want to be safe in the prior examples, use avvy:get_pos_ms() or gapi.get_avatar():get_pos_ms() (the latter is overkill, but sometimes it pays to be extra-cautious).

Under the given circumstances, it arguably should break (a spell that with valid_targets requirements that aren't being met should not cast!), but the code behind spells is a mess, and sometimes they'll go off despite that.

Copy link
Collaborator

@RobbieNeko RobbieNeko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out I am a silly goober and moved after I set pos. So long as you actually, you know, have the position variable stay correct by not moving after setting pos everything works perfectly fine!

... it's just that somehow, most of the spells actually work in spite of moving off of that tile?!? Magic code is hecking weird, man.

Copy link
Member

@chaosvolt chaosvolt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Compiled and load-tested.
  2. Started up a world with Magiclysm added.
  3. Entered first command shown in testing section.
  4. Died from going "I don't care how big the room is, I CAST FIREBALL"

@chaosvolt chaosvolt merged commit a4dde2f into cataclysmbnteam:main Dec 30, 2024
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
src changes related to source code.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants