Applications of the UI
![Aquadrizzt](https://forums.beamdog.com/uploads/userpics/276/nVR5XE74IJDXY.jpg)
in UI Modding
I'm unfamiliar with the internal workings of the UI system, so I figured I'd ask and let someone who actually knows what's going on answer my question.
Are UI elements able to cause in-game effects? For example, could you add a toggle above the hotbar that grants improved movement speed? If so, could that toggle be only made available to certain characters (such as only Barbarians and Monks)?
If this is possible, how would one go about implementing it?
Are UI elements able to cause in-game effects? For example, could you add a toggle above the hotbar that grants improved movement speed? If so, could that toggle be only made available to certain characters (such as only Barbarians and Monks)?
If this is possible, how would one go about implementing it?
0
Comments
The UI is largely disconnected from the rest of the game. Basically, the only interaction the UI can have with the game world is through console commands. It might be possible to do what you are describing by having the button use C:CreateCreature to create an invisible and non-colliding creature. This summoned creature's script could apply a spell to all party members that applies opcode 176; you could even have this script check for player class, if you wish. To disable the speed you could use opcode 321, again using the invisible-creature trick, and this time applying a "speed removal" spell. I've attached a rough version of what you are describing; I think you would learn more from looking at that than me trying (and probably failing!) to explain all of the details.
Edit: I forgot to mention, the rough example I attached is for BG2EE
To further explain the context of the question, I'm trying to implement some form of 5e Style Bonus Actions/Reactions.
My thoughts were to have Reactions be contingencies you toggle on or off, which only activate if you haven't Reacted in the last round. A UI toggle for each possible Reaction your character can make will make the management of such a system much less unwieldy (as you don't have to go into a dialog menu to change the configuration).
Bonus actions basically say how you spend your "not attacking or casting a spell" action each round. So a set of buttons that you can press to perform one of your bonus actions would make that much less miserable. (For example, I could have my Barbarian Enter or Exit Rage as a bonus action instead of taking their main action.)
It looks like this *is* possible because of the ability to tie scripts to buttons. That's really exciting.
EDIT: Is it possible to change the buttons presented depending on the character you have currently selected?
EDIT2: Is it possible to target only the currently selected character with the script?
I've updated the override.zip with an example of how to switch between which buttons are showing based on what class the currently selected character is.
The issue of only targeting the currently selected player is a tough one. I don't think that is possible, to be honest. There isn't enough cross-talk between the UI and the game environment to accurately do it.. sorry
EDIT: Would you mind clarifying the exact behavior of the code you wrote? I see the class checks, but I'm not sure how those tie into the buttons that are displayed. (Sorry for all the questions.)
Perhaps this is also a stupid question, but parts of the UI seem to refer to character[currentID]., is there not some way that you could read the current character and pass that to the script somehow?
EDIT2: Hacky thought of the day: you can check a creature's stats to determine which buttons are visible right? Why not just assign every party NPC to a different value of the tracking stat? Imoen is 1, Jaheira is 2, etc... This gives you 256 unique identifiers from just tracking (which is not actually used by any system, including the Tracking HLA).
And then you can fine-tune targeting because the summoned creature's can specifically target them.
The key in the button-switching is the Infinity_PushMenu() calls. Basically, bubbShowSpeedButtons() is deciding which button to show based on the character's current class. Infinity_PushMenu() is what is used to "open" a menu and display it to the user. Infinity_PopMenu is the inverse of Infinity_PushMenu; it closes the specified menu and hides it from the user. bubbShowSpeedButtons() is hiding all the menus which contain the wrong buttons, and showing the one that has the right buttons. In my example, the only difference between the two buttons (contained in BUBB_SPEED_MAGE and BUBB_SPEED_FIGHTER) are the tooltips.
You are correct; UI.MENU does indeed know the currently selected character, I just can't see a way of passing it to the scripting environment as a object. I'm pretty sure the id variable that is used to access the current character is an internal reference to the character, though I don't believe we can use it anywhere else. I've tried many times to figure out a way to target specific characters with a script from the UI; I just cannot get something to remotely work, not even a hacky workaround.
Have the script cast the effect on all characters in the party, but the spell only affects people with exactly X tracking, or this kit, etc. (How often do you run two characters of the same kit, etc.) It's a bandaid to be sure, but it means that you can have UI buttons that typically only affect a single character.
I don't know if you are still interested in this - but I did manage to figure out a *really* hacky way of specifically targeting Player1-6 from the UI. It has to do with giving each player a marker spell, and then detecting this marker spell in the UI to figure out their scripting object. I've updated the override.zip with the code, if you are interested.
In function scheduleCompilePlayerIds() you write that you have to put something in the log to prevent quickload check from firing more than once. What do you mean by this?
@Greenman: The way the code detects a reload is by checking if the combat log is empty. Once a reload is detected, I have to throw a line into the log to prevent that check from firing indefinitely, (since the only thing it is checking for is an empty log).