First, you don't need to add any XP. Adding a class automatically gives you enough to level up. Second, you've misspelled "multiclass" as "mutliclass". Don't feel bad, I did the same thing in my dialogue file when I was working on this. Third, CreateItemOnObject won't make you equip it, if that's what you want - although you couldn't equip it anyway until you actually level up, because you don't have the right feats.
Thanks, i picked the script somewhere else but that clears it up. Second, the Createitem bit, I wanted the items to go to my inven. Not equip. Like i level up and then get a lightsaber. Would that work?
Thanks for all yorur help.
I believe you're supposed to keep the NPC tag as the tag of whoever you're replacing. So you'll have to check the original NPC for that. The NPC integers are as follows (you can paste this right into your script if you need it for reference, it won't do anything):
Code:
/*
KOTOR
int NPC_BASTILA = 0;
int NPC_CANDEROUS = 1;
int NPC_CARTH = 2;
int NPC_HK_47 = 3;
int NPC_JOLEE = 4;
int NPC_JUHANI = 5;
int NPC_MISSION = 6;
int NPC_T3_M4 = 7;
int NPC_ZAALBAR = 8;
*/
/*
KOTOR 2
int NPC_ATTON = 0;
int NPC_BAO_DUR = 1;
int NPC_CANDEROUS = 2;
int NPC_G0T0 = 3;
int NPC_HANDMAIDEN = 4;
int NPC_HK_47 = 5;
int NPC_KREIA = 6;
int NPC_MIRA = 7;
int NPC_T3_M4 = 8;
int NPC_VISAS = 9;
int NPC_HANHARR = 10;
int NPC_DISCIPLE = 11;
*/
You can use either the integer or the name (exactly as it appears) - depending of course on who you're replacing. You also might want to add the following, which will bring up the party selection screen and force the player to pick your new NPC:
Code:
ShowPartySelectionGUI("", iNPC, -1);
The "" is the name of a script to fire upon exiting, so put something in there (in the quotes) if you want to fire another script (such as a dialogue). Change the -1 to another NPC integer if you want another forced NPC. But if you're going to do this, you have to make sure the module is set to unescapable, or else fire the following as well:
Code:
SetAreaUnescapable(1);
...which will prevent you from changing party members, no matter what the area. Then once this is over, fire:
Code:
SetAreaUnescapable(0);
...which will let you change party members again. This function only affects a single module for as long as you're in it and is undone if you enter a new module, so if you're dealing with more than one you'll have to trigger it each time you enter a module - I believe this only ever happens in K2, and they do it by setting a global and then having all the modules' OnEnter scripts check that global.
So here's an example with everything, replacing Mission (because I think she's useless but feel free to change it):
Code:
void main() {
//Define everything
object oPC = GetFirstPC();
object oNPC = GetObjectByTag("mission", 0);
int iNPC = NPC_MISSION;
int iClass = CLASS_TYPE_JEDISENTINEL;
//Recruit the NPC
AddAvailableNPCByObject(iNPC, oNPC);
SetNPCSelectability(iNPC, 1);
//Multiclass to Jedi Sentinel and give items
AddMutliClass(iClass, oPC);
CreateItemOnObject("g_a_jedirobe01", oPC);
CreateItemOnObject("g_w_shortsbr01", oPC);
//Bring up the party selection GUI, force the new NPC, and prevent any further changes
SetAreaUnescapable(1);
ShowPartySelectionGUI("", iNPC, -1);
}
Simple, right? But basically, AddAvailableNPC is really the only thing required to add an NPC (no really?) to the party. It's a lot like AddMultiClass; you think because it's such an important feature it must be immensely complicated, when in fact it's one line - although the hard coded stuff that the function calls probably is immensely complicated. Anyway, it's very simple, the rest is just window dressing. But of course you should consult the tutorial here on recruiting... it goes over a lot of things I haven't covered.
THANKS SOOO MUCh! Im sure many people will find this helpful, i get it. Your a true master JC
EDIT: Will this still work if I have 2 seperate scripts, 1 to recruit and 1 to change the class, for instance Atton, who you add but can only have as a defferent class at a later date?
Where does the value NPC_INTEGER come from? It probably is an integer constant from nwscript, so I am wondering what object it is being obtained from, and how... I would think it would need to be something along the lines of
Code:
int iNPC = GetSomeInfoFromObject(oNPC); This function compiles for me all the time ;)
I believe that what you posted is correct, so really I am asking for further enlightenment
Last edited by Qui-Gon Glenn; 01-12-2012 at 03:08 PM.
THANKS SOOO MUCh! Im sure many people will find this helpful, i get it. Your a true master JC
Quote:
Originally Posted by Qui-Gon Glenn
Great post JCarter426!!
At first reading, I was wishing there were a link to a tutorial somewhere... then realized I was reading one! Nicely done
No problemo and thanks. As I said it's not that complicated... and I've been messing around with this stuff for a while.
Quote:
Originally Posted by DarthJango/Weasley
Will this still work if I have 2 seperate scripts, 1 to recruit and 1 to change the class, for instance Atton, who you add but can only have as a defferent class at a later date?
Not sure what you mean exactly... if you want to split it up into separate scripts, yes, just duplicate it and remove what isn't necessary from each part. For example:
Code:
void main() {
//Define everything
object oNPC = GetObjectByTag("mission", 0);
int iNPC = NPC_MISSION;
//Recruit the NPC
AddAvailableNPCByObject(iNPC, oNPC);
SetNPCSelectability(iNPC, 1);
//Bring up the party selection GUI, force the new NPC, and prevent any further changes
SetAreaUnescapable(1);
ShowPartySelectionGUI("", iNPC, -1);
}
Code:
void main() {
//Define everything
object oPC = GetFirstPC();
int iClass = CLASS_TYPE_JEDISENTINEL;
//Bring up the party selection GUI, force the new NPC, and prevent any further changes
SetAreaUnescapable(1);
ShowPartySelectionGUI("", iNPC, -1);
}
But you can't change an NPC's class... as I mentioned earlier. If you mean the multiclass to Sentinel... what you posted (and I recreated) multiclasses the player, not Atton or anyone else, so you'd have to change the object for that. I think I'm just misunderstanding you though.
Also, I forgot to mention, with any recruitment you should remove the NPC you're replacing if they're already in the party - RemoveAvailableNPC(iNPC) - and remove the possibility of recruiting them if they're not.
Quote:
Originally Posted by Qui-Gon Glenn
Where does the value NPC_INTEGER come from? It probably is an integer constant from nwscript, so I am wondering what object it is being obtained from, and how... I would think it would need to be something along the lines of
Code:
int iNPC = GetSomeInfoFromObject(oNPC); This function compiles for me all the time ;)
I believe that what you posted is correct, so really I am asking for further enlightenment
Yes, lifted from nwscript.nss. Basically the number is just the slot they occupy; the names that are defined are just added for the developers' sake - I usually just use the numbers, since I've memorized them. There are 10 slots in K1, 13 in K2 (plus 3 puppet slots). As far as I know they're just slots, space for storing information, nothing else. (Side note: it is possible to add an NPC to a slot that isn't defined, but it's severely broken because the game doesn't store any information for it. I managed to have a non-existent NPC in my party, taking up space and preventing me from adding another, despite not existing.)
There's no function for the NPC integer, though - either to get an NPC's integer, or to get the object that's assigned to an integer. I guess no one ever needed it. You can, however, spawn the object that is stored in a specified slot. For my own purposes I wrote some subroutines (for K2) to rip the integer from an object, or to generate an object based on an integer (well, expected object- it's not perfect because other NPCs can and do occupy party member slots... Trask as Bastila, B-4D4 and the Remote as Bao-Dur, recruitment mods, etc):
I used these for a script that switches the active PC to a party member. I needed to get the integer of the current PC and store it, check if who I'm turning into is available, make sure the two aren't the same, remove who I'm switching to from the party if present so the game doesn't CRASH, add the other party members back into the party (with the integer), and various other things - and give different error messages depending on the situation. Took me days to sort out all the possibilities.
Last edited by JCarter426; 01-12-2012 at 04:43 PM.
Yes, that's the only thing you can do in the game, actually. AddMultiClass automatically gives you a level of the specified class, and that becomes your active class. You still have all your previous levels, all the points you spent and so on, but any new levels are in the new class. There seems to be no way to change the class of an existing object - for example, to turn Mission into a soldier or Kreia into a Sentinel. You can do it by changing the character's UTC, of course, but it's not possible within the game. Once a character has a class, you can only add a class, and only one class (trying to add another can crash the game).
I imagine it might. I haven't tested everything, exactly. Yeah, I do test a lot of things that supposedly aren't possible, just to see what exactly is wrong with them and why. But I haven't with this, not completely. According to nwscript.nss you should be able to have three classes, but that might be left over notes from Neverwinter Nights. When I did test some stuff, a third class caused the game to crash or it replaced the second class (I think only in the case where I hasn't leveled up yet, so it didn't really exist yet).
I used these for a script that switches the active PC to a party member. I needed to get the integer of the current PC and store it, check if who I'm turning into is available, make sure the two aren't the same, remove who I'm switching to from the party if present so the game doesn't CRASH, add the other party members back into the party (with the integer), and various other things - and give different error messages depending on the situation. Took me days to sort out all the possibilities.
Most interesting... The reason why I wondered this is because at the beginning of my SERIOUS scripting adventures, something you actually helped me with once upon a time, and sadly most of the thread was lost to a website database issue. Anyways, when I was needing to RemoveEffect(xxx) from a certain NPC, I needed to find the specific effect. I found it quite frustrating that there was no way to directly "get" the value - rather I had to use a loop and use GetCurrentEffect and compare that to my desired value, else GetNextEffect rinse'n'repeat.... It got the job done but it was IMO less than ideal.
My confusion I now recognize as one of those moments... NPC_INTEGER, where INTEGER is a placeholder for the actual data, eg MISSION or ATTON. I musta drank about 15 Dr. Peppers....
Anyways, when I was needing to RemoveEffect(xxx) from a certain NPC, I needed to find the specific effect. I found it quite frustrating that there was no way to directly "get" the value - rather I had to use a loop and use GetCurrentEffect and compare that to my desired value, else GetNextEffect rinse'n'repeat.... It got the job done but it was IMO less than ideal.
Aye, I've been there myself. K2, however, does have a specific function for that. They created it for Mandalore's implant switching; the other day I successfully used to to create a permanent Force Sight and then remove it. Let me dig it up...
So basically, if you define an effect, you can remove it later in the same script. This allowed me to have the Force sigh effect carry from module to module (rather than have it at an appalling 45 seconds) and I could still deactivate it with ease.
But I have NO idea how to do it in K1, apart from the way you described... tedious but effective. Judging by what's left in nwscript, I think Neverwinter Nights had all its effects defined, with functions that can get and remove them quite easily. But of course the KOTOR effects aren't defined properly.
Speaking of effects, I've tried out a couple left over NWN ones, some of them still work. Time Stop is quite hilarious. It freezes everything in the game, and I mean everything. I might play around with it at some point, because it would be pretty cool if it worked properly.
Quote:
My confusion I now recognize as one of those moments... NPC_INTEGER, where INTEGER is a placeholder for the actual data, eg MISSION or ATTON. I musta drank about 15 Dr. Peppers....
Oh, I see. Sorry about that. But as I said, I prefer the numbers anyway. That's probably just because I love script parameters, though.
Well... Now it is time for me to hijack my own thread!
I am having an issue with my OnEnter script for the Endar Spire in the hopefully to-be-released FFK1 by jonathan7 and co.... It is probably my stupid work that is holding up the release
My original version of the OnEnter worked fine... Because it had less going on, or because I did something wrong with my .utc's... Either way, I think that I need to go in a different direction in how I achieve what we want for the mod - specifically either modifying directly the original vanilla OnEnter so that script injection is removed from the equation, or move the script to Trask's dialog...
Has anyone ever decompiled successfully the (edit!) k_pend_1b_area.ncs? DeNCS fails as I am sure there are many include files....
Essentially, I have a cluster of bad guys to spawn in, and then separately their leader. They spawn in invisible and then "uncloak" and attack when they perceive the PC. The leader is a little more complex, with a talk-fight sequence. Also, according to PC class, several items are being added to either a new footlocker or the existing one... I was having difficulty getting my new one to appear.
I will post the code I was working with... it compiles, doesn't crash the game, but nothing works properly anymore - the main sequence with the leader has somehow been broken by the new enemies and footlocker I was spawning.
As said, this code compiles fine, and the game tries to work it out, EPIC FAIL. Any glaring issues you see? Especially, why isn't the footlocker spawning?
Last edited by Qui-Gon Glenn; 01-13-2012 at 05:32 PM.
1. The script decompiled for me just fine.
2. Isn't Trask dead when you get to that area?
3. What exactly isn't working, and what is? I can see a few things that in my experience have a 50% chance of working, but if they're working then any advice wouldn't be helpful.
4. Why's it necessary to have an "if oStalker isn't valid"? If you're doing everything with the OnEnter script, he should never be valid, right?
5. "qg_pnd_1b_area" - is that a typo?
1. Huh? Whoa. Derp. Hmm... I will pm you, perhaps chat over at the Hssiss or something. I did make a typo though, in that last post it should be k_pnd_1b_area.ncs that I cannot decompile. Not sure if there is a script named k_pnd_1b.ncs
2. He is no longer in your party.... Do we really know if he dies there
Everything could be spawned in and done by the end of your first conversation with him, I think, if it were to be injected into the dialog script spots.
3. The Stalker and 2 assassins spawn in. None of them spawn in correctly except for oddly one assassin, but their spawn in is unreliable. The Stalker spawns in the correct location but is no longer invisible when the encounter should occur. There is no footlocker at all, of course that could simply be an orientation issue, although I have played with it to no avail.
4. Correct. A vestige from when I thought I might do the script differently, via a dialog or other means. This script has been re-written extensively. It can be removed
5. No.... I had the audacity to rename Bioware's vanilla script with my tag. It could be old_k_pnd 1b_area.ncs, or diggitydo.ncs.
1. Huh? Whoa. Derp. Hmm... I will pm you, perhaps chat over at the Hssiss or something. I did make a typo though, in that last post it should be k_pnd_1b_area.ncs that I cannot decompile. Not sure if there is a script named k_pnd_1b.ncs
You... you did it again.
Quote:
No.... I had the audacity to rename Bioware's vanilla script with my tag. It could be old_k_pnd 1b_area.ncs, or diggitydo.ncs.
You did it again!
But that's all I meant, it's k_pend_1b_area... make sure you're being consistent.
Quote:
He is no longer in your party.... Do we really know if he dies there
Everything could be spawned in and done by the end of your first conversation with him, I think, if it were to be injected into the dialog script spots.
Yeah but... it's a different module. If you did want to use the dialogues, you'd need Carth, since he's the only one who ever says anything there.
Quote:
The Stalker and 2 assassins spawn in. None of them spawn in correctly except for oddly one assassin, but their spawn in is unreliable. The Stalker spawns in the correct location but is no longer invisible when the encounter should occur. There is no footlocker at all, of course that could simply be an orientation issue, although I have played with it to no avail.
Ok, now, no guarantees here. I have no idea why any of these things should be so, but I've observed them to be true.
First, vectors sometimes just don't work. But in cases where they don't, waypoints usually do. My best guess is that it has to do with how much of the area is actually loaded at any given time - waypoints are spawned in when the module is loaded, so they always exist no matter what. So even if your coordinates are correct - check that first, obviously - it might not spawn anything because it doesn't register the vector as being valid. So you might have to do it another way. That doesn't mean you have to edit the module, though - there might be waypoints nearby you can use, and even if that fails, vectors might work in combination with the position of an existing object... and if that fails, you might be able to tell the NPCs to move to a better position once they are spawned... the footlocker, not so much.
Second, in a script with a switch, the game sometimes fails to assign commands to an object that was spawned in the same script. Honestly, I've changed switches to ifs in the past, absolutely nothing else, and everything worked perfectly.
Again, no guarantees. I have no reason why either of these is the way it is, but it does seem to be the way it is.
I believe you're supposed to keep the NPC tag as the tag of whoever you're replacing. So you'll have to check the original NPC for that. The NPC integers are as follows (you can paste this right into your script if you need it for reference, it won't do anything):
Code:
/*
KOTOR
int NPC_BASTILA = 0;
int NPC_CANDEROUS = 1;
int NPC_CARTH = 2;
int NPC_HK_47 = 3;
int NPC_JOLEE = 4;
int NPC_JUHANI = 5;
int NPC_MISSION = 6;
int NPC_T3_M4 = 7;
int NPC_ZAALBAR = 8;
*/
/*
KOTOR 2
int NPC_ATTON = 0;
int NPC_BAO_DUR = 1;
int NPC_CANDEROUS = 2;
int NPC_G0T0 = 3;
int NPC_HANDMAIDEN = 4;
int NPC_HK_47 = 5;
int NPC_KREIA = 6;
int NPC_MIRA = 7;
int NPC_T3_M4 = 8;
int NPC_VISAS = 9;
int NPC_HANHARR = 10;
int NPC_DISCIPLE = 11;
*/
You can use either the integer or the name (exactly as it appears) - depending of course on who you're replacing. You also might want to add the following, which will bring up the party selection screen and force the player to pick your new NPC:
Code:
ShowPartySelectionGUI("", iNPC, -1);
The "" is the name of a script to fire upon exiting, so put something in there (in the quotes) if you want to fire another script (such as a dialogue). Change the -1 to another NPC integer if you want another forced NPC. But if you're going to do this, you have to make sure the module is set to unescapable, or else fire the following as well:
Code:
SetAreaUnescapable(1);
...which will prevent you from changing party members, no matter what the area. Then once this is over, fire:
Code:
SetAreaUnescapable(0);
...which will let you change party members again. This function only affects a single module for as long as you're in it and is undone if you enter a new module, so if you're dealing with more than one you'll have to trigger it each time you enter a module - I believe this only ever happens in K2, and they do it by setting a global and then having all the modules' OnEnter scripts check that global.
So here's an example with everything, replacing Mission (because I think she's useless but feel free to change it):
Code:
void main() {
//Define everything
object oPC = GetFirstPC();
object oNPC = GetObjectByTag("mission", 0);
int iNPC = NPC_MISSION;
int iClass = CLASS_TYPE_JEDISENTINEL;
//Recruit the NPC
AddAvailableNPCByObject(iNPC, oNPC);
SetNPCSelectability(iNPC, 1);
//Multiclass to Jedi Sentinel and give items
AddMutliClass(iClass, oPC);
CreateItemOnObject("g_a_jedirobe01", oPC);
CreateItemOnObject("g_w_shortsbr01", oPC);
//Bring up the party selection GUI, force the new NPC, and prevent any further changes
SetAreaUnescapable(1);
ShowPartySelectionGUI("", iNPC, -1);
}
Ok, looking through this, shouldn't I insert a 6 somewhere there?
Alright, I've come with a scripting question today. Basically, I want to know how to make an NPC preform feats in cutscenes/dialogue. Such as on Taris when the Sith interrogator executes the Aqualish prisoner, he takes a step back and then uses power blast to kill him. Could anyone shed some light?
The truly fallen cannot return to the light. If someone "falls" and "returns," they never really, truly fell.
What you're looking for is CutsceneAttack. It's supposed to let you have complete control over the animations, attack result, and damage for each round. I have never actually managed to get it to work, but then again it's been some time since I last tried it and I've learned a lot since then. I really should try it again, but I'm busy/lazy. Anyway, here's the source code for it:
Code:
// 503: CutsceneAttack
// This function allows the designer to specify exactly what's going to happen in a combat round
// There are no guarentees made that the animation specified here will be correct - only that it will be played,
// so it is up to the designer to ensure that they have selected the right animation
// It relies upon constants specified above for the attack result
void CutsceneAttack(object oTarget, int nAnimation, int nAttackResult, int nDamage);
Here are the attack results:
Code:
int ATTACK_RESULT_INVALID = 0;
int ATTACK_RESULT_HIT_SUCCESSFUL = 1;
int ATTACK_RESULT_CRITICAL_HIT = 2;
int ATTACK_RESULT_AUTOMATIC_HIT = 3;
And the animations are in animations.2da. combatanimations.2da explains which animations go with which, in case you need it. And I'm not sure if you have to add 10000 to the animation number like you must with ActionPlayAnimation. I don't believe you do, though.
And if you want Force powers, those functions are right above CutsceneAttack in nwscript.
This is a good question, that I cannot answer fully, although I think I have a few ideas. JCarter426 is around here a bit lately, so hopefully he can fill in the gaps and give a real explanation.
I would think that there is a number in combatanimations.2da that corresponds to the power blast, and any other combat animation, right?
What number that is.... that is the difficult part. Is there a way to determine what animation actually is the power blast? Has someone already done this for us?
EDIT: Thanks JCarter426
Last edited by Qui-Gon Glenn; 01-16-2012 at 01:26 PM.
Reason: JCarter is a speedy devil
What you're looking for is CutsceneAttack. It's supposed to let you have complete control over the animations, attack result, and damage for each round. I have never actually managed to get it to work, but then again it's been some time since I last tried it and I've learned a lot since then. I really should try it again, but I'm busy/lazy. Anyway, here's the source code for it:
Code:
// 503: CutsceneAttack
// This function allows the designer to specify exactly what's going to happen in a combat round
// There are no guarentees made that the animation specified here will be correct - only that it will be played,
// so it is up to the designer to ensure that they have selected the right animation
// It relies upon constants specified above for the attack result
void CutsceneAttack(object oTarget, int nAnimation, int nAttackResult, int nDamage);
Here are the attack results:
Code:
int ATTACK_RESULT_INVALID = 0;
int ATTACK_RESULT_HIT_SUCCESSFUL = 1;
int ATTACK_RESULT_CRITICAL_HIT = 2;
int ATTACK_RESULT_AUTOMATIC_HIT = 3;
And the animations are in animations.2da. combatanimations.2da explains which animations go with which, in case you need it. And I'm not sure if you have to add 10000 to the animation number like you must with ActionPlayAnimation. I don't believe you do, though.
And if you want Force powers, those functions are right above CutsceneAttack in nwscript.
Quote:
Originally Posted by Qui-Gon Glenn
This is a good question, that I cannot answer fully, although I think I have a few ideas. JCarter426 is around here a bit lately, so hopefully he can fill in the gaps and give a real explanation.
I would think that there is a number in combatanimations.2da that corresponds to the power blast, and any other combat animation, right?
What number that is.... that is the difficult part. Is there a way to determine what animation actually is the power blast? Has someone already done this for us?
EDIT: Thanks JCarter426
Thanks both of you.
The truly fallen cannot return to the light. If someone "falls" and "returns," they never really, truly fell.
And if you want Force powers, those functions are right above CutsceneAttack in nwscript.
Yes they are! Here is a simple way I have used to implement them in a dialog, from a node script slot... this way you can control the reaction of the NPC who is "choked" or "power blasted"...
As I said, the combat animations are in fact in the regular old animations.2da; combatanimations.2da is more like a seating arrangement. It lists all the attacks and then states which animation goes with it - hit, parry, dodge, and so on. It's entirely numbers so it can be a mess. animations.2da gives you more of a clue, but the naming scheme can seem a bit weird at first glance. The animation name is an alphanumeric code with four parts, alternating letters and numbers.
The first part corresponds to the attack type - a generic attack, a feat, or a monster attack. There also seems to be some attempt to divide it into ranged and melee, but I can't discern it entirely.
Code:
b - ranged
c- melee
f - feat
g - generic
m - monster
Next, it's divided into weapon type as well as whether the character wielding one or two. These are given abbreviations for K2 only.
Code:
0 - N/A - droid
1 - SB - stun baton
2 - SS - single saber
3 - 2HS - two-handed saber (double-bladed)
4 - DS - dual sabers
5 - SB - single blaster
6 - DB - dual blasters
7 - RF - rifle
8 - NT - natural attack (unarmed, I believe)
9 - HC - heavy carbine
10 - UC - unarmed, complex (K2 only)
11 - N/A - wrist launcher (K2 only)
Next, what the character is doing.
Code:
a - attack
d - damage
f - appears unused
g - dodge
n - deflection
p - parry
r - ready
w - wield
And finally, another number. In most cases this is simply a variation number; some in K2 have an additional letter, for even more variation.
So, for example, if you want a character wielding a blaster rifle to dodge, the animation would be g7g1.
Code:
g: generic
7: rifle
g: dodge
1: variation (in this case there's only one)
Now, Mr Guardian, you asked about power blast. This is where it gets complicated.
Some of these variables are limited by other variables. Parry, for instance, is only a melee occurrence. I believe this is the reason for the distinction between ranged and melee that I mentioned above. Let's look at the first part again.
1:b is used for all blaster attack animations.
1:c covers complex melee animations such as parries and clashes.
1:f is reserved for melee feats - critical strike, flurry, and power attack, as well as Force Jump.
1:m is for engaging a monster in melee.
1:g is anything else.
3:a is used for any attack.
3:d is used for any damage.
3:g is used for dodging ranged attacks.
3:n is used for deflecting ranged attacks with a lightsaber.
3:p is used for parrying melee attacks.
Because of these specifications, certain ones do not belong with certain other ones. If that's not confusing enough, the final number is not always a simple variation; what it is depends on both of the above letter slots. I'll go over the feats for you.
(I don't believe there's a separate feet for power shot.)
So, finally, a power blast animation is b*a4. The asterisk is either 5, 6, 7, or 9, depending on whether you are dealing with a single blaster, dual blasters, a rifle, or a heavy carbine.
If you're still confused, the 2DA for K2 has a description column that might help. The format is virtually the same as K1's, but of course K2 has more animations so you shouldn't go by it entirely.
Last edited by JCarter426; 01-17-2012 at 12:31 PM.
Uh..... Uh huh uh huh huh huh
I feel like Butt Head....
Now, that, that is some INFORMATION!
I have never seen that coding system explained, and therefore always ignored any of the animations labeled in such a way, wringing my hands with shame, laziness, and ignorance.
I know it's not really about scripting, but yeah, I used to ignore it all the time too. Over time I began to notice a pattern, and here we are. To make things even more confusing, there are a couple other animations that use the same scheme, in a way. The knocked down animations, for instance, are g1x1, g1y1, and g1z1. And in K2, there are multiple ready animations for lightsabers, the final number corresponding to the saber form, but I don't know if they ever finished the animations for them. By the way, I edited the last post, I forgot about Force Jump.
Last edited by JCarter426; 01-17-2012 at 12:35 PM.
Im back in the shack
Well, can someone point me in the right direction about booleons. This is my aim:
A script to check you have an item. If true, you progress to another part to the dialouge. Im sure it has something to do with booleons. I mean, how would you go about doing that. And what type of booleons can you set for deifferent scenarios?
EDIT: Also, how do you go about using the goodbye function. Can you note an example on how this is used?
Ok... I don't have time to give you a whole lot here, DJW, but the good news is TimBob12 has a great tutorial on conditional scripts that will help you here.
It is certainly possible to check if an NPC or the PC has a certain item equipped, and probably but not certain (for me) you can check if it is in the PC inventory period.
Think about the steps.
1. You need to "get" the individual in question.
2. You need to check for the item on said individual.
3. You need to return the value to the dialog to open or close the branch in question.
so, off the top of my head, and I may improve this later at a real PC with KTool, but... and I bet there is an in-game function for this so that we don't have to create one (came to me as I wrote my "name" for the conditional function, and it seemed oddly familiar):
Code:
int GetHasEquipped()
{
object oPC = GetObjectByTag(yourNPCtag);
if GetItemPossessedBy(oPC,yourItemToBeFoundtag)
return 1;
}
That might work, or something along those lines. KotOR Tool itself has a helpful script editor search window that you can just randomly type words into, like "equip" "item" "has" etc.... never know what that can bring up
As to the goodbye function... dunno... Never looked at it. Guess I'm curious though, so I will look at it. EDIT: goodbye "function". What are you referring to? is it a script in-game? There is no function in nwscript called "goodbye"
Last edited by Qui-Gon Glenn; 01-26-2012 at 01:11 PM.
I think it is something along the lines of oGoodbye, I have a feeling this might have something to do with exit script, making the character dissapear. Of coure, thers more script to it... Im intrested to work out just dissapear, no walk or anything...
EDIT
int StartingConditional()
{
int iResult;
object oW1 = GetObjectByTag("jediscout");
iResult = GetIsObjectValid(oW1);
return iResult;
}
Reading the TUT I made this, creditt to Timbob.Just to assure myself, when this script fires in the conversation it will check for "jediscout" then if true allow me the npc to say a particular line that will advance the conversation? Another note, what would I do to check if an NPC was still alive...
EDIT 2: Well, I found this...
int StartingConditional() {
return (GetGender(GetFirstPC()) == GENDER_FEMALE);
}
Yeah, || is logical OR as you found from tk's tut.... thanks tk102
I might be able to explain a use for that...
In a scenario where there were multiple ways to get to the desired outcome, acheivable by entirely different means.
Case A: Annihilate by incendiary, had to kill the girl
Case B: Overload and sabotage, the girl is your partner
Case C: Sweet talk the mayor.... but you had to rescue the girl
All three are acceptable outcomes to satisfy beginning our end-game. So,
Code:
if A || B || C
warp endgamemoduleofdoomforevernoooooooooo;
A, B and C are not simple predicates, they have && clauses built into them: (incendiary && kill girl) (overload and team up) (politics and rescue). This complexity and mixture of and's/or's allows you to evaluate a broad set of conditions in one statement.
Is that a decent explanation? I really don't know
@DJW.... Did you try playing with KTool? There is a GetIsDead(oCreature)!
as for "oGoodbye", the "o" indicates that Goodbye is an object, not a function. Further, since it has the "o" prefix, it means that Goodbye is just a nameholder for an object being used in a script. This is the script shack, I am happy to help, but please spend some time with the basic tut's!
Last edited by Qui-Gon Glenn; 01-26-2012 at 11:52 PM.
This tells you everything you need to know. oGoodbye can be any object in the kotor world - a container, a person, the PC, a computer console, etc.
Code:
oGoodbye = GetObjectByTag("n_jordin");
This is defining that oGoodbye is now assigned the value of "n_jordin", which is a tag of an NPC, I am guessing.
Code:
DelayCommand(1.0, DestroyObject(oGoodbye));
Now we understand why the object has been given this clever name "oGoodbye". Whatever object that is assigned to oGoodbye is going to be destroyed. It is going away, goodbye.
So, it could have been called, "oLaterdude", or "oGottago" or "oImouttahere" or "oDestroyme".
Please understand, oGoodbye is referring to a data type.
Ahh, I get it. Hmm, so DestroyObject destroys the o*insertrandomname* which = n_jordin. Thans for helping. Now where would I attach the fade command...
to distribute some HK51 units around the HK factory based on their behavior cores.
I just had to rewrite the code and I came up with this:
I put some comments in too to make it user-friendly.
Shows off some nice examples of how to use while loops and methods.
Show spoiler
Code:
/*If you're defining any methods, be sure you declare them up here first
*before using them in the main code.
*You can put all of the code up here if you want, but I find it easier
*to put it down below.
*/
string factWP();
//Any variables that are going to be used in more than one method, declare them here, but initialize in the method.
int nGlobal;
void main() {
/*Declare all of your variables at the top up here
*It doesn't matter what order you do them in, but
*it helps to have them in a certain order, especially
*if some are dependent on other type variables
*/
//Integer variables
int nObjectNum = 0;
int nGlobal = GetGlobalNumber("299TEL_HK51_Core");
//String variables
string sTag = "hk51_1";
string sWPName;
//Notice how sWPNum is dependent on nObjectNum existing
string sWPNum = IntToString(nObjectNum);
object oHk51cs = GetObjectByTag("hk51cs", 0);
object oHK51Object = GetObjectByTag(sTag, 0);
/*This runs a loop and keeps running through all of the objects
*in the area that fit the oHK51Object specifications.
*/
while (oHK51Object != OBJECT_INVALID){
//Always ClearAllActions() before trying to assign new actions
AssignCommand(oHK51Object, ClearAllActions());
//DelayCommands are essential to the sequencing process
//If you try to assign commands all at once, they most likely won't fire
DelayCommand(1.0, AssignCommand(oHK51Object, ActionJumpToObject(GetObjectByTag(factWP() + sWPNum, 0))));
DelayCommand(2.5, AssignCommand(oHK51Object, ActionPlayAnimation(19, 1.0, 0.0)));
/*It's often helpful to send debug information to your feedback screen so you know what's going on*/
SendMessageToPC(GetFirstPC(), factWP() + sWPNum + " is what's showing.");
//Any type of loop needs to be incremented if you want a possibility of ever exiting the loop
(nObjectNum++);
oHK51Object = GetObjectByTag(sTag, nObjectNum);
sWPNum = IntToString(nObjectNum);
//Then the loop starts over!
}
AssignCommand(oHk51cs, JumpToObject(GetObjectByTag(factWP() + "L", 0), 1));
DelayCommand(1.0, AssignCommand(oHk51cs, ActionPlayAnimation(19, 1.0, 0.0)));
}
string factWP(){
if(nGlobal == 1){
return "WP_HK51_LINE_";
}
else{
return "WP_HK51_NME_";
}
}
What's my point behind this? Well, the point is the more you know about scripting/programming, the more efficient your scripts can be. Same functionality, WAAAAY more concise.
*Notice the use of DelayCommand. You CANNOT assign multiple commands in one instance.
Fair enough again, but what if we have another Jedi join in on the Sith torture? Would we have to keep adding AssignCommand calls? No, not necessarily. Check out the following code:
For every instance of torture in void main, it will actually read the code in void torture(), substituting the parameters for whichever objects you write in! Cool huh?
Now, not ever method has to be void main() or void whatever(), you can actually write something like:
int countMyFoes()
string getMyName()
object getWeakestEnemy()
Hey again...got a problem I really can't figure out.
Now, I'm no programmer. I've never had any school or anything for programming. What I know of it is all from TSL scripting, out of necessity.
...because I want things to happen, or not happen.
What I want to happen is not have the player recieve a default lightsaber when constructing thier saber for Jedi training, but one of my custom hilt models with it's own tag/template.
I believe I have the right script for the event. k_pdan_saber16..
and when I decompiled it and looked at it I thought, "oh, brilliant. i'll just change the tag's for the string stringGLOB_4, 5 and 6.".....
Nope. Not gonna happen. You get nothing.
After messing with it and trying different things for three hours I had to stop before I started wrecking stuff.
Code:
// Globals
int intGLOB_1 = 1;
int intGLOB_2 = 2;
int intGLOB_3 = 3;
int intGLOB_4 = 4;
int intGLOB_5 = 5;
int intGLOB_6 = 6;
int intGLOB_7 = 3;
int intGLOB_8 = 4;
int intGLOB_9 = 5;
int intGLOB_10 = 6;
int intGLOB_11 = 7;
int intGLOB_12 = 1;
int intGLOB_13 = 2;
int intGLOB_14 = 3;
int intGLOB_15 = 4;
int intGLOB_16 = 5;
int intGLOB_17 = 6;
int intGLOB_18 = 7;
int intGLOB_19 = 8;
int intGLOB_20 = 9;
int intGLOB_21 = 10;
int intGLOB_22 = 11;
int intGLOB_23 = 12;
int intGLOB_24 = 13;
int intGLOB_25 = 14;
int intGLOB_26 = 15;
int intGLOB_27 = 16;
int intGLOB_28 = 17;
int intGLOB_29 = 18;
int intGLOB_30 = 19;
int intGLOB_31 = 20;
int intGLOB_32 = 21;
int intGLOB_33 = 22;
int intGLOB_34 = 23;
int intGLOB_35 = 24;
int intGLOB_36 = 25;
int intGLOB_37 = 26;
int intGLOB_38 = 27;
int intGLOB_39 = 28;
int intGLOB_40 = 29;
int intGLOB_41 = 30;
int intGLOB_42 = 59;
int intGLOB_43 = 0;
int intGLOB_44 = 1;
int intGLOB_45 = 2;
int intGLOB_46 = 29;
int intGLOB_47 = 30;
int intGLOB_48 = 34;
int intGLOB_49 = 35;
int intGLOB_50 = 36;
int intGLOB_51 = 37;
int intGLOB_52 = 38;
int intGLOB_53 = 39;
int intGLOB_54 = 41;
int intGLOB_55 = 42;
int intGLOB_56 = 46;
int intGLOB_57 = 47;
int intGLOB_58 = 15;
int intGLOB_59 = 10;
int intGLOB_60 = 5;
int intGLOB_61 = 2;
int intGLOB_62;
int intGLOB_63;
int intGLOB_64;
object objectGLOB_1;
int intGLOB_65;
int intGLOB_66;
int intGLOB_67;
int intGLOB_68;
int intGLOB_69;
int intGLOB_70;
int intGLOB_71 = 1;
int intGLOB_72 = 2;
int intGLOB_73 = 3;
int intGLOB_74 = 20;
int intGLOB_75 = 21;
int intGLOB_76 = 22;
int intGLOB_77 = 23;
int intGLOB_78 = 24;
int intGLOB_79 = 25;
int intGLOB_80 = 26;
int intGLOB_81 = 27;
int intGLOB_82 = 28;
int intGLOB_83 = 31;
int intGLOB_84 = 32;
int intGLOB_85 = 33;
int intGLOB_86 = 40;
int intGLOB_87 = 43;
int intGLOB_88 = 44;
int intGLOB_89 = 45;
int intGLOB_90 = 48;
int intGLOB_91 = 49;
int intGLOB_92 = 50;
int intGLOB_93 = 51;
int intGLOB_94 = 52;
int intGLOB_95 = 53;
int intGLOB_96 = 54;
int intGLOB_97 = 55;
int intGLOB_98 = 56;
int intGLOB_99 = 57;
int intGLOB_100 = 58;
int intGLOB_101 = 60;
int intGLOB_102 = 61;
int intGLOB_103 = 62;
int intGLOB_104 = 63;
int intGLOB_105 = 64;
int intGLOB_106 = 65;
int intGLOB_107 = 66;
int intGLOB_108 = 67;
int intGLOB_109 = 68;
int intGLOB_110 = 69;
int intGLOB_111 = 70;
int intGLOB_112 = 71;
int intGLOB_113 = 72;
int intGLOB_114 = 1;
int intGLOB_115 = 2;
int intGLOB_116 = 3;
int intGLOB_117 = 4;
int intGLOB_118 = 0;
int intGLOB_119 = 1;
int intGLOB_120 = 2;
int intGLOB_121 = 3;
int intGLOB_122 = 4;
int intGLOB_123 = 5;
int intGLOB_124 = 6;
int intGLOB_125 = 7;
int intGLOB_126 = 8;
int intGLOB_127 = 9;
int intGLOB_128 = 10;
int intGLOB_129 = 11;
int intGLOB_130 = 12;
int intGLOB_131 = 13;
int intGLOB_132 = 14;
int intGLOB_133 = 15;
int intGLOB_134 = 16;
int intGLOB_135 = 17;
int intGLOB_136 = 18;
int intGLOB_137 = 19;
int intGLOB_138 = 1100;
int intGLOB_139 = (-6);
int intGLOB_140 = (-5);
int intGLOB_141 = (-4);
int intGLOB_142 = (-2);
int intGLOB_143 = (-1);
int intGLOB_144 = 0;
int intGLOB_145 = 4;
int intGLOB_146 = 1;
int intGLOB_147 = 7;
int intGLOB_148 = 1;
int intGLOB_149 = 2;
int intGLOB_150 = 3;
int intGLOB_151 = 1;
int intGLOB_152 = 2;
int intGLOB_153 = 3;
int intGLOB_154 = 4;
int intGLOB_155 = 5;
int intGLOB_156 = 6;
string stringGLOB_1 = "bastila";
string stringGLOB_2 = "carth";
string stringGLOB_3 = "dan13_WP_council";
string stringGLOB_4 = "g_w_lghtsbr01";
string stringGLOB_5 = "g_w_lghtsbr03";
string stringGLOB_6 = "g_w_lghtsbr04";
string stringGLOB_7 = "dan_wanderhound";
// Prototypes
object sub1();
object sub1() {
object oPC = GetFirstPC();
object object3;
object object4 = GetItemPossessedBy(GetFirstPC(), "dan13_plotcrys");
SetPlotFlag(object4, 0);
DestroyObject(object4, 0.0, 0, 0.0);
int nGlobal = GetGlobalNumber("DAN_PATH_STATE");
if ((nGlobal > 0)) {
if ((nGlobal == intGLOB_148)) {
object3 = CreateItemOnObject(stringGLOB_4, oPC, 1);
}
else {
if ((nGlobal == intGLOB_149)) {
object3 = CreateItemOnObject(stringGLOB_6, oPC, 1);
}
else {
if ((nGlobal == intGLOB_150)) {
object3 = CreateItemOnObject(stringGLOB_5, oPC, 1);
}
}
}
}
if (GetIsObjectValid(object3)) {
DelayCommand(0.1, AssignCommand(oPC, ActionEquipItem(object3, 4, 0)));
}
return object3;
}
void main() {
object object1 = sub1();
ShowUpgradeScreen(object1);
}
object3 depends on what globals were set during the questioning, as you know. (intGLOB_148-150.)
Why can't I put my "pc_lghtsbr_001/002/003" tags in instead of "g_w_lghtsbr0x" and get my custom saber hilt?
Thankyou for any advice and knowledge you could bestow.
-QDJ
Last edited by Qui-Don Jorn; 01-28-2012 at 10:44 AM.