Page 1 of 1

Usecode Tutorial for Fishnet Stockings

Posted: Mon Jun 20, 2016 4:37 am
by Knight Captain
One of the items not included in the SIfixes is setting Flag 123, which allows you to ask the usual folks (Harnna, Jendon, and Bucia) about the fishnet stockings you found on or near Shmed after he attacks you. The released version of the game does not have these stockings, so the flag is never set. If you use the F2 cheat menu to set the flag you'll see the conversation option.

Previously I was trying to get Shmed’s death or the item on his corpse to somehow trigger this flag, but the original game didn't set other flags that way unless part of some other script. Most flags are set by conversation, such as giving info or an item, or by triggering an egg. Picking up items such as Erstam's Jawbone, the Flux Analyzer, and the Philanderer's Friend trigger eggs underneath them that set these flags accordingly. The Furnace lab explosions when you move certain reagents would be another eggample. These eggs are set to Criteria: "Something on" so when an item is moved off of them, they trigger an action.

Since there has been some interest in a tutorial, here’s a rough attempt.

Before you begin, it’s a good idea to have the latest Exult, SIfixes, Exult Studio, and Notepad++ installed.

1) Download the latest GIT source code snapshot from the Exult download page:
http://exult.info/download.php

2) Extract the files and find the content\sifixes folder. In the data folder has the output files, and the src folder has the input or source files.

3) Open the folder content\sifixes\src\header\si and open the file si_gflags.uc with Notepad++. You may need to right-click on it to get the option.

In Notepad++, to the Language Menu, then C, and choose C. This will color some of the words and functions, making the code a little more readable.

4) Scroll down to about line 162 or search for SLAIN_WOLF, and add this line after it:

Code: Select all

FOUND_FISHNETS = 0x7B, //123
This names the flag so we can use the friendly name elsewhere. The // indicates a comment which is the decimal number of the flag.

Save the file.

5) Use Notepad++ to create a new empty file, and copy/paste this content into it:

Code: Select all

void FoundStockings object#(0xBFF) ()

{
	if (event == EGG)
		gflags[FOUND_FISHNETS] = true; //Added to si_gflags.uc as 0x7B
}
Save this file as fishnets.uc in the Misc folder, content\sifixes\src\misc.

6) Open the file usecode.uc from content\sifixes\src in Notepad++.
Scroll down around line 58 and add these two lines:

Code: Select all

// Enables flag for fishnet questions
#include "misc/fishnets.uc"
This should line up with the other #include “misc/script.uc” lines listed above it.

Save the file. You can now close Notepad++ if you wish, it will reopen the three files when you reopen it.

7) Right-click on the make.bat file in content\sifixes\src, and choose Edit with Notepad++.
Go to the last blank line and add the word pause to the line, then save the file. This will let you see confirmation that your code compiled correctly or had an error, and if so where.

8) Right-click on that same make.bat file and choose Run as Administrator. This will recreate the output files that will be placed in content\sifixes\data. Go into that folder and find the Usecode file. It does not have a file extension.

9) Go to your SIfixes folder, something like C:\Program Files\Exult\Serpent_Isle\mods\sifixes\data and rename the existing Usecode file to orig_usecode. This way you can easily undo the swap if you need.

10) Copy that new Usecode file from content\sifixes\data to C:\Program Files\Exult\Serpent_Isle\mods\sifixes\data or your equivalent.

11) Copy your existing Exult shortcut, or make a new one. Then edit this shortcut by right-clicking on it and going to Properties. On the Target line, add a space and two dashes and the word edit to the end of the line. It should look something like: "C:\Program Files\Exult\Exult.exe" –edit

Click the Apply button, then optionally go to the General tab and rename the shortcut to Exult Edit Mode or similar. Click the OK button.

12) Start Exult Edit Mode and choose Show Mods under Serpent Isle, then choose Serpent Isle Fixes. Start a new game. The game engine will start in Edit Mode with Exult Studio open.

13) In Exult Press F2 to enter the cheat window. Note your starting coordinates, 0478, 2483.

Press N for NPC editing, then type 75 and press Enter. Shmed is already sitting in his office, the shack outside of the Knight’s Test. Press T to teleport to that spot, then press Escape twice.

14) In Exult Studio, go the Edit menu, then Create egg... Set the following options:
Criteria: Something on
Flags: Auto-reset (on by default)
Probability: 100 (we want this to happen consistently)
Distance: 1 (should be fine, it is the default)
Select the Usecode tab, then click on the Browse button under that. If it is not already selected, your file path should be something like C:\Program Files\Exult\Serpent_Isle\mods\sifixes\data\usecode with a list of Objects and Shapes.
Select the line FoundStockings, 00bffH, Object. Click OK.
The Function Number or Name should now show FoundStockings.
The Quality field should be set to 1 as the default. If not, set it.

Click the Apply button, then click on the main Exult map to place the egg. You can safely move it. In this case, I put it on the empty table in the southeast corner of Shmed’s office. It should be just a hair to the right of the bottom center, so the bottom of the green U shape is under the wall.

15) Back in Exult Studio, on the left side under Shape Files, click on shapes.vga.
In the lower right corner, click on the Frames button. This will expand out all the possible shapes there.
In the Find field, type in the word stockings and click on the Down button.
The blue moonsilk stockings will be selected, but the next item is the gray fishnet stockings.
Drag and drop that item onto the main Exult window. Like the egg you can reposition it. It should be on top of the green U shaped egg on the table, similar to the Jawbone or Flux Analyzer.

16) Optionally, you can double-click on Shmed and drag items from Exult Studio’s shapes section to his paperdoll. In the leaked beta version he has chain leggings, which makes him a more challenging opponent. Close his paperdoll window when you are done.

17) In the main Exult window, press F2, then T to teleport, and D to enter decimal coordinates. Enter the X and Y one at a time, 0478 and then 2483. The leading zero is optional. Press Escape twice to go back to the starting location.

18) In Exult Studio, go to the File menu, then choose Save all. This will update the map, as well as Shmed’s equipment. If you only save the map, I am not sure if Shmed’s updated gear will be saved. (Marzo, Dominus?) Close the main Exult window as well.

19) Restart Exult using the normal shortcut and start a new game. As before you can teleport to Shmed’s office by using F2, N, 75, T, Escape twice. You can check your current flag 123 status by going into F2, F, 123. It should be unset until you pick up the fishnet stockings, which should immediately set the flag when you pick them up or move them. If so, congratulations!

If anyone would like to try these instructions and give me feedback I’d appreciate it. I wish this Phorum had a preview button.

Re: Usecode Tutorial for Fishnet Stockings

Posted: Mon Jun 20, 2016 10:16 pm
by Dale
Awesome! Really excited to dig into this. Hopefully when I have a bit more time, I will re-read my thread to refresh and then go through this to help dig deeper.

You're getting making me very enthusiastic about the future of Exult and the modding community. Thanks, KC!

Re: Usecode Tutorial for Fishnet Stockings

Posted: Tue Jun 21, 2016 2:14 am
by Knight Captain
You're welcome Dale!

It looks like having the leading zero in step 13 is important, but I haven't been able to recreate a possible bug that hangs ES.

Re: Usecode Tutorial for Fishnet Stockings

Posted: Tue Jun 21, 2016 5:05 am
by Knight Captain
On step 14, I'm not sure the Quality number on the egg in ES is required unless there are multiple eggs nearby for the same code, say as done in Vasculio's treasure room.

On step 17 the leading zero may not be optional, ES hung saving when I didn't consistently use it.

And I probably should have named the file egg_fishnets.uc, if only to be pedantic.

-----------------------------------------------------------

Here's Tutorial 2, which reuses some of the steps above. This one will set the flag for Pomdirgun’s death when you pickup the Helm of Monitor, and includes some educational bits as well.

As before, this uses the existing SIfixes code, including these files as edited in the prior tutorial:
content\sifixes\src\header\si\si_npcs.uc
content\sifixes\src\header\si\si_gflags.uc
content\sifixes\src\usecode.uc

You will want to use the Notepad++ Languages menu to see each one to be colored by C programming language rules.

1) Use Notepad++ to open the si_npcs.uc file.
Go down to line 245, which should be: GOBLIN_KING = -265,
After that line, add a new one and press the Tab key on your keyboard. This will align the text with the others. Then add this text after the Tab:
POMDIRGUN = -265,
Save the file.

This will allow us to address the Goblin King as either GOBLIN_KING or POMDIRGUN. This is not strictly required, but shows that you can use both to refer to NPC 265. We will use POMDIRGUN in later parts of this tutorial.

2) Use Notepad++ to open the si_gflags.uc file.
Go down to line 142, which says: TOLD_HARNNA_FOUND_SCROLL = 0xC7
Add a comma after the 0xC7 so it matches the lines right above it.
Add a line after it and add a Tab to the new line, and add this text:
POMDIRGUN_IS_DEAD = 0xCC //204
Save the file.

This sets a friendly name to the existing Global Flag 204, which is addressed using its hexadecimal number 0xCC. The 0x indicates it is a hexadecimal, and the CC equals 204 in decimal. The double // lines indicate the remaining text is a comment, with the decimal there for easier reading.

3) Create a new blank document in Notepad++ using either the File menu or the icon in the upper left that looks like a white paper with a green circle on it.

Copy and paste this code into it:

Code: Select all

//This file will allow you to set an egg under the Helm of Monitor that will
// set the appropriate flag for Pomdirgun's prior death.

void FoundHelmofMonitor object#(0xBFE) () //object will autonumber if left blank

{
    if (event == EGG) //If our egg is triggered, set in ES
        {
        if (UI_get_item_flag(POMDIRGUN, DEAD)) //If the Goblin King is dead
            {
            delayedBark(AVATAR, "@We are the Champions!@", 0); //The Avatar barks
            gflags[POMDIRGUN_IS_DEAD] = true; //Added to si_gflags.uc as 0xCC
            }
        else if (!UI_get_item_flag(POMDIRGUN, DEAD)) //If the Goblin King is not dead
            {
            if (UI_get_item_flag(POMDIRGUN, MET)) //Check if we know his name
                delayedBark(DUPRE, "@We should slay Pomdirgun!@", 0); //Dupre barks
            else //if (!UI_get_item_flag(POMDIRGUN, MET)) //If we don't know him
                delayedBark(SHAMINO, "@We should slay their king!@", 1); //Shamino barks
            }
        }
} 

// After you save this code, add an entry for it in usecode.uc
//  and then run Make.bat as an Administrator.
Save this file in content\sifixes\src\misc as: egg_helm_of_monitor.uc

Use the Notepad++ Languages menu to select the C language coloring.

The first two lines are comments, a description of the file. Notice the leading slashes and green color?

The fourth line is to give this function a name and static (not automatically assigned) object number.
void indicates the function isn’t expected to return anything, and is very common in Usecode.
FoundHelmofMonitor will be used later in Exult Studio, but otherwise is made up by the author.
object# indicates just that, this is an object, in this case an egg, rather than using shape for all of the same shape.
(0xBFE) is the unused object hexadecimal number I assigned*. If you leave this blank () a number will be automatically assigned above 0xC00. I am not sure if it will change on recompiling, which would be a pain since it would require checking the Egg we’ll make later in Exult Studio.
() is required, but otherwise unused in this example.

(* To verify this number was unused in the existing SI usecode and other SIfixes, I had to decompile the Origin usecode. Then I had to open it in Notepad++, as well as all the other SIfixes scripts for SI and search for 0xBFE using the Find All in All Open Documents button found in the Find window. Note this is just two down from 0xC00, which all objects greater than are considered unused.)

Line six is a lonely curly bracket, which helps organize the file, much like it does in plain old C.

Line seven is our conditional statement. It says if our event, equaling an egg, is triggered.

Line eight is another opening curly bracket which will contain all the code if our prior if line is triggered.

Line nine is a conditional check to see if Pomdirgun, NPC 265 as previously set, is alive or dead. Just as we set Pomdirgun to be NPC 265, item flag DEAD was already set in content\sifixes\src\header\constants.uc. This is friendly than just putting a 4 here, as it allows us to read the line and better understand it than “if (UI_get_item_flag(-265, 4))” would be.

Line 10 starts a third layer of open curly brackets, this time containing the actions to take if the conditions on Line 9 are met.

Line 11 is a delayedBark by the Avatar, who if Pomdirgin is dead will make his proud exclaimation.
The final zero indicates no delay, although a slight delay of 3 would still make sense.

Line 12 is setting the global flag using the friendly name we set in si_gflags.uc. As before, using POMDIRGUN_IS_DEAD here is more understandable than using 0xCC.

Line 13 is our first closed curly bracket. If you click on it with the Notepad++ language selected it will color both this one and the one on line 10 to indicate they match up. Also notice the box and lines to the right of the line numbers. If you click on the box at line 10, lines 11, 12, and 13 will hide. Click the box again to reshow the lines.

Line 14 will be considered only if line 9, our prior if check is not met, and then if our if condition on this line is met. Notice it is almost the same as line 9, but has an ! to indicate a NOT. So the line here checks that the Goblin King is not dead. For example, if the Avatar used the Vibrate spell to get the key here instead of slaying him, we wouldn’t want to set the flag that indicates in he is dead.
Remember, the conversation entries that rely on this flag already exist in the original game’s compiled Usecode, so we could not easily patch them to check for Pomdirgun’s death.

Line 16 is our subcondition, in this case if we have met Pomdirgun. So the total of clauses by this line is:
The Egg was triggered, true (line 7)
Pomdirgun is dead, false, skipped (line 9)
Pomdirgun is not dead, true (line 14)
If we have met Pomdirgun, typically set by asking him his name, the next line runs.

Line 17 is another Bark, this time Dupre imploring the Avatar to slay the Pomdirgun.

Line 18 is an Else, which runs if the prior If on line 16 is not met. In other words, if we have not met Pomdirgun. Notice the commented out part that is the opposite of line 16? It isn’t required but should run the same if the first two comment slashes are removed.

Line 19 is a Bark from Shamino, suggesting we should dispose of the unnamed king.

The next three lines close the curly brackets for the prior open ones.

The last two lines are further comments, as a reminder that your custom Usecode won’t compile without being set in usecode.uc.

4) Open content\sifixes\src\usecode.uc in Notepad++.
If you are building off the previous tutorial, go to line 60 and add these two lines and save the file:
// Enables flag for conversation items about Pomdirgun's death
#include "misc/egg_helm_of_monitor.uc"

It does not strictly matter where exactly these two lines go. Since we are using a predefined function number, anywhere after line 44 would be reasonable.

5) In content\sifixes\src, right click on the Make.bat file and choose Run as Administrator. If you added the ending pause to it, you should see the success message. Otherwise it will close quickly.

6) Copy the resulting new usecode file from content\sifixes\data to the the destination, something like:
C:\Program Files\Exult\Serpent_Isle\mods\sifixes\data

7) The steps from here are nearly identical to steps 12 though 14 and 17 though 19.
In this case you’ll need to teleport using F3 to get into the Goblin treasure room, then drag and drop the Helm of Monitor off the table before creating the egg on it.
The Usecode to select will be FoundHelmofMonitor, 00bfeH, Object, and you do not need to set a specific Quality field on your Egg.
Then place the Helm of Monitor on the table. If you wish you can double-click on it and lower the Z height back to 2 so it matches its before location.
Teleport back to the starting location prior to saving in Exult Studio.

8) Now comes the fun part, the testing. You must make a new game to take full advantage of this new code, but you do not need to play though the opening parts. Just teleport your party up to the Goblin treasure room.

Press E to enable showing Eggs. Depending on your exact placement of the helm you may see all or some of the Egg.
Since you haven’t met or slain the Goblin King, double-clicking the Egg should trigger Shamino’s bark about slaying the unnamed king.
Use the F2 Cheat Menu to enter N for NPC, 265 for Pomdirgun, N for NPC Flags, then T for Met. Escape back out of the menu and double-click the Egg again. This time Dupre should bark, including Pomdirgun’s name.
Again in the F2 menu, enter N, 265, N, and then * for the advanced flags. Press 4 for the dead flag, then S to set the flag. Escape out and try the Egg, and the Avatar will bark.

You may want to go back in and toggle the Met flag. Notice that since Pomdirgun is dead and that clause takes priority over the ones that include Dupre and Shamino’s barks, they will remain silent here as long as Flag 4 is set.

You can also teleport back to Monitor and talk to the people to see the new conversation item. Since this flag was not tested by Origin, not all of the the conversations remove the Pomdirgun question option when asked. Standarr is an example of this.

Re: Usecode Tutorial for Fishnet Stockings

Posted: Sun Aug 07, 2016 3:53 pm
by Knight Captain
As I've learned more I've come up with easier ways to do both of these.

For Shmed, having a check for the MET flag when you talk to him can be used to trigger other events.

Code: Select all

void Shmed object#(0x44b) ()
{
	if (event == STARTED_TALKING)
	{	
		if (!SHMED->get_item_flag(MET)) // If not met.
		{
			SHMED->remove_cont_items(QUANTITY_ANY, SHAPE_SCROLL, 67, FRAME_ANY); // Remove existing scroll.
			SHMED->remove_cont_items(QUANTITY_ANY, SHAPE_KEY, 72, 17); // Remove existing key.
			SHMED->add_cont_items(1, SHAPE_CHAIN_LEGGINGS, 0, 0); // Add chain leggings.
			SHMED->add_cont_items(1, SHAPE_BAG, 0, 1); // Add 1 bag, quality 0, frame 1.
			var bag = SHMED->get_cont_items(SHAPE_BAG, QUALITY_ANY, FRAME_ANY); // Select the bag just created on him.
			bag->add_cont_items(1, SHAPE_SCROLL, 67, 34); // Add 1 scroll, quality 67, frame 34.
			bag->add_cont_items(1, SHAPE_KEY, 72, 17); // Add 1 key, quality 72, frame 17.
			bag->add_cont_items(1, SHAPE_STOCKINGS, 1, 1); // Add 1 stockings, quality 1, frame fishnets.
		}
		Shmed.original();
	}
	else
	Shmed.original();
}
If the player reads the scroll, this addition to the SIfixes scroll.uc will set the flag. I put this just a line after book_mode();

Code: Select all

	if (quality == 67)
	{
		gflags[123] = true;
	}
That's a lot easier than doing a map edit.

The Pomdirgun-is-dead and Marsten-can-be-accused ones are similar, just small edits to scroll.uc.