Note: LucasForums Archive Project
The content here was reconstructed by scraping the Wayback Machine in an effort to restore some of what was lost when LF went down. The LucasForums Archive Project claims no ownership over the content or assets that were archived on archive.org.

This project is meant for research purposes only.

Exile Detection?

Page: 1 of 1
 HouseOfAmon
08-29-2006, 1:12 AM
#1
Is it possible to detect the exile, I need to be able to return some sort of reference to him/her in a script, I remember seeing his/her npc number is -1, but have yet to find a function that can return that value for me..

Then again, I have only looked through nwscripts.nss, it may be in an include file. Any good include files I should look into for good functions..

Or is there a tag for him/her, I didnt see it in npc.2da..

So any function to return npc numerical values would be excellent, I am pretty sure he is -1... Or a tag, or any way to get the exile as a return value..

Short of eliminating all the other npcs, and assuming its him.. I am stumped..

Srry bout all the constant questions, I promise I almost got this scripting thing down..
 Mav
08-29-2006, 1:22 AM
#2
Srry bout all the constant questions, I promise I almost got this scripting thing down..I'm sorry I can't help you with scripting, it's like trying to read Chinese upside-down and drunk to me, honestly I've read through all the tutorials, but I think scripting for me is something that someone would have to sit down and teach me. As far as asking too many questions, thats not possible, essentially that is why the forum is here in the first place. Oh and btw, I finally got a chance to play through your lightsaber on/off mod, really cool, well done.
 HouseOfAmon
08-29-2006, 2:05 AM
#3
I'm sorry I can't help you with scripting, it's like trying to read Chinese upside-down and drunk to me, honestly I've read through all the tutorials, but I think scripting for me is something that someone would have to sit down and teach me. As far as asking too many questions, thats not possible, essentially that is why the forum is here in the first place. Oh and btw, I finally got a chance to play through your lightsaber on/off mod, really cool, well done.

Scripting aint too bad, but I guess thats opinion, really, for me its modeling/texturing, now thats some hard stuff, I am lucky to draw a smiley face in mspaint.. :)

I dont know how some of you make such awesome textures, and stuff, and modelling can be frustrating, I once modeled a pistol, it took me forever, and it still kinda sucked..

Glad you liked the mod, thats what I am working on atm, I have got most of what I want for the next update done, but I really want to take some time and sort the on/detection problem,..

So thats why I need this function.. I need some small and fast, so it doesnt lower response time between on/off states.

Well anyways.. I guess I will get back to work on it.. later Mav...
 oldflash
08-29-2006, 2:33 AM
#4
Depending of what you need to do there are few ways to get Exile ID.

If (GetTag(oObject) =="") //this will be TRUE only if oObject is Exile

I was use another way in one of my scripts. I put a unique hideitem on exile. In this way I was able to locate Exile whatever it was. But sometimes that item is go to inventory and need to be equipped.
That will be easy to do with a hearbeat script by checking script owner and hideitem status.
Exile's heartbeat script: k_hen_heartbt01.nss

// k_hen_heartbt01.nss
#include "k_inc_switch"
void main()
{
object oPC = OBJECT_SELF;
if (GetTag(oPC) == "")
{
//this part will be e executed only be Exile
// your code here

}

ExecuteScript("k_ai_master", OBJECT_SELF, KOTOR_HENCH_EVENT_ON_HEARTBEAT);
}
 HouseOfAmon
08-29-2006, 2:43 AM
#5
Thanks, I think the first one will work...

I need to detect who used the item/executed the script, its the old armband/spells.2da impact script trick,..

I need to know what party member exactly executed the script.. that way the right global variable can be set.. I have one for each npc in the party.. :)

So its like this?


void main()
{

object oPC=GetPartyMemberByIndex(0);

if (GetTag(oPC == ""))
{
Set Exiles Global.. Right.. ?? Yeah, it sounds good to me..
}

}


BTW, can I stick other function directly in the if like that... I had thought I had to declare that outside the if, then use a variable to pass it in..

Example..

object oPC=GetPartyMemberByIndex(0);
object tPC=GetTag(oPC);

if ( tPC == (oPC==""))
{
}


This is how I have been doing stuff, but if I can pass functions straight to the if statement that would save me a lot of time.. :)

Another thing, in nwscripts, I believe it said passing strings to globals was not allowed, can i do this, it would make my script a little easier..
 oldflash
08-29-2006, 3:30 AM
#6
...
Not really.
GetPartyMemberByIndex(0) is same as GetFirstPC()
To get this working right take

void main()
{

//object oPC=GetPartyMemberByIndex(0);
object oPC = OBJECT_SELF

if (GetTag(oPC == ""))
{
Set Exiles Global.. Right.. ?? Yeah, it sounds good to me..
}

}


Second code is a little wrong

object oPC=GetPartyMemberByIndex(0); // get Atton's ID
// object tPC=GetTag(oPC); // GetTag returns string not object
string sPC=GetTag(oPC)

// if ( tPC == (oPC=="")) // not valid if
{
}


Also you should be carefull with those "GetObject"
Example:

object oItem = GetObjectByTag("item_tag");
object oCheck = GetItemInSlot(4, OBJECT_SELF);

if (oPC == oCheck)
/* this is executed in 2 cases:
case 1: both objects are valid (object oItem is identic with object from right hand of script owner)
case 2: both objects are invalid (oItem does not exist in area and script owner has empty hands)
Always check what function returns in case of invalid tag or object
("Returns OBJECT_INVALID if the object cannot be found.")
*/
 HouseOfAmon
08-29-2006, 5:41 AM
#7
Yeah, I misused the object data type, I realised like 5 minutes after posting it, I stopped, and was like, wait a minute.... Thats a string... duh..
 oldflash
08-29-2006, 6:05 AM
#8
Still don't know what do you want to do.
Check for combat mode:

// 320: * Returns TRUE if oCreature is in combat.
//RWT-OEI 09/30/04 - If you pass TRUE in as the second parameter then
//this function will only return true if the character is in REAL combat.
//If you don't know what that means, don't pass in TRUE.
int GetIsInCombat(object oCreature=OBJECT_SELF, int bOnlyCountReal = FALSE);

If you want to control lightsaber state when PC is not in combat you should use heartbeat script k_hen_heartbt01 (this is executed by all party members at every 6 seconds)
Few checks and few settings should work.
Check if OBJECT_SELF is partymember
Check if OBJECT_SELF has lightsaber in slot 4 (it works with any lightsaber type)
check slot5 (offhand) for lightsaber
Check lightsaber status
Check the LightsaberStatusMark
Set lightsaber in slot4 on/off
set lightsaber state for slot5

But, like I say, I'm not sure what you intend to do.
 stoffe
08-29-2006, 6:24 AM
#9
Some script functions that might be worth remembering when working with the player party:
GetPartyMemberByIndex(0) returns the character the player is currently controlling.


GetPartyLeader() works the same as the above, returning the character the player is currently controlling (i.e. isn't AI controlled).


GetFirstPC() returns the main character. In all parts of the game where the Exile (or Revan in KotOR1) is present a reference to her object will be returned by this function. For areas where the player made character is not present this function will return the first character added to the party (i.e. the one you picked to lead the expeditions on G0T0's yacht or the Dxun Tomb). On the solo adventures of T3, Atton and Mira a reference to that character's object is returned by this function. Note that this is not identical to the character the player currently controls. Also note that this does not return a valid object if run in a OnModuleLoad script, since the player does not exist in the game world while a module loads.


GetIsPlayerMadeCharacter() returns true if the object reference set as parameter is the character you created at the start of the game, i.e. the Exile in TSL. This can be used like if (GetIsPlayerMadeCharacter(GetFirstPC())) { ... } to check if the Exile is currently in the party (i.e. if GetFirstPC() is the Exile).


As oldflash mentioned the Exile and Revan have a blank string as Tag, which can be checked for like any other tag. I.e. GetObjectByTag("") would return a reference to the Exile's object.


IsObjectPartyMember() returns TRUE if the object reference set as parameter is an active member of the player's party.
 HouseOfAmon
08-29-2006, 6:57 AM
#10
Thank you both,..

@Stoffe, a few of those commands might be just what i need, I was doing those functions by creating them through other functions.. Too bad I didnt know about them till after I coded ten miles worth of script, but I might just rework it for simplicity.. So thanks..

@oldflash, Well you asked, so I will answer, hope you got some time though..

Let me explain, I made a mod, the mod lets you turn your lightsaber on, and off at will, this works through a custom baseitem I made, it then when activated links to spells.2da, and runs and impact script...

This script originally would just turn on the lightsaber via SetLightsaberPowered for whoever was in the first position, and set global SPower to 1 for ON, and if the item was activated again, it would set SPower to 0 for OFF..

The problem lies in switching npc's, it obviously would still be set to OFF, even though the variable says ON, so what I am trying to do, is build an intricate tracking system, it tracks, who is currently in your party, and who is the party leader.. As far as I know you can onlly change npc's in one way, so the flow is always the same, exile, npc1, npc2, then npc1, npc2, exile, etc...
correct..

Since I can predict the scroll order of npc's, what I need is for my script to detect on each run who is the person that ran it(index(0)), and who else is in the party, and their positions..

Then I have to set the globals, SPower, SPower1, SPower2, to each npc's relative saber state on/off...

I then store all this information to globals, who was the last person to use the item, and who was in the party, and where they were by index..

So what should happen when it runs next, is it gets all this party info again, and cross checks it against the values stored in the global variables, to see if the party has changed since it was last used, if the party has changed, it checks to see if there are new party members, or if the change was just an index change...

So after this, it will readjust the globals SPower, SPower1, SPower2, accordingly...

Example..

First Run....
----------------
Exile Index 0
Mira Index 1
HK Index 2

SPower 1
SPower1 0
SPower2 1

Next Run
-----------
Mira Index 0
HK Index 1
Exile Index 2

Here is what the script does.. In theory..

SPower 0
SPower1 1
SPower2 1

======================

So it keeps the npcs index, matching the saber state, that way it should always turn On, when you turn it ON, or Off, when you turn it OFF..

Another thing it does, is if a new party member has been added, it will set the respective global to 0, since their saber would be OFF... And the same goes for removing NPC's, it will set the proper global to 0....

So in essence its a bug fix for the v1.2 update to my lightsaber on/off switch mod...
 oldflash
08-29-2006, 7:18 AM
#11
From here I think Stoffe (script master!!!) can help you more than I do.
I may be wrong but does very item has a local bolean?
You can use that to set state for a lightsaber mo matter which one use that item.
Other thing is to use k_hen_heartbt01 for do all this job but take care and restrict script for partymember only

if (IsObjectPartyMember(OBJECT_SELF) do things;

This script is executed by all partymembers (except droids I think). So when you add a new partymember in max 6 sec it will be checked for lightsaber state.

However, I'm a n00b when it comes about boleans, globals and dark magic.

If you have new entry in baseitem.2da for a custom lightsaber that will not respond to forcejump. http://static.lfnetwork.com/lucasforums.com/images/icons/icon4.gif)
 HouseOfAmon
08-29-2006, 7:39 AM
#12
Umm, dont know.. I think I am doing it about the only way possible, there might be better functions, but I honestly don't see any other way to do it, for what I need to happen.. :(

I was just hoping I guess, but I am pretty close to cracking this mystery, maybe Stoffe will come to the rescue, :) Stoffe has always helped me through the rough spots.. Truly is one of the smartest ppl here, I swear, so yeah, script master is good title... hehe..

And this is the hardest thing I have ever tried to do, ever.. And I did some crazy scripts for morrowind, max payne.. This tops em all.. ;)

Oh, well thanks to you both, hopefully I will figure something out, there is just so much going on in the script, its hard for me to keep my train of thought straight, I have to know what every variable, every value is going to be, and direct the tide of information where I need it to be, when I need it to be there, so to speak... :)

Looks like a job for some SendMessageToPC Debugging.. hehe..

Well back to work... Peace..
 stoffe
08-29-2006, 7:52 AM
#13
If I understand correctly what you wish to happen, something like the example below might work as impact script for the activatable item property:

void main() {
object oItem = GetItemInSlot( INVENTORY_SLOT_RIGHTWEAPON , OBJECT_SELF);
if (GetIsObjectValid(oItem)) {
int iTypeR = GetBaseItemType(oItem);
int iTypeL = GetBaseItemType(GetItemInSlot( INVENTORY_SLOT_LEFTWEAPON , OBJECT_SELF));
if ((iTypeR == BASE_ITEM_LIGHTSABER)
|| (iTypeR == BASE_ITEM_DOUBLE_BLADED_LIGHTSABER)
|| (iTypeR == BASE_ITEM_SHORT_LIGHTSABER)
|| (iTypeL == BASE_ITEM_LIGHTSABER)
|| (iTypeL == BASE_ITEM_DOUBLE_BLADED_LIGHTSABER)
|| (iTypeL == BASE_ITEM_SHORT_LIGHTSABER))
{
int bPowered = GetLocalBoolean(OBJECT_SELF, 115);
SetLightsaberPowered(OBJECT_SELF, TRUE, !bPowered, TRUE);
SetLocalBoolean(OBJECT_SELF, 115, !bPowered);
}
}
}


This uses a local boolean (index 115) set on the character using the armband instead of globals, to allow them to keep track of the state of their saber themselves.

It checks if the character has a lightsaber equipped and if that's the case it toggles the "Saber Powered" state of the saber every time the script is run.

The problem with this, like other solutions, is that there is no way to detect the "powered" state of a lightsaber from a script, and that the game automatically powers down the saber when the character exits combat mode regardless of how and when it was powered up. The animation state of the saber isn't saved in save games, or kept through area transitions either. Thus you'd need to "double-activate" the item if the saber was powered before such an event to get it back on.

The only way I can see getting around that is to alter the AI scripts of the party members, where the saber state LocalBoolean is checked in the OnSpawn script and the saber is powered appropriately (when transitioning to a new area or loading a savegame), and the heartbeat script to re-power the saber after exiting combat mode. Personally I think it's extreme overkill to alter the generic AI scripts for such a minor cosmetic effect, but if you want to do it that's probably how it needs to be done. :)

You'd do that by adding a line like this to the OnSpawn scripts k_hen_spawn01 and k_oei_spawn:

SetLightsaberPowered(OBJECT_SELF, TRUE, GetLocalBoolean(OBJECT_SELF, 115), FALSE);


And add something like this to the heartbeat script k_hen_heartbt01:

if (!GetIsInCombat(OBJECT_SELF) && GetLocalBoolean(OBJECT_SELF, 115)) {
SetLightsaberPowered(OBJECT_SELF, TRUE, TRUE, FALSE);
}
 HouseOfAmon
08-29-2006, 9:53 AM
#14
Thanks stoffe very helpfull, and I dont need it to re-power it, or anything like that I simply need to reset the globals to 0=OFF Position, so the next time you try to power it up, it actually works.. :)

Something like this, only with real code of course..

Example
if (combat == 1)
{
Set my global 0
}

if (area change)
{
set my globals 0
}

As of v1.1 it will not work the first time, if you go to different areas, or enter combat, or switch npc's because its still set to 1=ON, so I am simply adding detection for all of these things.. To turn it to 0=OFF

This is one of the most annoying bugs to the mod, and I am very, very close now to fixing it. After I post the mod, you can check out the finished product, to see what it does, and how it does it.. If you want to.. If anything its an interesting look at how far you can take scripting.. ;)

Bottom line, I am a perfectionist, I had to make cuts on my influence bug fix, because of how huge(10,000+ lines estimated) it would have been if I had did it perfect, and it being on a heartbeat script, that would killed FPS, badly.. And I see a way to not do that with this mod, and keep it reasonable.. So I have to try..

Anyways, thank you both for all your help,..

Peace..
 stoffe
08-29-2006, 12:59 PM
#15
I dont need it to re-power it, or anything like that I simply need to reset the globals to 0=OFF Position, so the next time you try to power it up, it actually works.. :)

Something like this, only with real code of course..

Example
if (combat == 1)
Set my global 0

if (area change)
set my globals 0


It's the same thing, only going about it from the opposite direction. The base problem still remains; you need a script to actually run that code, and the only reliable place I can think of is the AI scripts of the characters (unless you plan to manually activate the item every time you enter combat or before transitioning to a new area). Well, I suppose you could spawn an external controller when first activating the item as well which does the checking instead of the AI scripts, though that would make it a little more complex...

(Oh, and the lightsaber is automatically turned off if the character wielding it changes what they wear in their body inventory slot as well...)

There is an alternative workaround for the transition/reload thing, but it only works as long as the character keeps the same weapon, making it less reliable since it breaks if the character switches what lightsaber they have equipped. And it still doesn't solve the problem of the saber turning off at the end of combat.

The very easiest woryaround would be to skip the "use item to turn saber off" thing entirely and only use the item to turn the saber on. All you need to do to turn it off is to hit the flourish key anyway since that puts the character into combat mode for a few seconds, which will make the saber turn off when it ends. :)
 HouseOfAmon
08-29-2006, 3:02 PM
#16
yeah, I see your point, well, I definetely aint giving up the ability to turn it on and off when I want.. Have you tried the mod? It adds such a cool feel to the game, I find myself just turning my saber on, and off, for the fun of it..

Plus I got some cool saber sounds, its the individual on/off sound pack, so that adds a lot to being able to do it..

So thats out.. I guess I could just let it go, I am the only one who was a complaint with it, so it would seem, close to 200 ppl maybe more, have downloaded it, and not one has complained about it.. I got a 9/10 at kotor files.. Last I checked at least...

So I guess at least for now, I am putting it back on hold.. :(

Well Stoffe, i appreciate you help, not just today, but everything you have helped me with, i wouldn't be anywhere near as good as I am at scripting if it werent for you, I still have .txt files containing all the usefull stuff you have told me so I can reference it anytime I can't figure something out..

Those things are life savers, well, thanks for your help, and thank you too oldflash, I got the combat function, and the other stuff you gave me stored away in a few .txt files.. :)

Alright, well Im outta here, have fun you guys/gals, and if you havent already, you should try out my mods, they are up on Kotor Files, just search for my username, or look on the top 10 downloads this week, I think they are all there too...

Peace...
Page: 1 of 1