PDA

View Full Version : Need help with mod


wasa7
09-22-2006, 11:47 PM
Hello all, and thanks in advance to those who may reply to this Thread.

I've been trying to make a mod that spawns a Sith Patrol right outside the Hideout in Taris. Sith Patrol equals one Red Sith Patrol Leader and two Silver Sith Troppers. I've been reading a lot of the Holowans tutorials but I'm still missing some important things to make it work. I have a lot of questions too.

Until now, I have the trigger that will fire on entering to the area. I have this script attached to it. Don't know if it works. Is not completed.

void main()
{

//How do I check if Bastila has been rescued from the Black Bulkars

int nCreatureSpawned = GetGlobalBoolean("Sith_Patrol_Check"); // Boolean created in the globalcat.2da for this use only
if (nCreatureSpawned) { return; } // it will exit if TRUE

float x1=86.8399963378906; // coordinates from cheat console 'whereami'
float y1=104.660003662109;
float z1=0.00;

float r1=0.0f; // orientation in degrees. How do I get this? What is that letter f?
vector MyVec1 = Vector(x1,y1,z1); // positioning vector

float x2=88.2699966430664;
float y2=102.180000305176;
float z2=0.00;

float r2=0.0f;
vector MyVec2 = Vector(x2,y2,z2);

float x3=89.0500030517578;
float y3=103.519996643066;
float z3=0.00;

float r3=0.0f;
vector MyVec3 = Vector(x3,y3,z3);


location SLoc1 = Location(MyVec1, r1); // create location for creature
object oSithL=CreateObject( OBJECT_TYPE_CREATURE, "s_patrol_leader", SLoc1); // spawn creature Sith Patrol Leader in the location

location SLoc2 = Location(MyVec2, r2); //
object oSithT1=CreateObject( OBJECT_TYPE_CREATURE, "s_trooper", SLoc2); //


location SLoc3 = Location(MyVec3, r3); //
object oSithT2=CreateObject( OBJECT_TYPE_CREATURE, "s_trooper", SLoc3); //


SetGlobalBoolean("my_global_bool",TRUE); // this prevent creature from spawning again

}

From that script, how do I check if Bastila have been rescued? I checked the boolean list and found one that may work but I compare two saved games, one before and after having Bastila and it was the same for both so...

Then I need another trigger around the created creatures, that will open the dialogue between the Sith Patrol Leader and the PC. After that, the fight. And finally, a dialogue between PC and Bastilla. If someone could help me or maybe point me in the right direction would be appreciated. Thank you all again.

stoffe
09-23-2006, 12:39 AM
I've been trying to make a mod that spawns a Sith Patrol right outside the Hideout in Taris. Sith Patrol equals one Red Sith Patrol Leader and two Silver Sith Troppers. I've been reading a lot of the Holowans tutorials but I'm still missing some important things to make it work. I have a lot of questions too.

From that script, how do I check if Bastila have been rescued?


It should be enough to check if she's available as a party member, that will imply that she has been rescued since she's not available in the party before then. :) You could write that script like:

object SpawnNPCAtLocation(string sResRef, float x, float y, float r);

void main() {
if (IsAvailableCreature(NPC_BASTILA) && !GetGlobalBoolean("Sith_Patrol_Check")) {
SpawnNPCAtLocation("s_patrol_leader", 86.84, 104.66, 0.0);
SpawnNPCAtLocation("s_trooper", 88.27, 102.18, 0.0);
SpawnNPCAtLocation("s_trooper", 89.05, 103.52, 0.0);
SetGlobalBoolean("Sith_Patrol_Check",TRUE);
}
}

object SpawnNPCAtLocation(string sResRef, float x, float y, float r) {
location lLoc = Location(Vector(x, y, 0.0), r);
return CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc);
}



Then I need another trigger around the created creatures, that will open the dialogue between the Sith Patrol Leader and the PC.

You could put that in the OnPerception AI script of the patrol leader. If he perceives the player approach and start conversation... That custom OnPerception script could look something like:

void main() {
if (!GetLocalBoolean(OBJECT_SELF, 31) && (GetLastPerceived() == GetFirstPC())) {
ClearAllActions();
SetLocalBoolean(OBJECT_SELF, 31, TRUE);
ActionStartConversation(GetFirstPC(), "sithdialog", FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE);
}
else {
ExecuteScript("k_ai_master", OBJECT_SELF, 1002);
}
}


That should engage dialog mode directly when he spots the player (to prevent them from running away). If you want them to move closer and not shout from wherever they are do that via a script set on the first dialog node.

wasa7
09-23-2006, 01:30 AM
Gee thank you Stoffe, didn't hope to get such a fast answer. I also hope not be a bother but I have new questions.

You could put that in the OnPerception AI script of the patrol leader. If he perceives the player approach and start conversation...
Where on the Patrol Leader should that script be placed? I checked the NPC .uti in the script section and there are a lot of script sections (i.e. onheartbeat, onnotice, etc...). I copied this .uti from another module and it has a lot of scripts (default ones I think) so wich one shoul I replace? Onnotice?

That should engage dialog mode directly when he spots the player (to prevent them from running away). If you want them to move closer and not shout from wherever they are do that via a script set on the first dialog node.
Do I have to specify waypoints for the NPC to come closer to the PC? I want the whole Patrol to come closer to the PC, how do I specify that?

Thank you again for the help!

stoffe
09-23-2006, 07:20 AM
Where on the Patrol Leader should that script be placed? I checked the NPC .uti in the script section and there are a lot of script sections (i.e. onheartbeat, onnotice, etc...).


Yes, it's called OnNotice for some reason. Compile your custom Perception AI script under a new ResRef and put the name of the script in the OnNotice box. (By the way I just noticed the name of the global didn't match where it was set and where it was checked. I fixed that in the revised spawn script in the above post.)


Do I have to specify waypoints for the NPC to come closer to the PC? I want the whole Patrol to come closer to the PC, how do I specify that?

A simple dialog script to move closer (2 meters for leader, 2.5 meters for grunts) to the player:

void main() {
object oLeader = GetObjectByTag("PatrolLeaderTag");
object oTroop1 = GetObjectByTag("PatrolTroopTag");
object oTroop2 = GetObjectByTag("PatrolTroopTag", 1);
object oPlayer = GetFirstPC();

AssignCommand(oLeader, ActionMoveToObject(oPlayer, TRUE, 2.0));
AssignCommand(oTroop1, ActionMoveToObject(oPlayer, TRUE, 2.5));
AssignCommand(oTroop2, ActionMoveToObject(oPlayer, TRUE, 2.5));
}


A simple dialog script to make them attack the player if added to one of the end nodes of a DLG:

#include "k_inc_generic"

void main() {
object oLeader = GetObjectByTag("PatrolLeaderTag");
object oTroop1 = GetObjectByTag("PatrolTroopTag");
object oTroop2 = GetObjectByTag("PatrolTroopTag", 1);
object oPlayer = GetFirstPC();

ChangeToStandardFaction(oLeader, STANDARD_FACTION_HOSTILE_1);
ChangeToStandardFaction(oTroop1, STANDARD_FACTION_HOSTILE_1);
ChangeToStandardFaction(oTroop2, STANDARD_FACTION_HOSTILE_1);

AssignCommand(oLeader, GN_DetermineCombatRound(oPlayer));
AssignCommand(oTroop1, GN_DetermineCombatRound(oPlayer));
AssignCommand(oTroop2, GN_DetermineCombatRound(oPlayer));
}


An example OnDeath event script for the Sith Troops/Leader that might work to fire a dialog between Bastila and the main character when the Sith Patrol are all dead. You'll need to assign the script to the OnDeath event slot for both the Leader and the Trooper UTCs:

void StartPlayerBanter() {
int i;
for (i = 0; i < GetPartyMemberCount(); i++) {
object oParty = GetPartyMemberByIndex(i);
AssignCommand(oParty, ClearAllActions());
CancelCombat(oParty);
}

object oPC = GetFirstPC();
if (GetDistanceToObject(oPC) > 10.0) || !GetObjectSeen(oPC)) {
ActionJumpToObject(oPC);
}

ActionStartConversation(oPC, "PostCombatDLG", FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE);
}

void main() {
object oLeader = GetObjectByTag("PatrolLeaderTag");
object oTroop1 = GetObjectByTag("PatrolTroopTag");
object oTroop2 = GetObjectByTag("PatrolTroopTag", 1);

if ((!GetIsObjectValid(oLeader) || GetIsDead(oLeader))
&& (!GetIsObjectValid(oTroop1) || GetIsDead(oTroop1))
&& (!GetIsObjectValid(oTroop2) || GetIsDead(oTroop2)))
{
object oBastilaah = GetObjectByTag("Bastila");
if (GetIsObjectValid(oBastilaah) && IsObjectPartyMember(oBastilaah)) {
AssignCommand(oBastilaah, DelayCommand(2.0, StartPlayerBanter()));
}
}

ExecuteScript("k_ai_master", OBJECT_SELF, 1007);
}


In all the above scripts, substitute the parts in yellow with the tags specified in your Sith Leader and Sith Trooper templates. There is a field for the Tag in the UTC files, it does not necessarily match the ResRef/Filename. Make sure the tags for your templates are unique and not shared by any other NPCs in the game world. The part in green should be replaced by the ResRef of your DLG file containing the after-battle chatter with Bastila.

(Warning: The above scripts are untested since I don't have the ability to run the game now to see if they work. If you get any errors please let me know and I'll see if I can spot what's wrong.)

wasa7
09-24-2006, 12:07 PM
Hello Stoffe, how are things going?
Thanks a lot for the codes, I've studied them so I can understand them. I've made all the arranges so they are compatible with each other, put the right names, etc. Now all I need is to compile them and see if there are any errors. If they are, surely I'll let you know.

You've been very helpfull Stoffe, you're name will be in the "Thanks to" part inside the mod when released.

wasa7
09-24-2006, 01:30 PM
(Warning: The above scripts are untested since I don't have the ability to run the game now to see if they work. If you get any errors please let me know and I'll see if I can spot what's wrong.)


void StartPlayerBanter() {
int i;
for (i = 0; i < GetPartyMemberCount(); i++) {
object oParty = GetPartyMemberByIndex(i);
AssignCommand(oParty, ClearAllActions());
CancelCombat(oParty);
}

object oPC = GetFirstPC();
if (GetDistanceToObject(oPC) > 10.0) || !GetObjectSeen(oPC)) {
ActionJumpToObject(oPC);
}

ActionStartConversation(oPC, "PostCombatDLG", FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE);
}

void main() {
object oLeader = GetObjectByTag("PatrolLeaderTag");
object oTroop1 = GetObjectByTag("PatrolTroopTag");
object oTroop2 = GetObjectByTag("PatrolTroopTag", 1);

if ((!GetIsObjectValid(oLeader) || GetIsDead(oLeader))
&& (!GetIsObjectValid(oTroop1) || GetIsDead(oTroop1))
&& (!GetIsObjectValid(oTroop2) || GetIsDead(oTroop2)))
{
object oBastilaah = GetObjectByTag("Bastila");
if (GetIsObjectValid(oBastilaah) && IsObjectPartyMember(oBastilaah)) {
AssignCommand(oBastilaah, DelayCommand(2.0, StartPlayerBanter()));
}
}

ExecuteScript("k_ai_master", OBJECT_SELF, 1007);
}


Hello again Stoffe, I compiled the codes and they all did fine except for this one. It give me a syntax error at "||" and it does not create the .ncs file. I wish I could solve this myself but I don't know what does it mean :)

stoffe
09-24-2006, 03:31 PM
Hello again Stoffe, I compiled the codes and they all did fine except for this one. It give me a syntax error at "||" and it does not create the .ncs file. I wish I could solve this myself but I don't know what does it mean :)

There was a missing start paranthesis at the beginning of that if statement. Try the below version, it should compile. (Don't forget to change the tags to those of your Sith trooper characters and of the dialog file to start after the battle as well before compiling or it won't work as it should.)


void StartPlayerBanter() {
int i;
for (i = 0; i < GetPartyMemberCount(); i++) {
object oParty = GetPartyMemberByIndex(i);
AssignCommand(oParty, ClearAllActions());
CancelCombat(oParty);
}

object oPC = GetFirstPC();
if ((GetDistanceToObject(oPC) > 10.0) || !GetObjectSeen(oPC)) {
ActionJumpToObject(oPC);
}

ActionStartConversation(oPC, "PostCombatDLG", FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE);
}

void main() {
object oLeader = GetObjectByTag("PatrolLeaderTag");
object oTroop1 = GetObjectByTag("PatrolTroopTag");
object oTroop2 = GetObjectByTag("PatrolTroopTag", 1);

if ((!GetIsObjectValid(oLeader) || GetIsDead(oLeader))
&& (!GetIsObjectValid(oTroop1) || GetIsDead(oTroop1))
&& (!GetIsObjectValid(oTroop2) || GetIsDead(oTroop2)))
{
object oBastilaah = GetObjectByTag("Bastila");
if (GetIsObjectValid(oBastilaah) && IsObjectPartyMember(oBastilaah)) {
AssignCommand(oBastilaah, DelayCommand(2.0, StartPlayerBanter()));
}
}

ExecuteScript("k_ai_master", OBJECT_SELF, 1007);
}

wasa7
09-25-2006, 12:48 AM
Ok Stoff, almost seems to be ready. Last thing needed is to attach the spawning script to the module. I tried including a modified .git file into the override folder but crazy things happened. So, and this is not my idea, how about replacing an area script with the one you made and from that script make a call of the original one? An ExecuteScript would be required. This is what I did:


object SpawnNPCAtLocation(string sResRef, float x, float y, float r);

void main()
{
if (IsAvailableCreature(NPC_BASTILA) && !GetGlobalBoolean("Sith_Patrol_Check"))
{
SpawnNPCAtLocation("my_sith_patrol_leader", 86.84, 104.66, 0.0);
SpawnNPCAtLocation("my_sith_trooper", 88.27, 102.18, 0.0);
SpawnNPCAtLocation("my_sith_trooper", 89.05, 103.52, 0.0);
SetGlobalBoolean("Sith_Patrol_Check",TRUE);
ExecuteScript("k_ptar_rodiantrg"); // This is the new line!
}
}

object SpawnNPCAtLocation(string sResRef, float x, float y, float r)
{
location lLoc = Location(Vector(x, y, 0.0), r);
return CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc);
}
It gives me the followin error:
Required argument missing in call to "ExecuteScript". What am I doing wrong?

EDIT: I found that what is missing is something like this:
ExecuteScript("k_ptar_rodiantrg", OBJECT_SELF, ####);
What numbers should I put after oject_self?

stoffe
09-25-2006, 06:23 AM
Ok Stoff, almost seems to be ready. Last thing needed is to attach the spawning script to the module. I tried including a modified .git file into the override folder but crazy things happened.


Yes, never put GIT files in the override folder since it for some reason have higher priority than savegames, causing the GIT file containing the current area state to be ignored when loading the savegame. Also take care to use a GFF editor that handles the new Vector and Orientation field types, or the CameraList in the GIT file will get messed up when you modify the file.

If you need to modify the GIT file of an area you'll need to either put the modified GIT file back into the module's RIM file, or repackage the whole module as a MOD file, whichever you prefer.

That said, you don't set the event scripts of the area in the .GIT file, but in the .ARE file in the module. But it's probably a good idea not to put those in the override folder either, since many modules for some reason have ARE files with the same name, and putting one in the override folder will override them all. Put those back in the module RIM as well, or repackage as a MOD.


So, and this is not my idea, how about replacing an area script with the one you made and from that script make a call of the original one? An ExecuteScript would be required. This is what I did:
(snip)
SpawnNPCAtLocation("my_sith_patrol_leader", 86.84, 104.66, 0.0);
(snip)
ExecuteScript("k_ptar_rodiantrg"); // This is the new line!
(snip)
It gives me the followin error:
Required argument missing in call to "ExecuteScript". What am I doing wrong?
EDIT: I found that what is missing is something like this:
ExecuteScript("k_ptar_rodiantrg", OBJECT_SELF, ####);
What numbers should I put after oject_self?

If you want to replace a current script to fire your own, name your script exactly what the one you wish to replace was named. Then extract that original script, name it something else and put it in the override folder along with your new script. Then have your script execute the renamed file. If you use this variant, test it thoroughly in-game since I've noticed that there are some problems with ExecuteScript() not working properly under some unknown circumstances.

Anyway, as to your script, the first parameter to ExecuteScript() is the ResRef of the script to run, the second is the object who should run the script, and the third is an optional parameter to send to that script. Unless the script you replace requires any such parameters you should just leave out the third parameter entirely.

Another thing though, on the other line quoted above, marked in red, the ResRef of your UTC file is too long. It can be at most 16 characters in length, while yours is 21. You'll need to shorten it down to 16 characters, and rename your UTC file correspondingly, or it will not work properly.

wasa7
09-25-2006, 11:16 AM
Ok, I tested the mod and it works but the results are not entirely the ones that we were especting. First, I had to replace the "k_ptar_rodiantrg.ncs", this is the script I took the name of. With out it, the messenger from Canderous, the twileek, will never show up. That's ok for the moment. Other thing, even if Bastila is not in the party, a Sith Patrol shows up. Even worst, when she's in the party, it triggers like 20 Sith Patrols in the main hall outside the hideout. What could be wrong? The global boolean? I've read all the codes again trying to find something wrong. I understand if you get tired of this, I'm getting frustrated my self, but the mod is almost done. Thank you again!

stoffe
09-25-2006, 11:49 AM
First, I had to replace the "k_ptar_rodiantrg.ncs", this is the script I took the name of. With out it, the messenger from Canderous, the twileek, will never show up.


This is why you should extract the original script, rename it, and then run the renamed copy with ExecuteScript from within your new script. That way both will run.



Other thing, even if Bastila is not in the party, a Sith Patrol shows up.


The script only checks if she has been rescued (i.e. as joined your group), not if she's in the active party with the player, so that is not so strange. If you want to check if she's in the party with the player as well, add an extra condition to the if-statement like:

if (IsAvailableCreature(NPC_BASTILA) && IsNPCPartyMember(NPC_BASTILA) && !GetGlobalBoolean("Sith_Patrol_Check")) {




Even worst, when she's in the party, it triggers like 20 Sith Patrols in the main hall outside the hideout. What could be wrong? The global boolean?


I'd guess you have forgotten to add the global boolean to globalcat.2da. If you haven't the value you set to it will never be stored and thus it will always return FALSE. Also doublecheck that the name of the global is identical both where it is set and where it is changed.

Further, if this is supposed to be an OnEnter script of an area you must check that the entering object is the player as well. Since the OnEnter script fires whenever any creature is spawned into the area it will trigger once for every sith patrol you spawn in as well, in turn spawning 3 more who in turn spawn three more etc... Only triggering it for the player character solves that.

So, you'd end up with something like this as spawn script (don't forget to change the StrRefs of the troopers to the names you use):

object SpawnNPCAtLocation(string sResRef, float x, float y, float r);

void main() {
if ((GetEnteringObject() == GetFirstPC())
&& IsAvailableCreature(NPC_BASTILA)
&& IsNPCPartyMember(NPC_BASTILA)
&& !GetGlobalBoolean("Sith_Patrol_Check"))
{
SpawnNPCAtLocation("s_patrol_leader", 86.84, 104.66, 0.0);
SpawnNPCAtLocation("s_trooper", 88.27, 102.18, 0.0);
SpawnNPCAtLocation("s_trooper", 89.05, 103.52, 0.0);
SetGlobalBoolean("Sith_Patrol_Check",TRUE);
}

ExecuteScript("k_real_rodiantrg", OBJECT_SELF);
}

object SpawnNPCAtLocation(string sResRef, float x, float y, float r) {
location lLoc = Location(Vector(x, y, 0.0), r);
return CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc);
}

wasa7
09-25-2006, 02:28 PM
Hello Stoffe, here am I again :)

This is why you should extract the original script, rename it, and then run the renamed copy with ExecuteScript from within your new script. That way both will run.
I did this the first time, something's happening that it just doesn't work! This is what I did:


object SpawnNPCAtLocation(string sResRef, float x, float y, float r);

void main()
{
ExecuteScript("k_ptar_rodiantrg2", OBJECT_SELF);

if ((GetEnteringObject() == GetFirstPC())
&& IsAvailableCreature(NPC_BASTILA)
&& IsNPCPartyMember(NPC_BASTILA)
&& !GetGlobalBoolean("S_Patrol_Check"))
{
SetGlobalBoolean("S_Patrol_Check",TRUE);
SpawnNPCAtLocation("s_ptrl_ldr", 86.84, 104.66, 90.0);
SpawnNPCAtLocation("s_trpr", 88.27, 102.18, 85.0);
SpawnNPCAtLocation("s_trpr", 89.05, 103.52, 93.0);
}
}

object SpawnNPCAtLocation(string sResRef, float x, float y, float r) {
location lLoc = Location(Vector(x, y, 0.0), r);
return CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc);
}

I've checked the name of the global variable, both on the globalcat.2da and the script above. After I kill the Sith army we just spawned in the main hall, and reenter the area, they won't appear anymore so I think this boolean is working right.

So, what do we have? If the PC enters alone this area, the script won't fire. That's ok. If he enters with party members (Bastila not included), the script won't fire. I will change that it in the future, and I will add some options in the .dlg so they won't attack me unless Bastila is with the PC. But when Bastila is included:

1.- Sith army is spawned

2.- Original script won't trigger, even if I put the executescript line. I think somethig is missing there, like:
ExecuteScript("k_ptar_rodiantrg2", OBJECT_SELF, "some_other_parameter");

3.-When dialog triggers, Sith Patrol runs towards you, is there a way to make them walk?

4.-After you kill one patrol, another dialog corresponding another patrol will trigger and so on until you kill all patrols spawned.

5.-All Sith dead, dialog between PC and Bastila won't trigger.

I hope you're not so tired of helping me. If you want I can send you all the files so you can check what's wrong. If not, I will continue to test it untill it works just as I want it. Thanks a lot for all the help.

stoffe
09-25-2006, 03:11 PM
ExecuteScript("k_ptar_rodiantrg2", OBJECT_SELF);


Same problem here, a ResRef can be at most 16 characters long, k_ptar_rodiantrg2 is 17 characters long. You'll need to shorten the name of the original modified script or it won't run properly.


3.-When dialog triggers, Sith Patrol runs towards you, is there a way to make them walk?


Change TRUE to FALSE in the ActionMoveToObject() function calls in the script that makes the troopers move. This will make them walk instead.


4.-After you kill one patrol, another dialog corresponding another patrol will trigger and so on until you kill all patrols spawned.


Uh? I'm not sure I understand what you mean here. Does more than one patrol spawn? Is this intentional or is it a bug? If more than one patrol should spawn, should they also talk, or are they reinforcements?


5.-All Sith dead, dialog between PC and Bastila won't trigger.


Have you assigned the script starting that dialog to the OnDeath event slot of all the Sith Troopers? Have you set the ResRef of the DLG file properly in the ActionStartConversation() call in that script? Make sure the name of the DLG file is not longer than 16 characters. Make sure you have set the tags of the troopers properly in that script as well. Make sure all the troops really have been killed and there aren't any lurking somewhere. Make sure their tags are unique for that UTC and not shared by other characters.

If you've checked all those and it still doesn't work you could try an alternate approach to detecting if everyone is dead. You could create a "trooper counter" global var and give the troopers a new OnSpawn script that increases that counter by 1 when spawned, and make the OnDeath scripts reduce it by 1. And when it reaches 0, start the conversation.

Agent Xim
09-25-2006, 04:44 PM
You could create a "trooper counter" global var and give the troopers a new OnSpawn script that increases that counter by 1 when spawned, and make the OnDeath scripts reduce it by 1. And when it reaches 0, start the conversation.

Instead of using both OnSpawn & OnDeath, I use OnDeath to have trooper check if any are left (GetIsObjectValid), then if all are dead, set a boolean var to indicate death, then check for it from the spawn script so they only spawn once.

wasa7
09-25-2006, 07:48 PM
IT WORKS! IT'S ALIVE! MUA JA JA JA!!!

Hahaha it finally works Stoff, at least par of it. The Sith Patrol spawns at the perfect spot, the original script triggers at the right moment, when I approuch the Sith soldiers, the dialog starts and they walk towars me, and then they get agressives so other kind of negotiation are required. That's perfect!

They are only a few bugs to correct. The Sith Patrol spaws everytime, something is not working correctly with the bloody boolean. I'm still working on that. To be more specific, if I reenter the area without Bastila, a new patrol spawns. If Bastila is with me, two patrols (two patrols = six Sith soldiers) will appear at the selected spot. It gets serious if you don't kill those soldiers as they remain in the area. If you reenter ten times, you'll have 30 Sith soldiers. The dialog between Bastila and PC just won't trigger. I check all the things you said but I'm still going through the codes to see if I find something wrong.

Well, that's it. You'll have to give you addres so I can send you a Christmas or a Holiday Card for having such patience with me lol. Thank you again :)

EDIT: By the way, hello Agent Xim, good to see you around here! Thank you for your help too.

wasa7
09-26-2006, 01:29 AM
Ok Stoffe, the bloody boolean works! Hehe, yep you were right about that something was wrong in the conception of the global variable itself. I'm not sure why but the globalcat.2da file wasn't saving as it should so,... anyways, now I got it working. I'm still thinking how to arrange the dialog between Bastila and Pc. Take care!

stoffe
09-26-2006, 06:44 AM
I'm still thinking how to arrange the dialog between Bastila and Pc.

Try this slightly modified variant of the OnDeath script of the troopers. As before, modifiy the part colored in yellow with the name of the DLG file (without the .dlg extension) to start after the battle is over, and the parts in blue with the proper tags of your Troopers (as set in their UTC files).

I've tested this script and it triggers the conversation when all the hostiles have died in my game.

The only thing that changed is that I added a slight delay before the conversation was triggered, since the StartConversation action was flushed from the action queue when Bastila exited combat mode for some reason if it was issued directly after. NWScript can be rather peculiar at times. :)


void StartPlayerBanter() {
int i;
for (i = 0; i < GetPartyMemberCount(); i++) {
object oParty = GetPartyMemberByIndex(i);
AssignCommand(oParty, ClearAllActions());
CancelCombat(oParty);
}

object oPC = GetFirstPC();
if ((GetDistanceToObject(oPC) > 10.0) || !GetObjectSeen(oPC)) {
ActionJumpToObject(oPC);
}

NoClicksFor(1.0);
DelayCommand(1.0, ActionStartConversation(oPC, "BastilaDlg", FALSE, CONVERSATION_TYPE_CINEMATIC, TRUE));
}

void main() {
object oLeader = GetObjectByTag("PatrolLeader");
object oTroop1 = GetObjectByTag("PatrolGrunt");
object oTroop2 = GetObjectByTag("PatrolGrunt", 1);

if ((!GetIsObjectValid(oLeader) || GetIsDead(oLeader))
&& (!GetIsObjectValid(oTroop1) || GetIsDead(oTroop1))
&& (!GetIsObjectValid(oTroop2) || GetIsDead(oTroop2)))
{
object oBastilaah = GetObjectByTag("Bastila");
if (GetIsObjectValid(oBastilaah) && IsObjectPartyMember(oBastilaah)) {
AssignCommand(oBastilaah, DelayCommand(2.0, StartPlayerBanter()));
}
}

ExecuteScript("k_ai_master", OBJECT_SELF, 1007);
}


If that still doesn't work then you've done things different somewhere else than I did when I tested. :)

wasa7
09-27-2006, 12:00 AM
Try this slightly modified variant of the OnDeath script of the troopers.
Hello Stoffe. What can I say? The code above worked just fine. THANK YOU! A LOT! I REALLY MEAN IT! The whole mod works perfectly. The dialogs trigger at the perfect time. I'm working on the dialogs so feel as part of the original game. I think you're going to be proud of it.

I can't think a better way to thank you that, from now long, to make mods for Kotor and Kotor TSL. I've learned a lot with what you've gave me. If you ever need something, a mod tester or whatever, just ask ok? Thank you again. I'll let you know when the mod is released.

wasa7
09-28-2006, 10:29 AM
Hi Stoffe, just wanted to let you know the mod is out. You can find it here:

http://www.lucasforums.com/showthread.php?p=2183660#post2183660

http://www.pcgamemods.com/mod/19179.html

Thanks again for everything!

wasa7
09-30-2006, 02:53 PM
Hello Stoffe, remember me? how are things going?
I found recently that you're not a he but a she, I'm sorry for not knowing that before he he :)

Since my mod, I've been testing some other changes to the game. Right now I'm trying to modify Agent Xim's mod Operation Kill Bastila (OPK) (so far for my personal use only) but the results are not as I spected. I wonder if you could help me again with this.

The mod as it is, make all Sith Trooper to attack if Bastila is a party member. They all turn hostile when you enter the area but it looks weird because they stand in their places just waiting for you to come. What I've been trying to do is to make them walk normally as they usually do (this I did it ok) and when they notice the PC and Bastila, they become hostile (this is what I'm still working on). I made a code to put in the Onnotice field that check if Bastila is a party member, then turn hostile, or else, act normally by calling the original but renamed onnotice script just as you taught me. This is what I did:

#include "k_inc_debug"
#include "k_inc_generic"
#include "k_inc_tar"

void main()
{
object oCreature = GetLastPerceived();

if (GetLastPerceptionSeen() && GetIsPC(oCreature))
{
object oPlayer = GetFirstPC();

if ((!TAR_GetWearingSithArmor())
&& (IsNPCPartyMember(NPC_BASTILA) == TRUE)
&& (GetDistanceBetween(GetPCSpeaker(), GetObjectByTag("bastila")) <= 10.0)
|| (GetIsObjectValid(GetItemPossessedBy(GetFirstPC(), "ptar_shieldcodes"))))
{
ActionDoCommand(SetFacingPoint(GetPosition(oCreatu re)));
ExecuteScript("tar_gohostile", OBJECT_SELF);
}


if ((TAR_GetWearingSithArmor())
&& (!GetIsObjectValid(GetItemPossessedBy(GetFirstPC() , "ptar_shieldcodes"))))
{
ExecuteScript("tar_goneutral", OBJECT_SELF);
}

}

else
{
ExecuteScript("k_old_percept01", OBJECT_SELF);
}

}

The structure of the code is a combination of the original OPK code with an on_notice code I found on the web. I tried using the one you gave but it didn't work either. The yellow code is the original code (it works) that make the Sith Troopers to become hostile and the orange code is the original but renamed onnotice code. What do you think? Sorry to bother you again and I thank you in advance for your help. See ya and take care!

stoffe
09-30-2006, 05:30 PM
The structure of the code is a combination of the original OPK code with an on_notice code I found on the web. I tried using the one you gave but it didn't work either. The yellow code is the original code (it works) that make the Sith Troopers to become hostile and the orange code is the original but renamed onnotice code.

A few things I spotted:
You use GetPCSpeaker() for distance check, but that function is only valid to use during a dialog. It returns the object the caller is in conversation with. Since you want to check distance from the one running the script (OBJECT_SELF), I'd use the GetDistanceToObject() function instead.


I'm not 100% sure how it works in KotOR, but believe GetIsPC() only returns true if the object passed to it is the player character. Thus Bastila could run around alone unmolested as long as the the player character keeps out of sight. Better to check for all party members instead, then it will trigger even if Bastila is running around alone.


Finally, it's probably better to execute k_ai_master directly with the parameter set to 1002 (i.e. triggering its OnPerception code). This is since all k_def_percept01 does is to execute k_ai_master. This way you save one script and one step of execution.


With that you might end up with a modified script looking something like:

#include "k_inc_debug"
#include "k_inc_generic"
#include "k_inc_tar"

int HasShieldCodes(object oPossessor) {
return GetIsObjectValid( GetItemPossessedBy(oPossessor, "ptar_shieldcodes") );
}

void main() {
object oSeen = GetLastPerceived();
object oPC = GetFirstPC();

if (GetLastPerceptionSeen() && IsObjectPartyMember(oSeen)) {
if (HasShieldCodes(oPC)
|| (!TAR_GetWearingSithArmor()
&& IsNPCPartyMember(NPC_BASTILA)
&& (GetDistanceToObject( GetObjectByTag("Bastila") ) <= 10.0)))
{
ActionDoCommand(SetFacingPoint(GetPosition(oSeen)) );
ExecuteScript("tar_gohostile", OBJECT_SELF);
return;
}
else if (TAR_GetWearingSithArmor() && !HasShieldCodes(oPC)) {
ExecuteScript("tar_goneutral", OBJECT_SELF);
return;
}

}

ExecuteScript("k_ai_master", OBJECT_SELF, 1002);
}


It should be noted though that if Bastila is not within a 10 meter radius once all party members have been perceived the trooper will not attack even when she gets closer, since the OnPerception event only fires once the NPC either first perceives, looses perception of, or re-perceives a character it lost perception of. It does not continually fire while seeing another character. At least as far as I understand it. :)

wasa7
09-30-2006, 07:01 PM
WOW! You did again Stoffe, thank you very much! Not only the code works perfectly, but the effect that it causes (I mean visually) is simply amazing. I will even ask Agent Xim to see if he want to release this upgrade for his mod. Thanks again!

Agent Xim
09-30-2006, 07:14 PM
That's some fine coding there stoffe :)

I pretty much (attempted) in Operation Kill Bastila to combine the code from:
k_ptar_sithdis.ncs, k_ptar_sithdis2.ncs, k_con_bastpm.ncs, k_ptar_candcode.ncs
which were all dialog conditionals so that explains why my code doesn't always work lol.

wasa7
09-30-2006, 07:17 PM
That's some fine coding there stoffe :)

I pretty much (attempted) in Operation Kill Bastila to combine the code from:
k_ptar_sithdis.ncs, k_ptar_sithdis2.ncs, k_con_bastpm.ncs, k_ptar_candcode.ncs
which were all dialog conditionals so that explains why my code doesn't always work lol.

I was just PM-ing you Agent Xim. I was planing to send you the modifications I made, with Stoffe's help off course, so you can post it as a new update to the OKB mod. PM me so I know where to send you the .zip file. You're going to like it!

wasa7
10-02-2006, 01:09 AM
Hello Stoffe, it's me again, how are you? I'm in need of your helpful teachings again. I spoke to Agent Xim and he agreed to pass me the Operation Kill Bastila project, mostly because he is bussy with other projects and off course because I just can't stop messing around with it hehehe :P

Right now, what I'm trying to do is to spawn some Sith Troopers and some Battle Droids in the Sith Base, right after you kill the Sith Governor so the party can't scape so easily from the Sith Base. I compiled this code without errors (is a melange of some codes you've given me) but I can't make it trigger because I can't figure what's the correct entering .ncs file of the area. Any ideas?

//I don't know why I keep including this libraries but what the h***...

#include "k_inc_debug"
#include "k_inc_generic"
#include "k_inc_tar"


//Used to check is Sith Codes are available
int HasShieldCodes(object oPossessor)
{
return GetIsObjectValid(GetItemPossessedBy(oPossessor, "ptar_shieldcodes"));
}

//Used for easy creature spawnign
object SpawnNPCAtLocation(string sResRef, float x, float y, float r);


void main()
{
object oPC = GetFirstPC();

//Execute original area script
ExecuteScript("k_old_govtlk_en", OBJECT_SELF, 1002);

//If PC enters the area and if Sith Codes are available, then spawn creatures
if ((GetEnteringObject() == GetFirstPC())
&& (HasShieldCodes(oPC)))
{
SpawnNPCAtLocation("x_sith_1", 35.36, 12.84, 0.0);
SpawnNPCAtLocation("x_sith_2", 34.38, 10.69, 0.0);
SpawnNPCAtLocation("x_battle_droid", 37.08, 11.28, 0.0);

SpawnNPCAtLocation("x_sith_1", 6.20, 33.59, 0.0);
SpawnNPCAtLocation("x_sith_2", 1.37, 33.23, 0.0);
SpawnNPCAtLocation("x_battle_droid", 4.15, 31.15, 0.0);
SpawnNPCAtLocation("x_battle_droid", 2.77, 36.19, 0.0);

SpawnNPCAtLocation("x_sith_1", -3.50, -14.25, 0.0);
SpawnNPCAtLocation("x_sith_1", -3.22, -15.40, 0.0);
SpawnNPCAtLocation("x_sith_2", 6.44, -15.26, 0.0);
SpawnNPCAtLocation("x_battle_droid", -5.69, -14.66, 0.0);

}


}


object SpawnNPCAtLocation(string sResRef, float x, float y, float r)
{
location lLoc = Location(Vector(x, y, 0.0), r);
return CreateObject(OBJECT_TYPE_CREATURE, sResRef, lLoc);
}

The yellow part should be the name of the original but renamed onentering area script, once I find wich one is it off course. I hope you don't get too tired of helping me out. In any case, thanks in advance and have a nice week! Take care!

stoffe
10-02-2006, 07:44 AM
Right now, what I'm trying to do is to spawn some Sith Troopers and some Battle Droids in the Sith Base, right after you kill the Sith Governor so the party can't scape so easily from the Sith Base. I compiled this code without errors but I can't make it trigger because I can't figure what's the correct entering .ncs file of the area. Any ideas?


As far as I can tell the Sith Base area has no standard OnEnter event script assigned, so if you want to use one you will have to create your own and then assign it to the area's OnEnter event slot in the m09aa.are file.


This would be found in the file tar_m09aa.rim, extract it, open it with k-gff and put the name of your script (without the .ncs extension) in the OnEnter field. Save the m09aa.are file and put it back into the tar_m09aa.rim file.

(If you want to release your mod to others though it might be better to use a mod installer to handle modifying the ARE and RIM file if you are concerned about compatibility with other mods modifying the same area. If you don't care about that you'll have to ship the modified tar_m09aa.rim file with your mod instead.)

I'd also suggest you add a condition check to the script to ensure that it only runs once, otherwise a new batch of droids and troopers would be spawned every time you re-enter the area (either by area transition or by loading a savegame inside the area). Something like this should work:


int HasShieldCodes();
object SpawnNPCAtLocation(string sResRef, float x, float y, float r);

void main() {
//If PC enters the area and if Sith Codes are available, then spawn creatures
if ((GetEnteringObject() == GetFirstPC())
&& !GetLocalBoolean(OBJECT_SELF, 40)
&& (HasShieldCodes()))
{
SpawnNPCAtLocation("x_sith_1", 35.36, 12.84, 0.0);
SpawnNPCAtLocation("x_sith_2", 34.38, 10.69, 0.0);
SpawnNPCAtLocation("x_battle_droid", 37.08, 11.28, 0.0);

SpawnNPCAtLocation("x_sith_1", 6.20, 33.59, 0.0);
SpawnNPCAtLocation("x_sith_2", 1.37, 33.23, 0.0);
SpawnNPCAtLocation("x_battle_droid", 4.15, 31.15, 0.0);
SpawnNPCAtLocation("x_battle_droid", 2.77, 36.19, 0.0);

SpawnNPCAtLocation("x_sith_1", -3.50, -14.25, 0.0);
SpawnNPCAtLocation("x_sith_1", -3.22, -15.40, 0.0);
SpawnNPCAtLocation("x_sith_2", 6.44, -15.26, 0.0);
SpawnNPCAtLocation("x_battle_droid", -5.69, -14.66, 0.0);

SetLocalBoolean(OBJECT_SELF, 40, TRUE);
}
}

//Used for easy creature spawning (ResRef, x-coord, y-coord, facing)
object SpawnNPCAtLocation(string sResRef, float x, float y, float r) {
return CreateObject(OBJECT_TYPE_CREATURE, sResRef, Location(Vector(x, y, 0.0), r));
}

//Used to check is Sith Codes are available
int HasShieldCodes() {
return GetIsObjectValid( GetItemPossessedBy(GetFirstPC(), "ptar_shieldcodes") );
}

wasa7
10-02-2006, 11:30 AM
Hello Stoffe, as usual, thank you for answering.

As far as I can tell the Sith Base area has no standard OnEnter event script assigned, so if you want to use one you will have to create your own and then assign it to the area's OnEnter event slot in the m09aa.are file.

The code above can be used as an OnEnter script or should I create one that calls the script you just gave me?

This would be found in the file tar_m09aa.rim, extract it, open it with k-gff and put the name of your script (without the .ncs extension) in the OnEnter field. Save the m09aa.are file and put it back into the tar_m09aa.rim file.

Found it, found the OnEnter field. When I save that file, where should I put it back? I believe it's not into the Override Folder. Back into the tar_m09aa.rim? How should I do that?

When I have this running, I'll think how to use the ModInstaller instead of just draging all the file into the Override Folder. Thank you again Stoffe!

stoffe
10-02-2006, 03:30 PM
The code above can be used as an OnEnter script or should I create one that calls the script you just gave me?


That posted script can be used as an OnEnter event script, no need or point to call it from other scripts.



Found it, found the OnEnter field. When I save that file, where should I put it back? I believe it's not into the Override Folder. Back into the tar_m09aa.rim? How should I do that?


There are three ways to go about it that I can think of:
Put the modified ARE file back into the tar_m09aa.rim file you extracted it from. Then you'll need to ship this modified RIM file with your mod files at all. You can use the simple ERF/RIM Editor I made a while ago for this, there might be other tools as well that escapes my mind at the moment. I don't know if the latest version of KotorTool allows you to edit RIM files, the one I have (a few versions old) does not, AFAIK.


Use a mod installer to modify the ARE file in place inside the RIM file that already exists in the end mod user's game, then you don't need include the RIM file at all. TSLPatcher can do this. I don't remember if KISS can since I only looked at that one briefly a number of months ago.


Extract all data from both tar_m09aa.rim and tar_m09aa_s.rim and repackage it all (your modified ARE file included) into a tar_m09aa.mod file instead, and ship that one with your mod files. You can do this with KotorTool.


It can be risky to put ARE files in the override folder so I wouldn't recommend doing that. (On the same note, never put any .GIT files or a module.ifo file in the override folder, or bad things will happen.)

wasa7
10-06-2006, 10:45 AM
Hello Stoffe, how are you?
I've been bussy this week and I didn't have the time to work on the mods as I usually do. I found a little too complicated to put the OnEnter script into the Sith Base area so I decided to drop it, meaning that the Sith Base will remaing empty as the PC runs out from it.

What I decided is to spaw some Sith Troppers and a new character I'm making just outside the Sith Base. I'm working on a Dark Jedi Quarren (who will be the master of the Sith Governor) for wich I have modified the already existing skinn n_alien02_low. When renaming the skinn, how do I do to put it on a character? I've checked the .utc file in the appearance section but I'm not really sure if that what I'm looking for.

stoffe
10-07-2006, 12:47 PM
I'm working on a Dark Jedi Quarren (who will be the master of the Sith Governor) for wich I have modified the already existing skinn n_alien02_low. When renaming the skinn, how do I do to put it on a character? I've checked the .utc file in the appearance section but I'm not really sure if that what I'm looking for.

While I'm not 100% sure, I believe you will need to add a new line to the appearance.2da for your modified Quarren. Copy the existing line for the quarren and paste it at the end. Then change the name in the racetex column to use your modified texture instead. Save the modified appearance.2da in your override folder, and modify the UTC file for your quarren to point to the line number of your new row in the Appearance_Type field.

When testing, make sure you use a savegame made before the NPC was spawned, otherwise your changes will not take effect.

wasa7
10-09-2006, 01:18 AM
Hello Stoffe, so far I'm doing good with the project. I have spawned the Sith Soldiers and the Quarren Dark Jedi, I've made the dialog between the PC and the quarren and I just have to put the scripts to make it all work.

I have one question: Is there a function that make a NPC flourish his weapon wich can be triggered from a dialog? My idea is, while they are talking, the Dark Jedi flourish his lightsaber right before the last line, and before battle begins. Can it be done?

stoffe
10-09-2006, 07:23 AM
I have one question: Is there a function that make a NPC flourish his weapon wich can be triggered from a dialog? My idea is, while they are talking, the Dark Jedi flourish his lightsaber right before the last line, and before battle begins. Can it be done?

Not in KotOR1, as far as I am aware. In KotOR2:TSL there is a function called CreatureFlourishWeapon() that does what you want, but that function is new to the scripting language in the second game and doesn't exist in the first, AFAIK.

You might be able to do it "the hard way" though with the PlayAnimation() and SetLightsaberPowered() functions, if you can figure out the animation number for the Flourish animation.

wasa7
10-20-2006, 04:35 PM
Hello again Stoffe, sorry to bother you again. I've been off for a few days but now I'm retaking the work I left unfinished. I've succesfully achieved to trigger scripts once the player party leaves the Sith Base with the Sith Codes. I've spawned some Sith Soldiers here and there, they are aready hostile when spawned, and turned the Lower City Elevator Sith Guard also hostile. The thing is that when PC enters the area, all enemies just stand there, and do nothing. They attack only if I attack first. What should I do to correct this? Also, is there a script to fully heal all party members that I could trigger when I enter an area? Thanks in advance!

EDIT: I discovered that the reason for they to stand and do nothing is a script you came up some time ago, that I used for Agent Xim's Operation Kill Bastila Mod. If I remove those OnPerceit script, bad guys attack me perfectly. What I will try to make that scrip to work only when need it and then to turn off. I hope that is possible.

stoffe
10-20-2006, 08:16 PM
Also, is there a script to fully heal all party members that I could trigger when I enter an area?

If you want to fully heal all party members, you can do that with a script like:


void ST_HealActor(object oTarget);



// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ST: Main function...
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void main() {
int i;

for (i = 0; i < GetPartyMemberCount(); i++) {
ST_HealActor(GetPartyMemberByIndex(i));
}
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ST: Support function - remove harmful effects from character
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ST_RemoveBadEffects(object oTarget) {
effect eEff = GetFirstEffect(oTarget);
while (GetIsEffectValid(eEff)) {
int iType = GetEffectType(eEff);
if ((iType == EFFECT_TYPE_POISON)
|| (iType == EFFECT_TYPE_PARALYZE)
|| (iType == EFFECT_TYPE_STUNNED)
|| (iType == EFFECT_TYPE_FRIGHTENED)
|| (iType == EFFECT_TYPE_SLEEP)
|| (iType == EFFECT_TYPE_ABILITY_DECREASE)
|| (iType == EFFECT_TYPE_ATTACK_DECREASE)
|| (iType == EFFECT_TYPE_AC_DECREASE)
|| (iType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE)
|| (iType == EFFECT_TYPE_SAVING_THROW_DECREASE)
|| (iType == EFFECT_TYPE_DAMAGE_DECREASE)
|| (iType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE)
|| (iType == EFFECT_TYPE_FORCE_RESISTANCE_DECREASE)
|| (iType == EFFECT_TYPE_SKILL_DECREASE)
|| (iType == EFFECT_TYPE_BLINDNESS)
|| (iType == EFFECT_TYPE_ENTANGLE)
|| (iType == EFFECT_TYPE_CONFUSED))
{
DelayCommand(0.1, RemoveEffect(oTarget, eEff));
}
eEff = GetNextEffect(oTarget);
}
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ST: Heal character of injuries and afflictions
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ST_HealActor(object oTarget) {
// ST: Revive if dead
if (GetIsDead(oTarget))
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oTarget);

// ST: Restore Health
int iHeal = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget);
if (iHeal > 0)
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(iHeal), oTarget);

// ST: Restore force points
iHeal = GetMaxForcePoints(oTarget) - GetCurrentForcePoints(oTarget);
if (iHeal > 0)
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHealForcePoints(iHeal), oTarget);

// ST: Remove harmful effects
ST_RemoveBadEffects(oTarget);

// ST: Show heal visual on target.
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEAL), oTarget);
}


I discovered that the reason for they to stand and do nothing is a script you came up some time ago, that I used for Agent Xim's Operation Kill Bastila Mod.

Is your custom script always running ExecuteScript("k_ai_master", OBJECT_SELF, 1002); no matter what else happens? Make sure that even if this line exists that it's always reachable (i.e. the script doesn't return before reaching it in some circimstances.

By your description it sounds like the standard OnPerception AI doesn't run, which is what makes an NPC attack when they spot an enemy. The above mentioned line runs the standard OnPerception AI and should always be called in any custom OnPerception AI scripts you use, either before or after your new script code.

wasa7
10-21-2006, 10:01 AM
Thanks again Stoffe, I think I would have quit modding if it wasn't for you. I plan moving from this thread to another one I just created yesterday. It's called scripting help. I hope to see you there when I ask for help hahaha.

I will test the healing script above and tell you if it worked. About the script always running, you might be right about the original OnPerception AI script not always running. The thing is that the conditionals that trigger custom script are the same than when PC comes out the Taris Sith Base. I plan of using some custom boolean as you thaugh me to make a difference between the time before and after entering Sith Base. I would check if k_ai_master is running or not. Thank you again!