Please look at this thread for an idea as to what I would like to do. New Hybrid Saber Crystals Help Please. I am not sure this can be done with a script but if it can be and would be easier I am all for that and very interested in learning how to do it.
I should clarify I am requesting help in the form of 1) is this even possible with a script? 2) a mentor who would help me along the way and work with me on creating the script 3) if it is a good idea and you want to take over to get it posted by all means run with with but please credit me with the idea lol.
I am really new to this never totally scripted before so it could be slow going but with the right input I might surprise myself and go faster than I expect.
Last edited by bigdarthbobo; 06-17-2012 at 04:15 PM.
Here are two basic templates that should handle the job (well, two and a half); you just need to replace the stuff in quotes with the correct information, and repeat stuff as needed. The first checks if a container has the crystal you want:
You would attach this to a dialogue node... I'd do it as a player node; have the computer say "select the crystal you would like to modify" and then you choose one from the list it gives you, conditional script attached to each node. Then the next node gives you the list of which ones you can blend it with, in a similar fashion.
Now, for K1 you would have to create a different conditional script for every crystal. It would just be copy/paste work, put in a different tag. With K2 you wouldn't have to do this, though; you could create a universal script:
Then you would just have to enter the appropriate tag in the string parameter of each dialogue node.
You might also want to have different conditionals, like "there aren't any crystals" or "a foreign object is present". That would be a bit more complicated.
The second script destroys two crystals and then creates a new one:
It could be converted to delete three, four, and so on; just duplicate the string sTag, object oCrystal, and ActionTakeItem lines, and adjust the information as required.
Now, I have a conundrum of my own. I was working on a script and I thought an efficient way to do it would be to use a switch for the string parameter. However, I wasn't sure if this is possible. I believe I've seen it done before, but I couldn't find anything by searching. I eventually did it with if trees instead... it was probably easier with ifs, actually. But I'm still curious. I believe it should look something like:
Code:
case "whatever":
...but you know how the engine is. Anyway, just curious... not a big deal. If any of you remember seeing something like this, just let me know.
Alright, so I've come here with an on enter script filled with conditionals. Now my only problem with this script while compiling, at least so far, is that I keep getting syntax errors at the && symbols in lines 52, 78 and 103, or all the lines I've put in red. I believe it has something to do with the parentheses on the ends of each line but I'm not entirely sure. Could anyone please help?
(The commented out lines with stars in them are there to help me keep track of what's happening in the script.)
Code:
#include "k_inc_debug"
#include "k_inc_utility"
void main()
{
//***** DEFINING THE OBJECTS *****\\
object oPC = GetFirstPC();
object oHound = GetObjectByTag("g_hound01");
object oCantDoor = GetObjectByTag("d_654_dor01");
object oSwooper = GetObjectByTag("swoopmcx01");
//***** DEFINING THE CONDITIONAL CHECKS *****\\
int ncheck = GetGlobalNumber("dt_num01");
int iResult = ((GetGlobalBoolean("dt_check01")));
int iResult2 = ((GetGlobalBoolean("dt_check02")));
int iResult3 = ((GetGlobalBoolean("dt_check03")));
int iResult4 = ((GetGlobalBoolean("dt_check04")));
//***** BEGINNING CONDITIONAL FOR SPAWN *****\\
if (!GetLocalBoolean(OBJECT_SELF, 40) && (GetEnteringObject() == GetFirstPC())) {
if (ncheck != 5)
{
SetLocalBoolean(OBJECT_SELF, 40, TRUE);
vector cPosition=Vector(29.7199993133545,-32.4500007629395,0.06339);
location lHound=Location(cPosition,175.01396);
object oCre = CreateObject(OBJECT_TYPE_CREATURE, "g_hound01", lHound);
}
}
//***** CONDITIONAL FOR NEVER TALKING *****\\
if (iResult == TRUE) && (!GetLocalBoolean(OBJECT_SELF, 41) && (GetEnteringObject() == GetFirstPC())) {
DestroyObject(oHound);
SetLocalBoolean(OBJECT_SELF, 41, TRUE);
//***** CONDITIONAL FOR CHECKING IF PC ENTERED IN FROM CLOSE TO CUTSCENE POINT *****\\
if( GetDistanceBetween(oCantDoor, oPC) <= 5.0 ) {
AssignCommand(oSwooper, ActionStartConversation(oPC, "dt_man_dist"));
}
//***** CONDITIONAL FOR DID NOT ENTER THE AREA CLOSE TO CUTSCENE POINT*****\\
if( GetDistanceBetween(oCantDoor, oPC) > 5.0 ) {
SetGlobalBoolean(dt_304_trig, FALSE);
}
}
//***** CONDITIONAL IF THE PC TOLD PERSON TO LEAVE *****\\
if (iResult2 == TRUE) && (!GetLocalBoolean(OBJECT_SELF, 42) && (GetEnteringObject() == GetFirstPC())) {
DestroyObject(oHound);
SetLocalBoolean(OBJECT_SELF, 42, TRUE);
//***** CONDITIONAL FOR CHECKING IF PC ENTERED IN FROM CLOSE TO CUTSCENE POINT *****\\
if( GetDistanceBetween(oCantDoor, oPC) <= 5.0 ) {
AssignCommand(oSwooper, ActionStartConversation(oPC, "dt_man_hap"));
}
//***** CONDITIONAL FOR DID NOT ENTER THE AREA CLOSE TO CUTSCENE POINT*****\\
if( GetDistanceBetween(oCantDoor, oPC) > 5.0 ) {
SetGlobalBoolean(dt_304_trig, FALSE);
}
}
//***** CONDITIONAL IF THE PC WANTED IT DONE BUT TOOK TOO LONG *****\\
if (iResult3 == TRUE) && (iResult4 == TRUE) && (!GetLocalBoolean(OBJECT_SELF, 43) && (GetEnteringObject() == GetFirstPC())) {
DestroyObject(oHound);
SetLocalBoolean(OBJECT_SELF, 43, TRUE);
//***** CONDITIONAL FOR CHECKING IF PC ENTERED IN FROM CLOSE TO CUTSCENE POINT *****\\
if( GetDistanceBetween(oCantDoor, oPC) <= 5.0 ) {
AssignCommand(oSwooper, ActionStartConversation(oPC, "dt_man_sdlor"));
}
//***** CONDITIONAL FOR DID NOT ENTER THE AREA CLOSE TO CUTSCENE POINT*****\\
if( GetDistanceBetween(oCantDoor, oPC) > 5.0 ) {
SetGlobalBoolean(CC_207_TRIGGER, FALSE);
}
}
}
The truly fallen cannot return to the light. If someone "falls" and "returns," they never really, truly fell.
EDIT: It compiles! Thanks JC. Now to see if it works in-game...
Doesn't look like you use an addition () around the whole function... so
if (iResult == TRUE) && (!GetLocalBoolean(OBJECT_SELF, 41) && (GetEnteringObject() == GetFirstPC())) {
In theory that should work, but I find it easier to use a line for each part of the condition. Makes adding, changing, and removing them a lot easier, as well as detecting errors.
I generally prefer it all in one line, makes it easier to go through scripts if containing a lot of code, and easier to see what's wrong if the compiler gives a line error.
But since both work fine, it's really just a matter of preference...
I generally prefer it all in one line, makes it easier to go through scripts if containing a lot of code, and easier to see what's wrong if the compiler gives a line error.
The debugger is sometimes pretty vague about what's wrong, though. In Fallen Guardian's case, it probably just said "syntax error at &&" or whatever, and since there are a handful on those lines, figuring out what's wrong is that much harder. If you have every condition on a different line, then you get more useful data - it would flag all of them.
Well, I'm back. And with a scripting problem. I'm doing a request that requires adding the items to the locker on the Endar Spire. I edited the k_inc_end.nss script, which details the Endar Spire, and when I compile it with KT, saving it as k_inc_end.ncs, it compiles, but there's no output file. I try it with HazardX's compiler, and it's an include file and becomes ignored. The specific parts of code I added were these:
Before you ask, yes I have the tags correct, the files in the override, and yes they all work in-game. But I can't find a solution. Nothing else has been modified, so it's not a capitalization error. It is an include file, but in what should I include it? Thanks for the help in advance guys.
EDIT2:I read this thread about compiling scripts, and discovered that the "_CompileAll.bat" file included in HazardX's compiler download is faulty, at least for me. I copied down the code in the thread linked above and made my own "Compile.bat" It worked, but the script didn't. I ended up slagging the above script and used this one instead:
Well, you need the semicolon. Every command has to end with a semicolon. However, you're also missing a close parenthesis.
Hmm. I'm afraid I can't be of much help, because I've never messed around with k_inc_force. Frankly I don't like including scripts, generally; too easy to mess things up. The amount of work including saves is countered by the amount of work it takes to get it to work. So the only thing I can suggest is you look at k_inc_force and make sure you've done everything right; if I had to guess, I'd say the first P in "Sp_RemoveSpellEffectsGeneral" has to be capitalized.
As for VFX_IMP_BATTLE_MED_III, I'm not entirely sure what's going wrong there, but you can easily resolve it by looking at visualeffects.2da and finding the actual line number of VFX_IMP_BATTLE_MED_III and input that in its place.
Just thought that you might like to know, I finally revisited this script, and spent the last few hours pouring over this conversation and NWNLexicon(which is VERY helpful), and managed to get the script to work. Here's the code:
Had to change a few things, like the visual effect entirely, but oh well. The only issue, which I'm happy to overlook at this time, unless you know how to correct it, is that the script increases your base CON by 30 and reduces your base CON by 9, as opposed to what the intention was.
I'm just guessing, but it might be hard coded to round. I'd suggest testing a few different numbers to see if there's a pattern.
I tried by adjusting it to 20 CON increase, and 18 CON decrease, on account of how far it was off to either side, and nothing. I tried something outrageous like 60 CON increase and 40 CON decrease, and nothing. Could it be Spells.2da?
Here's the line(Whatever info I skip is ****):
Code:
Row:177
Label:FORCE_POWER_LAST_STAND
name:49332
spelldesc:49333
good/evil:-(neutral)
usertype:1(same as cure, valor,etc.)
guardian,consular,sentimel,inate:15
maxcr:6
range:P
using "ip_ lightning"
script is correct
conjtime and anim are the same as everything else.
casttime and anim are the same as everything else.
castsound is default.
Everything else is the same, except "Forcefriendly"is 27, to make it in it's own row in the level-up gui.
And "pips" is 1(though who knows what the pips have to do with anything.)
Well, I've determined that your CON will never drop below 3. Probably hard coded. So if you have a CON of 12, it will only decrease it by 9. I also believe invulnerability makes you immune from CON decreases, but not CON increases. I really should turn it off... it screwed up other test results in a similar manner just yesterday.
However, I've reported no problems regarding CON increase of any kind. Here's the script I used:
Okay so I've been setting up an onenter script for one of my areas in KotOR 1 and in this area I've decided to include sitting placeables. So here's the part of the script that sets up the sitters:
Code:
int nNth = 0;
object oPlaceable = GetObjectByTag("d50ab_sitter",nNth);
while (GetIsObjectValid(oPlaceable))
{
AssignCommand(oPlaceable,ActionPlayAnimation(ANIMATION_PLACEABLE_ANIMLOOP01));
nNth++;
oPlaceable = GetObjectByTag("d50ab_sitter",nNth);
}
Now the issue is only one of the placeables will actually sit down, the other just stands there in the default model pose with its arms stretched out. Now I'm thinking this may have to do with the nNth but I copied this code straight from Manaan, where'd they'd set up multiple sitters.
The truly fallen cannot return to the light. If someone "falls" and "returns," they never really, truly fell.
That's the same problem I ran into on the first page. I'll quote to save you the trouble of going back:
Quote:
Originally Posted by JCarter426
My problem was that one NPC seemed to be excluded 95% of the time, which I resolved by using GetNearestObjectByTag rather than GetObjectByTag, which is screwy... clearly why GetNearestObjectByTag exists. However, GetObjectByTag does recognize 0, and inputting 0 doesn't immediately crash the game. So there's that.
Apart from that, there are three things that could be wrong. First, make sure you got the template right. I know, I know... but you wouldn't believe how much time I've wasted before noticing a typo. Second, make sure the coordinates are correct, particularly the Z value. It could be spawning in some part of the module you can't see, like below. Finally, if those two are correct, then I'd blame it on the vector. I've found them to be particularly unreliable, and I can only suggest to find a way to do it without using one, such as spawning near something that's already in the module.
Or you could make a waypoint in the GIT, and make the waypoint's location the location of your vector. Then grab that waypoint's location via the script and use it for location lCorpse. So something like this:
Or you could make a waypoint in the GIT, and make the waypoint's location the location of your vector. Then grab that waypoint's location via the script and use it for location lCorpse.
Well, if you're going to edit the module, you could just put the placeable in it that way.
Quote:
Also, JC, it appears that my script works it's just that SittingSelkath placeable does not.
Ah well... that would explain it. Nothing I can do about that, I'm afraid. I take it the Selkath don't have the regular sitting animation?
In place of the orange text, you could add anything you want. I think this script would be ideal for certain force powers, and also it could be quite useful in convos...
This should do the same as the above... well, not entirely as I'm not sure what all your ifs are checking, but it will heal the whole party by nHealCount:
Code:
int i;
int n = ( GetPartyMemberCount() - 1 );
for( i = 0; 0 <= n; i++) {
ApplyEffectToObject(0, EffectHeal(nHealCount), GetPartyMemberByIndex(i));
}
I really hate repeated lines of code.
Rather than checking how many party members there are and then doing different functions depending on that, and then applying it to each party member... this simply does one thing to every party member, repeating until there aren't any left.
This should do the same as the above... well, not entirely as I'm not sure what all your ifs are checking, but it will heal the whole party by nHealCount:
Show spoiler
Code:
int i;
int n = ( GetPartyMemberCount() - 1 );
for( i = 0; 0 <= n; i++) {
ApplyEffectToObject(0, EffectHeal(nHealCount), GetPartyMemberByIndex(i));
}
I really hate repeated lines of code. :xp:
Rather than checking how many party members there are and then doing different functions depending on that, and then applying it to each party member... this simply does one thing to every party member, repeating until there aren't any left.
Then I guess people will have to decide which one to use. The reason my code has repeated lines is because I wanted the same action all around, but if this were you used in dialogues, people might want to make dynamic options, so it still has a purpose.
EDIT: And my code
if(GetPartyMemberCount() == 3)
{
if(GetCurrentHitPoints(GetPartyMemberByIndex(0)) < GetMaxHitPoints(GetPartyMemberByIndex(0)) && nHealCount > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealCount), GetPartyMemberByIndex(0));
}
if(GetCurrentHitPoints(GetPartyMemberByIndex(1)) < GetMaxHitPoints(GetPartyMemberByIndex(1)) && nHealCount > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealCount), GetPartyMemberByIndex(1));
}
if(GetCurrentHitPoints(GetPartyMemberByIndex(2)) < GetMaxHitPoints(GetPartyMemberByIndex(2)) && nHealCount > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealCount), GetPartyMemberByIndex(2));
}
}
else if(GetPartyMemberCount() == 2)
{
if(GetCurrentHitPoints(GetPartyMemberByIndex(0)) < GetMaxHitPoints(GetPartyMemberByIndex(0)) && nHealCount > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealCount), GetPartyMemberByIndex(0));
}
if(GetCurrentHitPoints(GetPartyMemberByIndex(1)) < GetMaxHitPoints(GetPartyMemberByIndex(1)) && nHealCount > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealCount), GetPartyMemberByIndex(1));
}
}
else
{
if(GetCurrentHitPoints(GetPartyMemberByIndex(0)) < GetMaxHitPoints(GetPartyMemberByIndex(0)) && nHealCount > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nHealCount), GetPartyMemberByIndex(0));
}
}
The very first 'if', along with the 'else if' and the 'else' checks how many people are in the party. The set of 'ifs' in the conditionals check to see if a person has less than their maximum health, and if so heals them for nHealcount. If their current and maximum health points are the same, nothing happens. I used this bit of code to heal the entire party with death field instead of just the PC, as part of a mod request I picked up.
Last edited by Fair Strides 2; 09-15-2012 at 10:12 PM.
Reason: add-on
It does heal them if they have max VP, but for 0 points and then you get the floating green zero and a report in the feedback screen. You might not want that in some situations.
Okay, so I'm making a script for KotOR II to work in the onEndRound field for a character. Basically, this would make it so that every time you're in combat, and someone is currently attacking you, then you get a decrease to your attack stats and accuracy (dexterity). But, if you're in combat and no one is attacking you, then you get a bonus to your to your attack stats and accuracy (dexterity). And if you're not in combat, it returns your stats to their normal state. What I would like to know is if this script is actually set up correctly to do that, and if there are any holes in my scripting.
It does heal them if they have max VP, but for 0 points and then you get the floating green zero and a report in the feedback screen. You might not want that in some situations.
Aaaaaaaah, I hadn't considered that.
Quote:
Originally Posted by Fallen Guardian
Okay, so I'm making a script for KotOR II to work in the onEndRound field for a character. Basically, this would make it so that every time you're in combat, and someone is currently attacking you, then you get a decrease to your attack stats and accuracy (dexterity). But, if you're in combat and no one is attacking you, then you get a bonus to your to your attack stats and accuracy (dexterity). And if you're not in combat, it returns your stats to their normal state.
All right, interesting premise.
Quote:
What I would like to know is if this script is actually set up correctly to do that, and if there are any holes in my scripting.
All right, first thing that comes to mind is ClearAllEffects might clear stuff you don't want cleared. There are a few ways to get around that, though.
Second thing that comes to mind is these are permanent effects but the OnEndRound script fires every three seconds during combat. This would lead to a slippery slope, with more and more bonuses or penalties applied until they're ridiculously high or low in a matter of seconds. Change those duration types to temporary and set a duration of three seconds and you should be fine.
Third thing is I'm not sure if OnEndRound ever fires if you aren't in combat, so the reset might never happen. I could be wrong though.
Last thing is GetGoingToBeAttackedBy. The notes say not to use it. But maybe it works like it seems.
I'm trying to invent a 'smart script' to automatically heal yourself(Here I mean your companion to auto-heal themselves), but it doesn't do anything at all in-game. The script is K1, though if it ever works, I'll adapt a TSL version:
EDIT: I'll expand and explain the script. Sorry for not doing so earlier.
This script is to be placed inside, or related to, the heartbeat script. It is supposed to check if you meet the prerequisites for the force power cure and then checks if you have the advanced form, Heal, and if yes, it casts it; if you don't have Heal, it casts cure.
IF you don't have either power, it embarks on a jpourney to see if you have a medpac, then an advanced medpac, and finally a lifepack. If one of the tiers of healing items returns false, the script will use the previous tier item, or if tier one fails, nothing happens.
I might also mention that all of this only happens if you have less than half your max health(I hope I set that part up right with
"
int CHEALTH = GetCurrentHitPoints(oPC);
int MHEALTH = GetMaxHitPoints(oPC);
MHEALTH/2;
while(CHEALTH < MHEALTH)
").
Last edited by Fair Strides 2; 09-30-2012 at 09:29 PM.
Reason: Expansion
// 383: Force the action subject to move to oMoveTo.
void ActionForceMoveToObject(object oMoveTo, int bRun=FALSE, float fRange=1.0f, float fTimeout=30.0f);
You shouldn't have to use SetCommandable() as creatures are always set to commandable by default, and it doesn't affect movement anyway. All it affects is whether the character can queue actions; setting it to false is essentially stunning them without the stun effect. Since you haven't done that (I think) you can ignore it.
It might not just be the door. That sort of thing largely depends on the area, though I've never really had any problems with it, guess I've just been lucky. You could try opening the door earlier, or maybe commanding the NPC to go to the door, then to the player.