Adding scripts generated like a levelled list merger.

Questions specific to OpenMW-CS can be asked, and content development related topics can be discussed here
Post Reply
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Adding scripts generated like a levelled list merger.

Post by i30817 »

I've been hacking omwllf to 'merge' another kind records in order to make a mod that alters all spell scrolls (and vendor spell sellers, the idea is to make scrolls learnable and disable spell vendors regardless of which mods adding scrolls are installed and without requiring MWSE).

My current problem. I started modifying the scrolls with little problem (added to the text a list of required spell schools skills to learn it) and to progress i now need to create script records.

However, https://en.uesp.net/morrow/tech/mw_esm.txt says for the 'SCPT' (script) record that the script text is *compiled*. I'm pretty sure that compiling code is beyond my wheelhouse.

Should i just use the openmw support for python or lua?

Some questions if 'yes'.
Are those interpreters built in openmw or do they require system tools installed (in linux python always is, but assuming a windows user). If it requires a system interpreter does openmw at least tell what went wrong?

If i use python for instance, can i install my script 'out' of the omwaddon file, that is not as a record, but as a free-standing 'py' file installed like textures for example? (this feature might make me use it even if the 'compilation' is not a problem).


My current code if you're curious and if i die tomorrow:
Spoiler: Show
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Re: Adding scripts generated like a levelled list merger.

Post by i30817 »

Apparently, nope, can't start a py script from a object without using a wrapper and duplicate the number of scripts.

Since my whole problem was creating compiled mwscript records for the metaprogramming, this doesn't help me.

What's a 'compiled' mwscript anyway? From looking at it with vbindiff very little seems different from text, any tool to get a byte or string representation given a 'uncompiled' form?
User avatar
AnyOldName3
Posts: 2667
Joined: 26 Nov 2015, 03:25

Re: Adding scripts generated like a levelled list merger.

Post by AnyOldName3 »

If you're making a script in the original CS, you have your script source code, and then it also automatically compiles it to script bytecode when you save the ESP. The original Morrowind engine doesn't execute the script source code, but instead executes the bytecode. OpenMW is a little different, though. As the original CS' compiler was buggy, fairly often the bytecode it produces doesn't match the source code and doesn't do exactly what the mod author intended. Because of this, OpenMW ignores the bytecode and just executes the script source directly.

This means that to do what you're trying to do, if you only want your generated ESP to work with OpenMW and not the original engine, you only need to include the script source and not the compiled bytecode.

If you want the mod to work with the original engine too, the simplest solution is to open the generated ESP in the original CS and save it again. If you want to automate it, though, you might find that either the CS, the compiler it uses, or one of the third-party Morrowind editors can be used from the command line to do it automatically.
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Re: Adding scripts generated like a levelled list merger.

Post by i30817 »

The original approach is not doomed. From some vbindiff looking around, apparently openmw-cs doesn't bundle the 'compiled script' so the edited esp loads there and in game. I'm just making sure now the offsets match (some strings are null terminated, some aren't... - they don't actually need it because the esp subrecord stores the size just before, but it's good to match what openmw-cs outputs)

edit: didn't see your post AnyOldName3, thanks for the explanation.
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Re: Adding scripts generated like a levelled list merger.

Post by i30817 »

I have other questions:

If i have a stack of items (in this case scrolls) all of the same type and with the same 'script' field, this means that only 1 copy of that script is running in the inventory right, not Number_Of_Items scripts? That would be terrible and counterintuitive.

Similarly, does anyone know of a nice way to delete the object (a scroll in the inventory) from its script, 'consuming' it as a alternative to 'stopscript' not working on local scripts?

I'm a bit worried about adding lots of little scripts. Objects in unopened containers but in the cell won't run their scripts right? Only (scrolls in this case) placed on the world?



Finally i'd really prefer this to be a (single) global script, but without any way to get a reference to the 'current dropped object' and build strings based on that name to add the right spells there is no point. References can make things more efficient, just a reminder if you implement them to also add some properties that can be listened to.
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Re: Adding scripts generated like a levelled list merger.

Post by i30817 »

I'm also curious about 'GetButtonPressed'. The only way that works without problems is if that function (or rather messagebox) stores its value to a 'hidden' local variable right? Because if it was global, the scripts would get all over eachother when they used messagebox. How does that work when you use a messagebox on a global script?

edit: ok i figured this one out. No, they're global variables - i just wasn't noticing because my check probably didn't use the same kind o 'messagebox' (deleting a spell) as the script function or had already 'consumed' the 'getbuttonpressed' value. Once i got a message box that didn't care about the value (the chargen 'ok' prompts work well) the script fired immediately on entering the inventory because there wasn't a 'local variable' check against it. Which is concerning because i wanted to skip resetting the local variable in some cases.
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Re: Adding scripts generated like a levelled list merger.

Post by i30817 »

Isn't it kind of...

fucking terrible

that messagebox getbuttonpressed needs to be 'collaborative' then to prevent another mod from 'consuming' the getbuttonpressed value just by calling it before the right script consumes it?
I'm thinking that not every mod will bother to guard getbuttonpressed calls behind a local guard variable AND remember to reset it on all 'button pressed' exit paths.

The guard is not only to prevent others stealing getbuttonpressed input, it's even worse if your script fires if another script messagebox is clicked. Both these problems could be avoided with a 'script local' getbuttonpressed.

Even if you do everything right, you might be waiting for input (getbuttonpressed==-1) and a jackass mod script come along and call 'getbuttonpressed' without a local guard to link it to a messagebox they opened and consume what you're waiting for before you choose or overwrite your own showing messagebox with theirs and get a essentially random result (if you didn't reset the guard in all relevant button exit paths, its 'any messagebox after' that can activate the critical path).

I wonder how many scripts can be broken with just this global script.

Code: Select all

begin jerk
getbuttonpressed
end jerk
or with this:

Code: Select all

begin jerk
(imagine a timer with 'every 5 minutes' here)
messagebox 'just a innocent messagebox with a button'
end jerk
Shouldn't the variable this function returns and messagebox sets be local (even if hidden) to the script/console that called messagebox if not requested especially on a global context (maybe a 'getbuttonpressedglobal' function for compatibility with terrible mods that want to interfere with other scripts?)



Another way is to make the MessageBox with at least one button block the running script that invoked it but there are probably technical reasons involving singlethreaded execution why that would be a bad thing in morrowind. It would simplify scripts a lot though (if complicating the implementation. Threadpools, eventqueues or continuations is my guess)
i30817
Posts: 58
Joined: 07 Nov 2018, 05:56

Re: Adding scripts generated like a levelled list merger.

Post by i30817 »

Current code works for the scroll spells but i had to add a hack limiting the magicka cost to around 200 (largest TR spell cost) because there are a few scrolls with gonzo cost values because scrolls don't use player magicka. Supreme domination, scroll of icarian flight, windform etc. The autocalculate flag doesn't appear to do anything for spells not created from a spellmaker? TBH i don't know how that works, if it's broken for non-spellmaking menu spells or if Supreme Domination is just that costly.

I gave up on using messagebox and the scripts got much simpler and more reliable and the mod more usable, lol.

Currently working on creating a 'no spells sellers' addon in the same program, it's a bit annoying because NPC records are a definite step up in complexity.

Spoiler: Show
The person making omwllf could make this definitely easier by providing some kind of generic record writer to go along with their generic record reader, so people like me didn't have to parse out and write out each type of record and could zoom in to just the changes we want.

I also found the TEXT record in books doesn't terminate with \0, unlike every other non-flag record, which i find strange, even if strictly speaking no record should need \0 because they write their size - but it's usually writen 'length(string+1)' to include the \0, i suppose for C string compatibility - except on BOOK text records, verified with a vbindiff on linux.


I'd also still like a answer to three of the still not outdated questions above:

1. If i have a stack of items (in this case scrolls) all of the same type and with the same 'script' field, this means that only 1 copy of that script is running in the inventory right, not Number_Of_Items scripts? That would be terrible and counterintuitive.
2. does anyone know of a nice way to delete the object (in the inventory) from its script, 'consuming' it as a alternative to 'stopscript' not working on local scripts?
3. Objects in unopened containers but in the cell won't run their scripts right? Only (scrolls in this case) placed on the world or player inventory?
User avatar
Capostrophic
Posts: 794
Joined: 22 Feb 2016, 20:32

Re: Adding scripts generated like a levelled list merger.

Post by Capostrophic »

1. Scripted items aren't supposed to be stacked, but even if stack comparison is fixed there's another issue that can cause unstackable items to be stacked. And yes, stacking scripted items breaks scripts since there is a single reference with non-1 count and one script.
2. Use a variable in the script itself that marks the conditions of the script not being able to run (like doonce)
3. I think.
Post Reply