Please help: Trying to modify/fix Tome of Battle

Sorry, I meant there were already too many checks. For instance, it could just say:

if (nWarblade > 0 && GetLocalInt(oToB, "SupernalClarity") == 0)
     DisplayGuiScreen(oPC, "SCREEN_MARTIAL_MENU_WB", FALSE, "martial_menu_wb.xml");
     ExecuteScriptEnhanced("gui_quickstrike", oPC, FALSE);
     ExecuteScriptEnhanced("gui_addqs_texture", oPC);
     SetLocalInt(oToB, "IsQStrikeActive_WB", 0);

Do that for the controlled character (checking for each class’s integer and the martial adept feat, of course) and just close the gui for everyone not currently controlled.

That would do everything Warblade-related in one check and would open the quickselect. A lot happens when you open the quickselect via gui_quickselect and gui_addqs_texture though (I have a decent machine and notice a slight lag each time I open it), so I don’t know if saving the click is worth it.

EDIT: now that I look at it more, outside of the script calls for the quickselect menu, it basically does the same things it did originally. Maybe I will try and run the original script OnSelect and see what happens.

I think opening the quickstrike menu automagically if it was open the last time you piloted the character would be an improvement. Any time I’m switching to a Crusader or Warblade in combat I’m likely going to either order a maneuver or order the maneuver recovery on the warblade, so I’m going to want that quickstrike menu open as soon as I switch back.

Swordsage and non-tob-classes would have a much smaller gas tank, but if I left the quickstrike menu open I probably was going to use maneuvers next round and only switched away to do some spellcasting.

Do you play it differently?

It does need the check of “was last open”, because out of combat I’m going to have the menu closed and I don’t want the lag when switching between characters because I’m dealing with traps or buffing or whatever.

Come to think of it, I wonder if it’s possible to tie up the quickstrike menu to a hotkey. I probably would tie it to the same quickcast hotkey so it plays like a caster, but that’s me.

Not sure about hotkeys. I feel like that may be hard coded. If you can run a script when a GUI opens (not sure what the XML callback for that is), you could have it open when you pressed F for the quickcast menu, but does that menu even open if the character is not a caster? As much as I want to play a character build that doesn’t include Warlock, I have never been able to force myself to - the pull of the `lock is just too strong - so I have never tried to open the quickcast menu with a melee cat.

When I play, I just open it up when I load the game and leave it off to the side open the whole time. Since the game becomes Time Stands Still > Recover Maneuvers (While TSS is going) > Repeat, I am always using it.

You may not need to run the script each time (unless the character has leveled up maneuvers since the last time it was opened with the script) and just try opening it with DisplayGUIScreen. Not sure if that would work, but it might!

Non-casters don’t get to open the quickcast menu I’m afraid, and it does seem to be hardocded, or at least the XMLs don’t mention anything on hotkeys and there are no vanilla scripts calling the quickcast menu that I can find. I had hoped that there was a little script that checked if it was a caster and then decided to open the menu or not, but no dice.

I usually leave it open as well while in fights, at least for martials, but outside fights it’s a bit too much screen real estate that I can’t click through to get to that chest.

I could see having it closed in a fight with non-martials using martial study, say, get an utility maneuver, assassin’s stance, and the dex-to-damage feat on a rogue, you’re just going to activate the stance and then forget about the menu forever. But that kind of basically autofights without supervision so it’s not like I’m switching to them outside “Get away from the AOE you fool!”.

Haha you have basically described my most recent character, except not a Rogue. Warlock + Warblade. The Dex-to-Damage feat (Shadow Blade), Assassin’s Stance and Battle Cunning. Retributive Invisibility means the latter two always proc. So Dex-, Str-, Int-to-damage and 2d6 sneak attack on every hit. With Perfect TWF, Flee the Scene, and TSS that is 26 attacks per round at level 30. And you are a Warlock, so you can craft the best weapons for yourself.

I think I’ve found a way to persist everything across campaigns. Just need to do a bit more testing.

It should be possible to add a ToB “tab” to the vanilla quickstrike menu. Then add a check in the code that handles the martial menu to check if you’re a spellcaster and either open the vanilla, or ToB quickstrike.

I always have a thing for trying to make mod content feel like it’s part of the basegame. So I was never a big fan having a big sword-menu hanging out in the screen. I would have tied those buttons to feats.

Issue being I don’t think you can get the quickspell to open on non-casters, so that tab is never going to show up outside gishes.

And you don’t want a either/or, because gishes. Particularly if anyone ever bothers to implement JPM.

Issue being I don’t think you can get the quickspell to open on non-casters, so that tab is never going to show up outside gishes.

Right. So non-spellcaster would get the ToB-quickstrike menu. So as pseudocode:

	if (GetIsSpellcaster(oPC))
		// Vanilla quickspell menu
		sXML = "quickspell.xml"				
		// ToB quickstrike menu
		sXML = "quickstrike.xml"
	DisplayGuiScreen(oPC, sScreen, FALSE, sXml);

I had a similar idea, but who would call that code? That’s the issue here, the opening of the quickspell menu seems to be hardcoded since it’s never mentioned on any scripts and the gui xmls call on a function that’s also not on any scripts.

Since the whole ‘don’t open anything if it’s not a caster’ is hardcoded, we can’t just slip a call on the quickspell.xml that opens the quickstrike one, because the game will see it’s not a caster and never call it.

Note also that gishes are a thing, if you’re a bard/crusader exploiting the whole white raven goodness then you want both the quickstrike and the quickspell. If you’re a warlock/whatever, you probably want your invocations to open too.

not sure if this helps you guys but there’s a UserDefinedEvent signalled by the engine

// Brock H. - OEI 05/24/06 - called when this creature has become controlled, or is no longer controlled, by a player
1 Like

True! That would work for me as the merge I’m working on uses event scripts via Kaedrin’s stuff, but the ToB system actually doesn’t (miraculously) hook into the event handlers directly at all. It uses OnAquire when it gives you the book and runs all the other updates via a persistent feat. You could SetEventHandler I suppose…

i guess that’s a way of keeping things encapsulated, instead of changing module-level scripts …

Speaking of bugs! This is one I slayed ages ago… and then lost the files.

Whenever gui_execute_boost, gui_execute_counter, gui_execute_stance, or gui_execute_stance2 get called, they call a locally-defined function called CheckStatus (which is identical in all of them, so it really should be in an include) which checks if you’ve been disabled, if you have, they set a local int called bot9s_status_check to 1.

This local int is never cleared, once it’s there, you can no longer do any stances/boosts/counters.

These are the only scripts that use this local int btw, nobody else checks for it or sets it, and with the amount of code replication it ought to be skipped and just used a function that returns 1 or 0 on an include instead of this weird thing.

Anyhow, the hack solution is to add clearing this localint to the CheckStatus function when it doesn’t detect a problem. The slightly prettier solution does that and moves it to an include that returns 1 or 0 and cleans up the calls to the local int from those 4 scripts, then replace the identical check on gui_activate_sf for good measure, which runs the exact same check but do so inside main and don’t leave a localint hanging and mucking things up for everyone.

1 Like

Interesting - I’ll look at that. Not sure if this function exists in NWN2, but in NWN1 there is GetEffectDurationRemaining and you could grab that for the disabling effect and set a delay loop to clear the integer. Would need to be a loop rather than a DelayCommand in that case.

If only those scripts use it, I doubt the integer is doing anything though (since each one of them is already doing the check status thingy anyhow). Mostly those scripts just set up the data to pass into Student of the Sublime Way or something else downstream/execute the proper script. The gui_execute_strike script doesn’t check status?

EDIT: just actually looked at the script - just make that function an int function rather than a void function if nothing else uses the local integer. Then just:

int nStatus = CheckStatus(oPC);

Or just jam the whole thing in void main().

Something like:

int CheckStatus(object oPC)
	int nCheck;
	effect eSuck;

	eSuck = GetFirstEffect(oPC);

	while (GetIsEffectValid(eSuck)) // In order to initiate a maneuver the player must be able to move(ToB p.38).
		nCheck = GetEffectType(eSuck);

			return 1;

		eSuck = GetNextEffect(oPC);

    return 0;

Could be in an include if desired. I’m lazy though, so I wouldn’t. :slight_smile:

All the gui_execute_whatevers check conditions, but those I mentioned are the ones with the bug.

There’s no need for checking durations. You’re disabled? You don’t get to do fancy weeaboo fightan magic, print a message to the console and exit early. You aren’t anymore? Code proceeds and wuxia happens.

I did, pretty much exactly that code, just slapped it in the misc include instead. And altered the calls to use that return value instead of a local int of course.

Yeah, after I looked I realized it was just a really silly way of scripting that check. The duration isn’t important.

Notably, gui_execute_strike feeds to Student of the Sublime Way and its spellscript activate_strike, which just has that status checking code in a separate function and doesn’t bother setting an integer. Not sure why the author did that local variable thing with the other gui scripts.

This may be a bit outside of the scope here. But I’ve been going over the notes Drammel kept to find out why he did certain things the way he did.
For example, why did he make copies of a whole bunch of includes? Turns out it was because of the DRM on MoW Mysteries Of Westgate Bug Notes - Drammel's Notes

Looking at MoW’s .hak files, it seems the only actual issue was nw_i0_spells. Though I don’t think having that copy is still necessary anymore with the DRMless version of MoW included in the gog release.
Edit: Actually nevermind. A .hak is loaded after files in the Override folder. So having a copy of nw_i0_spells would still be necessary.

1 Like

Yeah he made a note about that somewhere in the codebase too. Said he was having trouble compiling with the vanilla includes so just made duplicates. He made some copies of includes from Kaedrin’s too and put them in. This has been a real thorn in my side because he also took functions from Kaedrin’s stuff and re-used them in his own includes without changing the name. So trying to merge the two things together gets a bit hairy. My script for Eldritch Glaive is absurd because I made use of the good features of the scripted combat system from ToB, but since there is conflict now due to the replicated functions, I had to copy and paste all the functions I needed from ToB directly into the script so I could avoid the tangled bird’s nest of includes altogether.

Dumb bug: Blistering Flourish (DW1) affects the user, when it shouldn’t.