I'm relatively new to the KotOR community, and I've just started reading through tutorials and examining files to learn the basics of modding... Apologies if this has been posted before, as the search function is currently not working.
I'm working on a new recruitment mod which replaces G0-T0 (yeah, big surprise there, I know), following Darth333's awesome recruitment tutorial, and stoffe's puppet tutorial, and it's pretty much all working quite nicely.
But I do have a few questions, mostly about puppets.
- Is it possible for puppets to equipped items or feats (droid trick ect.) on enemies? I have a couple of modified unlimited use droid items equipped on a droid puppet, but I have yet to see the puppet ever use them.
-Maybe this is something I missed but, how exactly do you get a recruit script and puppet creation script in the same dialogue? (Like when you recruit Bao-Dur/Remote) Every time I put them in the same dialogue entry (or a following one), only the recruit script seems to fire, and it seems to ignore the puppet script.
Currently, the only way around it I've found is to have it so that you must talk to the new recruit to activate the puppet script. Which brings up another question...
-How would I make it so that once you've trigged a dialoge option (and any connected scripts), you don't get the dialoge option again? I get the feeling this has to do with globals/booleans, which I've never really understood.
Anyway, thanks in advance! Any help is appreciated.
- Is it possible for puppets to equipped items or feats (droid trick ect.) on enemies? I have a couple of modified unlimited use droid items equipped on a droid puppet, but I have yet to see the puppet ever use them.
What have you set the AI style of the puppet to? This can affect what abilities and items the puppet uses during combat. If, for example, you use NPC_AISTYLE_PARTY_REMOTE (14) the puppet will just follow the owner around and use standard attack actions on enemies, never any powers, feats or items. If you use one of the Grenade or Support AI styles it should use items/powers/feats as well.
Though if you don't use the tweaked AI scripts I've done it may be rather sporadic in its item/power use. If you want it to only use droid weapons and never any standard attacks you'll need to make a custom AI script for it though.
-Maybe this is something I missed but, how exactly do you get a recruit script and puppet creation script in the same dialogue? (Like when you recruit Bao-Dur/Remote) Every time I put them in the same dialogue entry (or a following one), only the recruit script seems to fire, and it seems to ignore the puppet script.
Hmm, have you tried putting the scripts on separate nodes? I.e. first the recruit script, and then on the next node the puppet script?
You can also try to modify the recruit script to make it add the puppet as well right after the NPC has been added to the party.
-How would I make it so that once you've trigged a dialog option (and any connected scripts), you don't get the dialog option again? I get the feeling this has to do with globals/booleans, which I've never really understood.
You'd usually use either local or global variables for this.
Local variables are stored on a particular object (like a creature, placeable, trigger, area or module) and can only be accessed when that object is present in the active game world (i.e. exists in the same module as the player currently is in). There are a fixed number of available local variable slots for each object.
In TSL there are 160 boolean slots (numbered 0-159) and 32 number slots (numbered 0-31) for each object. A boolean variable is like an on/off switch and can only contain either the value FALSE (0) or not FALSE (true). A number variable can contain a value between 0 and 255.
Note: As far as I can tell you can't reliably set local variables on inventory items (weapons, robes, armbands etc).
Global variables can be accessed from anywhere in the game and are not set for a particular object. Unlike local variables they are accessed by a text tag/name instead of a slot number, and they must be added to the globalcat.2da file for the game to recognize them.
Which type you choose to use is generally up to you, but just tracking dialog stages of a single NPC is often best to set as either a local number variable, or a series of local boolean variables, on that NPC, since the info is only needed by that NPC thus reducing the amount of global data the game need to keep track of, and you won't have to modify any 2DA files for them to work.
For things like plot progress, quests and the like you usually use global variables, since those can be checked from anywhere and aren't associated with one particular NPC or object.
In TSL there are a number of ready-made scripts you can use to set and check both global and local variables in dialogs.
Setting:
a_global_dec - decreases the global number variable whose tag is set in the String Param field by the number set in the P1 field.
a_global_inc - increases the global number variable whose tag is set in the String Param field by the number set in the P1 field.
a_global_set - sets the global number variable whose tag is set in the String Param field to the number set in the P1 field.
a_global_bool_set - sets the global boolean variable whose tag is set in the String Param field to the value set in the P1 field. ( 0 = false, 1 = true )
a_localn_dec - decreases the local number variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter, by the number set in the P2 field. (leave the String Param field blank to use the object running the script = the conversation owner)
a_localn_inc - increases the local number variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter, by the number set in the P2 field. (leave the String Param field blank to use the object running the script = the conversation owner)
a_localn_set - sets the local number variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter, to the number set in the P2 field. (leave the String Param field blank to use the object running the script = the conversation owner)
a_local_set - sets the local boolean variable on the object whose tag is set in the String Param field, and whose slot index is set by the P1 parameter. (leave the String Param field blank to use the object running the script = the conversation owner)
Getting:
c_global_eq - returns true if the global number specified by the String Param field equals the number set in the P1 field.
c_global_gt - returns true if the global number specified by the String Param field is greater than the number set in the P1 field.
c_global_lt - returns true if the global number specified by the String Param field is lower than the number set in the P1 field.
c_global_bet - returns true if the global number specified by the String Param field is higher than the number set in the P1 field and lower than the number set in the P2 field.
c_global_set - returns true if the global boolean specified by the String Param field is set (true).
c_localn_eq - returns true if the local number set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, matches the value in the P2 field.
c_localn_gt - returns true if the local number set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is greater than the value in the P2 field.
c_localn_lt - returns true if the local number set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is lower than the value in the P2 field.
c_local_set - returns true if the local boolean set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is true (i.e. not FALSE).
c_local_notset - returns true if the local boolean set on the object whose tag is set in the String Param field (leave blank for conversation owner), where the slot index is set in the P1 field, is FALSE (0).
P1, P2 and String Param above refer to the input fields listed to the right of the script name field in tk102's DLG Editor.
Some local numbers and booleans are already used by generic scripts such as the Random Loot and AI scripts, and as such should be avoided for any objects of that type that have AI scripts/loot scripts. Here is a likely incomplete list of some locals already used:
Creatures:
Boolean 1-3 - Creature AI, ambient NPC settings.
Boolean 10 - Dialogs, used to set that the creature has been talked to once.
Boolean 20-28 - Creature AI, used to activate userdefined script events.
Boolean 29 - Creature AI, used to set if NPC should play ambient animations when idle.
Boolean 30-64 - Reserved range for scenario/plot specific uses, some NPCs use them, most do not.
Boolean 65 - Creature AI, used to set of the NPC should walk around randomly when idle.
Boolean 66-86 - Creature AI, various settings set in the NPC spawn scripts.
Boolean 87 - Creature AI, blocks out the AI for this creature if set.
Boolean 88 - Creature AI defined, but likely unused in K2:TSL.
Boolean 89 - Creature AI, sets the creature to use the Boss Combat AI, overriding their normal AI style.
Boolean 90 - Creature AI, sets that the creature has activated their energy shield in combat.
Boolean 91 - Creature AI, toggles userdefined event for the OnDialogEnd event handler.
Boolean 92 - Creature AI, sets that a force using NPC has buffed with Resist/Immunity at start of battle.
Boolean 94 - Creature AI, sets that the creature has entered combat.
Boolean 95 - Creature AI, sets the creature to use the KotOR1 Malak end fight AI.
Boolean 96 - Creature AI, sets creature to use a zone controller to determine their combat zone.
Boolean 97 - Creature AI, setting for the OnDialog event.
Boolean 98-109 - Creature AI, used by the waypoint walking/ambient animation system.
Boolean 110-159 - Generally unused as far as I can tell.
Number 0-2 - Creature AI, used by the waypoint walking/ambient animation system.
Number 3-6 - Creature AI, internal state info for last attack used, chosen attack pattern etc.
Number 7 - Creature AI, Zone Controller this creature is attached to, if any.
Number 8-9 - Creature AI, settings for healer AI, how much to heal and how often.
Number 10-11 - Creature AI, used for turrets to determine rate of fire.
Number 12-31 - Generally unused as far as I can tell.
Placeables:
Boolean 10-19 - Security terminals, used to set the user's choice of action.
Boolean 55 - Containers, container has been bashed and broken item substituted.
Boolean 57 - Containers, used to set that random loot has been spawned.
Triggers:
Boolean 40 - Used to set that the trigger has been tripped for one-shot triggers.
Wow, when you answer a question, you really answer everything don't you? :D
What have you set the AI style of the puppet to? This can affect what abilities and items the puppet uses during combat.
Ah, I did indeed use just the regular NPC_AISTYLE_PARTY_SUPPORT. I wasn't sure if it was possible to use other AI's for puppets, so I just left it as the default one to eliminate and possible variables.
Though if you don't use the tweaked AI scripts I've done it may be rather sporadic in its item/power use. If you want it to only use droid weapons and never any standard attacks you'll need to make a custom AI script for it though.
I am indeed using your Improved AI scripts, the one available from KotORfiles, anyway. But hey, sporadic is better than none, I just wanted the puppet to occasionally do something other than the default attack. I'll try some of the other ones then!
Hmm, have you tried putting the scripts on separate nodes? I.e. first the recruit script, and then on the next node the puppet script?
You can also try to modify the recruit script to make it add the puppet as well right after the NPC has been added to the party.
Indeed I have, but when putting the recruit script on the first node, it brings up the GUI, which interrupts the rest of the conversation. (Unless I put a delay time that's rather long) Can I safely remove 'ShowPartySelectionGUI' from the recruit script? I did a quick attempt at combining the recruit/add puppet with little success.
Which type you choose to use is generally up to you, but just tracking dialog stages of a single NPC is often best to set as either a local number variable, or a series of local boolean variables, on that NPC, since the info is only needed by that NPC thus reducing the amount of global data the game need to keep track of, and you won't have to modify any 2DA files for them to work.
Alrighty, I'll tinker around with the local variables and scripts, as, at this point I'm only looking for NPC specific things, and don't have any side-quests or anything in the works.
Thanks for the quick reply!
Ah, I did indeed use just the regular NPC_AISTYLE_PARTY_SUPPORT. I wasn't sure if it was possible to use other AI's for puppets, so I just left it as the default one to eliminate and possible variables.
Hmm, I forgot to mention... if the droid weapon spell added to the puppet is a custom one you've created yourself, that doesn't use one of the standard spells in the game, make sure the category column in spells.2da is set to 0x8000, otherwise the AI scripts won't find it.
If you are using the tweaked AI you should set the AI style to NPC_AISTYLE_PARTY_SUPPORT (13), this will make it run the special droid AI if the Race of the puppet is set to Droid (1).
Indeed I have, but when putting the recruit script on the first node, it brings up the GUI, which interrupts the rest of the conversation. (Unless I put a delay time that's rather long) Can I safely remove 'ShowPartySelectionGUI' from the recruit script?
You could remove it, but then you'd need to make sure the new party member is added to the group automatically, and another member booted off if the party was already full. In that case it's probably less intrusive to keep the ShowPartySelectionGUI() function call, but use its callback script to add the puppet. The first parameter to the ShowPartySelectionGUI() function can be set to the name of a script that will be run automatically when the player exits the party selection screen.