Page 1 of 2

A Doubt

Posted: Fri Jul 15, 2016 6:27 pm
by Jhonny
There are two Ernesto in moonshade(the ranger i mean)
Is this a bug or also present in the original game?

Re: A Doubt

Posted: Fri Jul 15, 2016 7:29 pm
by Knight Captain
I have not run into that. Where did you find him / them?

Re: A Doubt

Posted: Fri Jul 15, 2016 8:10 pm
by Jhonny
In the Winery

Re: A Doubt

Posted: Fri Jul 15, 2016 10:05 pm
by Knight Captain
Just before noon in the game I was able to find both Ernestos at the Catacombs hut and in the Winery like you said. Cool find!

Under the hood, Ernesto isn't a regular NPC but a spawned human "monster" much like the other male Rangers or Batlin. There are two eggs that spawn him:
Catacombs hut function 0x6C9 quality 3
Winery lobby function 0x6C9 quality 4

Likely there is some code that "unspawns" him, and seemingly there is a check that if he's slain he won't respawn. Looks like that might be flag 288 (0x120).

As for the question "Why did Origin program him this way instead of using one of the many unused NPC slots?" I do not have an answer for that.

Re: A Doubt

Posted: Tue Aug 09, 2016 1:23 am
by Knight Captain
My guess is either this is an original game bug, or Exult doesn't cache out at the same distance as the original game.

Ernesto isn't a real NPC but the Ranger Shape, Ident 1. His schedule is done with some greater-than and less-than signs rather than greater-than-or-equal and less-than-or-equal, so there are some hours where he shouldn't spawn.

Midnight to 7AM, Sleep at 2177, 1846.
8AM to 3PM, Tend Shop at 2193, 1863.
5PM to 8PM, Loiter at 2263, 2095.
After 8PM, Tend Shop again, but not clear where.

I've nearly figured out how to make him into a "real" NPC so this might be something fixable so he's got a schedule, and there's only one of him.

Re: A Doubt

Posted: Tue Aug 09, 2016 3:04 am
by Knight Captain
Code is done, will need to test it soon. Here's half:

Code: Select all

const int ERNESTO = -233;

extern void shapeRanger shape#(0x103) ();

void Ernesto object#(0x4E9) ()
{
	if (event == DOUBLECLICK)
	{
		0->shapeRanger();
	}
	if (event == STARTED_TALKING)
	{
		0->shapeRanger();
		ERNESTO->set_item_flag(MET);
	}
	if (event == PROXIMITY)
	{
		0->shapeRanger();
	}
	if (event == DEATH)
	{
		0->shapeRanger();
	}
}
I'm going to give him a magic bow and some arrows to differentiate him from the other rangers. He is second in command, after all.

Re: A Doubt

Posted: Wed Aug 10, 2016 12:45 am
by Knight Captain
Can anyone else verify finding multiple Ernestos at the same time?

Re: A Doubt

Posted: Wed Aug 10, 2016 10:15 am
by marzo
That code is unlikely to work: shapeRanger expects an object, and you are passing 0 to it. Better would be to pass item instead. Also, I recommend putting an 'else' before most of the ifs as it will result in faster code. Finally, since you call shapeRanger on every case, you can just pull it out and leave only the code to set met flag in STARTED_TALKING.

Re: A Doubt

Posted: Wed Aug 10, 2016 11:17 am
by Knight Captain
Thanks. I've got the rest of this done and will upload it soon.

Passing 0 to it worked in testing, but I'll try item instead.

Re: A Doubt

Posted: Wed Aug 10, 2016 7:46 pm
by Knight Captain
It is rarely used, but it is possible to pass 0 to another function and have it work. The Wall of Lights cutscene original code does this as: 0x0000->Func07D8();

Item is passed a lot more often, so I'll try that. Code, compile, test. :)

Re: A Doubt

Posted: Wed Aug 10, 2016 7:58 pm
by Knight Captain
I can't find any difference between the two, so I'll use item as suggested.

Code: Select all

const int ERNESTO = -233;

extern void funcRanger shape#(0x103) (); // Changed func name

void Ernesto object#(0x4E9) ()
{
	if (event == STARTED_TALKING)
	{
		item->funcRanger();
		ERNESTO->set_item_flag(MET);
	}
	else item->funcRanger();
}
Is that more in line with what you suggested?

Re: A Doubt

Posted: Wed Aug 10, 2016 8:13 pm
by Knight Captain
The only difference seems to be when a recycled NPC is slain the corpse does not take the name, so it's just "body" not "Ernesto's body". This doesn't seem to help:

Code: Select all

	else if (event == DEATH)
	{
		abort;
	}
Aside from that everything I've coded seems to be working to correct this multiple-Ernestos issue.

Re: A Doubt

Posted: Wed Aug 10, 2016 8:33 pm
by marzo
What I meant was:

Code: Select all

const int ERNESTO = -233;

extern void funcRanger shape#(0x103) (); // Changed func name

void Ernesto object#(0x4E9) ()
{
	item->funcRanger();
	if (event == STARTED_TALKING)
	{
		ERNESTO->set_item_flag(MET);
	}
}
But yours is close enough.

Re: body names: there is nothing that can be done about names from the usecode side: the body names are based on the NPC's number and stored in the body object when it is created, and monsters do not have an NPC number in Exult.

Also, DEATH event only ever triggers if tournament flag is set, so you can take appropriate actions (such as clearing tournament flag and killing the NPC).

And that is not even what abort does: what it does is exit all current usecode functions, nothing else.

Re: A Doubt

Posted: Thu Aug 11, 2016 4:25 am
by Knight Captain
Is there a way to rename a given shape via Usecode? If so, would using the DEATH event to rename the last created object be a workaround?

Since I've got Ernesto's new life almost done, I'm going to apply the same logic to the main 7 SS NPCs so they also have schedules and sleep. The code provisions NPCs 233 to 255 so they can be used in the future, waiting at the House of the Dead. Depending on if I also convert Aram Dol or not, that's either 14 or 15 ready for recycling for other uses.

And I've got some new functions to share too.

Re: A Doubt

Posted: Thu Aug 11, 2016 9:35 am
by marzo
No, there is not. You can rename an NPC, but not a shape.

Re: A Doubt

Posted: Thu Aug 11, 2016 11:43 am
by Dominus
Depending on what you want to do (especially when it's an inventory object) you could (probably) delete the shape with name foo and add the same looking shape foobar.

Re: A Doubt

Posted: Thu Aug 11, 2016 3:08 pm
by Knight Captain
I think this will be an acceptable wont-fix because most of these NPCs are not intended to be slain. The ones that are already have "body" as the title of their remains, so little is lost.

Re: A Doubt

Posted: Thu Aug 11, 2016 8:07 pm
by Knight Captain
It looks like the UI_set_item_frame_rot and plain UI_set_item_frame are backward in the Usecode doc. The rot one is indeed needed to set the NSEW rotation bit. The one without rot sets the non-rotated shape, only NS.

Re: A Doubt

Posted: Thu Aug 11, 2016 8:59 pm
by Knight Captain
Should I bother listing known shapes with code in si_externals.uc or keep it clean, adding only what is needed?

Code: Select all

extern void funcGangPlank shape#(0x96) ();
extern void funcSerpentGate shape#(0xA0) ();
extern void funcMap shape#(0xB2) (); // displays map based on quality or frame
extern void funcOphidianItems shape#(0xD1) ();
extern void funcChickenCoop shape#(0xD2) (); // creates chicken eggs
extern void funcTurtleHead shape#(0xD7) ();
extern void funcBigDoorV shape#(0xE1) ();
extern void funcPikeman shape#(0xE4) ();
extern void funcNakedBlonde shape#(0xE6) (); // Frigidazzi sex scene

extern void funcBigDoorH shape#(0xF6) ();
extern void funcRanger shape#(0x103) ();
extern void funcPowderKeg shape#(0x2C0) (); // explosion, also responsible for blowing open big brass doors.
 
// Silver Seed Shapes
extern void funcCapedAutomaton shape#(945) ();
extern void funcMageWomanBlueGreen shape#(1015) ();
extern void funcHealer shape#(946) ();
extern void funcOphidianSoldier shape#(947) ();
extern void funcMadMan shape#(975) ();
extern void funcCatMan shape#(957) ();
extern void funcGreenDragon shape#(978) ();

Re: A Doubt

Posted: Fri Aug 12, 2016 2:21 am
by Knight Captain
Any recycled NPCs that are listed as "unused" in ES are not keeping their changes through saved games. NPCs that are not listed like that work, so I can wipe Dupre's stats, but cannot do so for the future Ernesto at -233. Is this list hardcoded somewhere?

Re: A Doubt

Posted: Fri Aug 12, 2016 9:18 am
by Knight Captain
So far I have Ernesto and the 7 main SS NPCs about ready to go.

Re: A Doubt

Posted: Fri Aug 12, 2016 3:16 pm
by Knight Captain
I should specify that both used and unused NPCs are fully wipe-able and recyclable, but only used ones survive saving/reloading.

If all 29 unused ones below Fitch (< 296) can be made to work it would help the mod I am working on (not part of SIfixes).

Re: A Doubt

Posted: Fri Aug 12, 2016 4:48 pm
by marzo
For what is worth, Exult is not limited to 256 full NPCs and 100 monsters like the original; for your mod, you could turn all of these fake NPCs into full NPCs.

Re: A Doubt

Posted: Fri Aug 12, 2016 9:07 pm
by Knight Captain
It looks like I would have to edit the map then, since to be considered used the NPC has to appear on the map.

We would likely still need to skip the special range of 356, 357, 358, and 359 though, since those are used for the Avatar, the Party, Non-Party-on-screen, and the ANY wildcard.

Re: A Doubt

Posted: Fri Aug 12, 2016 9:14 pm
by Knight Captain
Placing them via Exult first seems to clear the unused setting on them, so looks like I'll be forced to do so.

Re: A Doubt

Posted: Fri Aug 12, 2016 9:32 pm
by marzo
Given your recent bug report, I took a closer look at what you are doing. So here it goes:
It looks like the UI_set_item_frame_rot and plain UI_set_item_frame are backward in the Usecode doc. The rot one is indeed needed to set the NSEW rotation bit. The one without rot sets the non-rotated shape, only NS.
The documentation is correct: if you want to PRESERVE the rotation flag, use set_item_frame; if you want to CHANGE it, use set_item_frame_rot. "Rotation bit" means exactly that: the bit that rotates the NPC from being facing NS to EW. I can show the code.
Any recycled NPCs that are listed as "unused" in ES are not keeping their changes through saved games.
Stop right there. What do you mean by "recycling unused NPCs"? Do you mean using usecode to place them back into the game world? If so, this will not work — unused NPCs can only be added back to the game world by selecting them in ES and dragging them into Exult, and doing anything else will cause all sorts of woe. Although to be fair, I guess that could be changed.

Re: A Doubt

Posted: Fri Aug 12, 2016 10:01 pm
by Knight Captain
Okay, so using the set_rot one is preferable then, at least to me. What is a use case for the set_non-rot change_frame one? I can see why it would be handy for get-non-rot though.

As for the NPCs, my understanding is that map editing is riskier than coding since it is a compiled file rather than text. This makes it harder for you to check and approve changes. That's why I've focused on doing this exclusively in usecode. If you're comfortable with me doing map edits, I can proceed that way.

Re: A Doubt

Posted: Sat Aug 13, 2016 5:35 am
by Knight Captain
I've got the map edits done, so just need to clean up my code and upload it all.

Re: A Doubt

Posted: Sat Aug 13, 2016 4:17 pm
by Knight Captain
While I can set Ernesto's Ident number to 1, starting the game resets it to zero.

Re: A Doubt

Posted: Sat Aug 13, 2016 6:30 pm
by Knight Captain
An old post elsewhere confirms Ernesto does appear too often.

As part of rewriting him, I've found he's got an odd check for the flag state of the Anti-Dupre shape.

Re: A Doubt

Posted: Sun Aug 14, 2016 2:00 am
by Knight Captain
I'm finding more errors in the original code.

Ernesto wouldn't check if you had a Fawnish ale bottle or not before telling you about it. QA probably didn't catch it because who gives up mid-quest in Monitor? Similarly he wouldn't act surprised if you had a tattoo and still asked what the Monitor shield was, despite his visit to Monitor as a lad. Surely he'd remember the tattoos.

Elissa will cause both conversation with the companions' faces to appear with text as well as different barks at the same time, which shouldn't happen. Like the other SS NPCs, her Ident number is used the way gflags would for normal NPCs. I'm not sure if this is why I just had a crash after talking with her.

Image

The girdiron football field's teleporter platform now works using the Beta's output destination. This prevents requiring death-by-starvation as the only way out of there.

As suggested I've changed the name of Sonar to Windrunner. Maybe some early draft of the game had you calling Sonar by the whistle rather than the Hound? He doesn't have any conversation or other actions though, per the original game.

NPCs 233-240 are now used by these formerly-spawned NPCs, but they were done The Right Way via being placed on the map using ES rather than my prior Usecode-only approach.

NPCs 241-255, 286, and 288-292 have been placed to the west of Vasculio in the House of the Dead. While this wasn't strictly required for SIFixes right now, it should make modding SI the game easier in the future. I've set them all to the Brass Automaton shape so they're visually different, given them Unused # names, and zeroed all their stats so using the stats deltas is easy consistent math.

I may recode Draxinar as well because he's got far too many spelling errors in his conversation for me to accept.

Jhonny, this is a lot of work you've unintentionally sent got me on. :)

Re: A Doubt

Posted: Sun Aug 14, 2016 2:19 am
by Knight Captain
How do I edit the contents of an NPC's usecode container in ES?

Re: A Doubt

Posted: Mon Aug 15, 2016 10:50 pm
by Knight Captain
I think I'm going to pass on editing the Silver Seed conversations until the improved Usecode extractor is done. Then it will be much easier to fix a lot of smaller issues that don't justify complete recoding right now.

Aside from the usecode container editing, that's the only thing keeping this from submission now. Three of the NPCs have spells that should disappear when they die.

Re: A Doubt

Posted: Tue Aug 16, 2016 12:19 pm
by marzo
Only the avatar can really have an usecode container. All it has are path eggs, by the way, which SI's usecode uses to run scripts on.

Re: A Doubt

Posted: Tue Aug 16, 2016 12:55 pm
by Knight Captain
The reason I ask is that NPCs with spell shapes are supposed to lose them on death. How can I handle this?

I need to check the tournament flags for the Silver Seed NPCs.

Re: A Doubt

Posted: Tue Aug 16, 2016 2:17 pm
by marzo
That happens automatically when they die (this is a bug if it is not happening). The spells would not be inside the usecode container anyway.

Re: A Doubt

Posted: Wed Aug 17, 2016 1:30 am
by Knight Captain
It appears Exult handles this differently for new NPCs vs. original ones. Using the latest release (2016-08-09) with the unmodded SI, if I put on God mode and kill Elissa or Shal neither has spell shapes on them.

If I dispatch them the same way in the mod, they retain the spell shapes on their corpses. Vasculio does not. Does it matter they are in containers (bag/backpack)?

It also looks like the NPC Ident number and Tournament flag isn't being retained by Exult when starting a new game, even if those are set in ES. I have not checked if they are retained by saved games, but that's how the fake NPCs determine which conversation to use.

Shall I submit a bug report?

Re: A Doubt

Posted: Wed Aug 17, 2016 3:32 am
by Dominus
Hmm, can you try if that happens with a newly created mod? I suspect that it might be due to the mod being essentially an old savegame.

Re: A Doubt

Posted: Wed Aug 17, 2016 10:08 am
by marzo
If he is saving from ES, then it is creating a new savegame. I will have to check the identity issue; but in the mean time, you can set custom usecode for them in ES which sets the identity to the proper value then calls their normal usecode.

As for the spells, I just realized that the way the code is setup right now prevents spells in containers from being deleted because the container will just be moved wholesale to the body.

Can you make bug reports for these issues?

Re: A Doubt

Posted: Wed Aug 17, 2016 10:35 am
by Dominus
I'm happy if my worst case scenario is still a non-issue

Re: A Doubt

Posted: Wed Aug 17, 2016 12:40 pm
by Knight Captain
What seems okay is that once a game is started, the conversation-changed Idents remain. I'll verify that is is retained by save/load. It's not as much of an issue at the start because I recoded Ernesto and I think he was the only non-zero one except maybe Johnson.

Would a workaround (event == DEATH) allow me to delete the spell shapes?

As always, thank you. I'll file the bugs when I'm home.

Re: A Doubt

Posted: Wed Aug 17, 2016 8:18 pm
by Knight Captain
Bug 1976 has been opened. There are two main issues.

1) The spell shapes do not disappear from the new NPCs. If I can trigger a function on (event == DEATH) I could write the usecode to remove these spell shapes from the dying person. Maybe there is some unidentified UI_ something that does this?

2) The MET and SI_TOURNAMENT flags, and IDENT numbers are not taken from the initial state of the mod files (initgame.dat?) but seem to be set by some function around the time Iolo finishes his welcome speech. For example, DBeyer 293 only gets his Tournament flag set after Iolo is done. This is also why Johnson doesn't have his IDENT set to 15 from the start but only when you are near him. So Marzo's suggestion to set these elsewhere seems valid. I'd like to know what function does this at the start though so I can append to it via new code rather than leaving edits all over.

I don't know if these would be an issue in a brand new game in ES, but my focus is on modding SI.

Re: A Doubt

Posted: Sun Aug 21, 2016 6:31 pm
by Knight Captain
Here's my code that removes the spell shapes on death when the tournament flag is set.

Code: Select all

void removeAllSpellShapes (var npc)
{
	var spell;
	var spells = [SHAPE_IGNITE, SHAPE_CURSE, SHAPE_SWORDSTRIKE, SHAPE_DISPEL_MAGIC, SHAPE_LONGER_IGNITE,
				  SHAPE_MULTICOLOR_TELEKINESIS, SHAPE_PARALYZE, SHAPE_TELEKINESIS, SHAPE_DEATH_BOLT, SHAPE_DOUSE,
				  SHAPE_UNNAMED_FIRE_BOLT, SHAPE_LIGHTNING_BOLT, SHAPE_FIRE_BOLT, SHAPE_DRAGON_BREATH];

	for (spell in spells with index to max)
	{
		npc->remove_cont_items(QUANTITY_ANY, spell, QUALITY_ANY, FRAME_ANY);
	}
}

Re: A Doubt

Posted: Fri Sep 02, 2016 12:20 am
by Knight Captain
As Marzo noted in IRC in the logs for 25 Aug 2016, the rabbit's function handles a lot of the initial setup of the game. I found it also includes wiping most of the SI-used NPC flags, and then resets them as needed for the SI NPCs. My guess is this was done to clear anything left over from the BG NPCs since their names and alignments were not fully wiped.

Re: A Doubt

Posted: Wed Sep 21, 2016 6:27 pm
by Knight Captain
In testing, I found a 'bug' in Tsandar's code that wipes his schedule after conversation. If the conversation ends because you don't have the 200 gold to train, it also sets his current activity to just STANDTHERE.

Re: A Doubt

Posted: Wed Sep 21, 2016 7:17 pm
by Knight Captain
Unless I've got my new Usecode wrong, it seems like all The Silver Seed NPCs do this.

Re: A Doubt

Posted: Sat Sep 24, 2016 11:05 pm
by Knight Captain
Disregard my last two posts. I didn't verify my test environment. :(

Re: A Doubt

Posted: Sun Sep 25, 2016 2:38 am
by Knight Captain
Yurel has PROXIMITY barks code but it doesn't seem to work. Can anyone else see him bark?

Re: A Doubt

Posted: Thu Sep 29, 2016 10:03 pm
by Knight Captain
I'm still stumped on this. The Yurel bark code is very similar to the Iolo bark code in SIfixes, so I borrowed that for new Yurel bark code. It still doesn't work.

Then I borrowed that code and gave it to Ernesto (my real NPC version) and it works.

I cannot see a difference between the two. They're both "Monsters" in ES, so there has to be some other reason why one barks and the other does not.

Re: A Doubt

Posted: Fri Sep 30, 2016 12:11 am
by Dominus
You write that it works with your real NPC version of Ernesto and then that they are both monsters?