Jump to content

Home

Qui-Gon's Script Shack


Qui-Gon Glenn

Recommended Posts

Well, this has been a long time in coming, and this is not really how I thought I would get it started, but oh well here we go. This first post will be heavily edited, so for today we will just start with the basic idea of the thread.

 

The Premise

-------------------------------------------------------------

 

I like to dabble in things, modding wise. I am not especially talented in any of them, but I guess I like the challenge of scripting, so that is where I find myself most of the time when involving myself in Holowan-style activities.

 

There are some tutorials on scripting that are quite excellent, and I have some example oriented add-on tutorials half-written for some of the superb work of tk102 and stoffe. However, scripting can be a very dry or confusing subject, and so I have always wanted to have an area where I could work out loud on the scripts I am working on, and also share smart scripts that I find or make that might be helpful. It is hopefully also a place where I can learn a few things, from the masters as well as the rooks.

 

Also, this is a place to ask for help with a script! Please though, do me a little courtesy and don't just turn this into a script request thread - I am not that skilled, and I have better things to do. However, if you are confused by something, or are having a hard time working something out, or are just stuck - share what you have, and we can try to work through it together. If I can't get it, I will bother some of my scripting mentors enough that maybe they will post a clue!

 

As I said, this post will be edited a great deal. I am starting it right now because I feel guilty to be hijacking j7's tinkering's thread :p

 

That said, the first post for now shall contain the recent little script I am working on for Force Fashion K1. I think it is a useful template for giving specific items according to class, and anyone can use it - I don't expect a credit in your ReadMe (unless I actually make new scripts for ya o_Q ) so feel free to use and alter and *improve* at will!

 

Just thought I would share this in this thread, since it is active and it does pertain to part of FFK1...

 

or I was just trying to be a shiny object. ooooooh :lol:

 

This might be a handy script for many folks, so I am sharing it here as a generic script that you can cut & paste, with simple variable name substitution. This will spawn specific items in a container according to a PC's class.

 

// qg - to spawn class-specific clothing to a container
//       9/20/2011

/* int CLASS_TYPE_SOLDIER       = 0;
  int CLASS_TYPE_SCOUT         = 1;
  int CLASS_TYPE_SCOUNDREL     = 2;
  int CLASS_TYPE_JEDIGUARDIAN  = 3;
  int CLASS_TYPE_JEDICONSULAR  = 4;
  int CLASS_TYPE_JEDISENTINEL  = 5;
  int CLASS_TYPE_COMBATDROID   = 6;
  int CLASS_TYPE_EXPERTDROID   = 7;
  int CLASS_TYPE_MINION        = 8; */

void main()
{
  object oPC=GetFirstPC();
  object oContainer=GetObjectByTag("containertag");
  int iClass=GetClassByPosition(1,oPC);

  switch (iClass) 
  {
     case 0:
        CreateItemOnObject("soldier",oContainer,1);
        break;  
     case 1:
        CreateItemOnObject("scout",oContainer,1);
        break;
     case 2:
        CreateItemOnObject("scoundrel",oContainer,1);
        break;
  }
}

 

So, there is a general example of what is going on here. I will be reserving the first post after this one, for the possibility that something actually happens here and there is a need down the road for a little organization.

 

Happy Modding :thumbsup:

 

Credits: tk102, stoffe, beancounter, RedHawke, DarthStoney, bead-v, Varsity Puppet, Pavlos, Tupac Amaru and JdNoa - I learned it from watching you, ok?!?!?!!!

Link to comment
Share on other sites

  • Replies 352
  • Created
  • Last Reply

The current script I am working on is related to an earlier script I did for j7 when we first were spawning his fantastic Sith Stalker skin. We had fun making a baby mini-mod out of it, with some basic cinematics.

 

The gist - this script will make folks "appear from nowhere" just uncloaking in your face... and I mean IN YOUR FACE, as they will attack you immediately.

 

The script will not do it all alone - your NPC would need to be spawned in however you chose and given the effect of invisibility (real easy, just add in EffectInvisibility(oYourNPC) to the spawn script), and then s/he or they (plural FTW :devsmoke:) would need a custom OnSpawn script allowing for perception to be opened. It is a simple cut&paste of the script k_def_spawn but with the "//" removed in front of the line for OnPerception events. Finally my handy script goes into the OnPerception slot of your .utc.

 

I post this script, for two reasons. One, I know it works and can be used to do several different jobs with just minor alteration. Two, I hope that someone that has used TimBob12's Populate Function will go ahead and use this custom UserDefined script for a .utc of your choice and populate the hell out of 'em. Then go ahead and warp into that area and it's a total free-for-all, but enemies will only appear as you near them.

 

The obvious test room would be the Rakatan Prison module.... Combining the two makes stealthy angry Mandalorians or Sith A.... Sneaky sith people :p appear wherever you go!

 

Custom OnSpawn:

//:: k_def_spawn01
//:: v1.0, Default On Spawn In
//:: Created By: Preston Watamaniuk, Copyright (c) 2002 Bioware Corp.

#include "k_inc_generic"
#include "k_inc_debug"

void main()
{
// WALK WAYPOINT BEHAVIORS (Comment In or Out to Activate ) ****************************************************************************
[color=darkorange]/* I cut this section out as in this use of the script it is not necessary.
  If you need to have these behaviors in for a spawn, simply use the original
  provided in scripts.bif. As it is, this script will compile and work
  just fine for this purpose, just not all purposes  */[/color]

// CUSTOM USER DEFINED EVENTS

   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1001
   GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_PERCEPTION); [color=darkorange]//[b][u][i]BEHAVIOR WE NEED - Fire User Defined Event 1002[/i][/u][/b][/color]
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_ATTACKED);         //OPTIONAL BEHAVIOR - Fire User Defined Event 1005
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_DAMAGED);          //OPTIONAL BEHAVIOR - Fire User Defined Event 1006
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_DISTURBED);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_COMBAT_ROUND_END); //OPTIONAL BEHAVIOR - Fire User Defined Event 1003
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE);         //OPTIONAL BEHAVIOR - Fire User Defined Event 1004
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_DEATH);            //OPTIONAL BEHAVIOR - Fire User Defined Event 1007
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_DISTURBED);        //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_BLOCKED);          //OPTIONAL BEHAVIOR - Fire User Defined Event 1009
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_FORCE_AFFECTED);   //OPTIONAL BEHAVIOR - Fire User Defined Event 1010
   //GN_SetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE_END);     //OPTIONAL BEHAVIOR - Fire User Defined Event 1011

// DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) *****************************************************************************************

   GN_SetDayNightPresence(AMBIENT_PRESENCE_ALWAYS_PRESENT);

   GN_SetListeningPatterns();  //This function although poorly named sets up the listening patterns and other important data for the
                               //creature it should never be removed.
   GN_WalkWayPoints();
}

Custom UserDefined:

// qg_ambush.nss
// 9-21-2011 


void main()
{
  object oSelf = OBJECT_SELF;
  effect eUncloak = EffectVisualEffect(8001);
  effect eCurrent = GetFirstEffect(oSelf);
  int nEvent = GetUserDefinedEventNumber();   // OnPerception
  ////////////////////////////////////////////// 

  if (nEvent == 1002)
  {
     while (GetIsEffectValid(eCurrent))       
     {
        if (GetEffectType(eCurrent) == EFFECT_TYPE_INVISIBILITY)    
        {
           DelayCommand(1.5, RemoveEffect(oSelf, eCurrent));
        }
        eCurrent = GetNextEffect(oSelf);
     }
     DelayCommand(2.0, ApplyEffectToObject(0, eUncloak, oSelf)); 
     ChangeToStandardFaction(oSelf, 1);
     ExecuteScript("k_ai_master", oSelf, 1005);
  }
}

Link to comment
Share on other sites

Here's a fun script structure I use quite often.

 

The Cutscene Script!

 

The basic premise behind it is that for dialogs and cutscenes, there are multiple nodes where things are going on. Instead of creating a script for each one of these nodes, you can use the slots in the dialog to specify a script, and then input a script parameter to choose which section to use.

 

void main(){

[color="Lime"]//Declare all of your variables here. You can give them values in each separate case in the switch below

//Each dialog node allows you to put in 5 pieces of information to deliver to the script.
//5 integers, with which you can do whatever[/color]
int Param1 = GetScriptParameter(1);
int Param2 = GetScriptParameter(2);
int Param3 = GetScriptParameter(3);
int Param4 = GetScriptParameter(4);

[color="Lime"]//and one String parameter, useful for putting in item templates or waypoints or whatever else[/color]
string sParam = GetScriptStringParameter();

[color="Lime"]//For the generic Cutscene script structure though, I just use Param1 to build each case[/color]
switch(Param1){
	case 0:
		[color="Lime"]//Code goes here[/color]
	break;
	case 1:
		[color="Lime"]//Code goes here[/color]
	break;
	case 2:
		[color="Lime"]//Code goes here[/color]
	break;
	case 3:
		[color="Lime"]//Code goes here[/color]
	break;
}[color="Lime"] //Keep adding cases and breaks ad nauseum[/color]
}

 

That's the general structure of the Cutscene Script. Then in the dialogeditor where you want it to run, you type the script name and the case you want to run.

 

Example:

 

[a_905sleep] [1] [ ] [ ] [ ] [________]

 

This would run case 1 from the script above.

 

Hope that was helpful.

Link to comment
Share on other sites

Hope that was helpful.

:D

 

Exactly the stuff we are looking for here! Thanks VP, I think that ultimately the second post will be a directory of the scripts made and contributed here, with a link to the specific post and code. This way, this can be a script depository, and save some searching "everywhere" by just searching here.

 

Just for clarity, is that a script that will run in either KotOR environment, or is it TSL specific?

Link to comment
Share on other sites

Well, I am not sure that I understand the question fully, without a little more background. What I think you are saying is that the non-custom party member you that is the PC's choice, you would like to be able to address this NPC generally? That is too simple I think to be what you are looking for, but the solution sure would be easy - say something generic!

 

If you are wanting to initiate a different dialog for each standard party member as the the PC choice, that can also be done in one script, although the script will be specific and not general regarding the party member NPC.

 

Looking through the Lexicon, I am finding some functions for identifying and acting on party members, but many of them are NWN specific and not available in KotOR scripting, or at least not K1. That is unimportant though, we can work around it.

 

So... I think I need a little more description Fallen!

Link to comment
Share on other sites

Well this actually relates to the walking script that I posted in my scripting mishap thread. Basically, there is one party member in your party who is mandatory. The other party member is the PC's choice. Now, if I wanted to make a script that would make the PC's choice party member walk to a certain location would I have to make separate scripts for each of the possible party member scenarios or just one that identifies anyone traveling as a henchman of the PC?

Link to comment
Share on other sites

@Fallen Guardian

If I understand your problem correctly, GetPartyMemberByIndex() is your help here. Function defines party member as object, but you don't have to give tag or anything, it'll work on whoever is party member at a time.

object oPC = GetPartyMemberByIndex(0);
object oNPC1 = GetPartyMemberByIndex(1);
object oNPC1 = GetPartyMemberByIndex(2);

The int parameter defines which party member it is; 0 is player character, 1 and 2 are other party members. Now only thing you need to figure out which one is 1 and which one is 2, but that shouldn't be too hard ;)

Link to comment
Share on other sites

Ok Fallen, I am still not sure what the problem was with our earlier stuff, so forgive me for just cut & pasting it here. Perhaps you have figured out what the problem was with the door itself.

 

While zbyl2 has presented you with a solid means to skin the cat, and one that I was not aware existed :p (thanks zbyl2!), here is another way. This compiles fine, I think the logic works, and except for the original problem this should, with minor tweaking, work for you.

 

What I would like to ask the more knowledgable - how would I subroutine-ize the repeated portion of the code, so that I could just have the main script call it twice rather than having the text there for both instances of use? I know I would need to consolidate variables by making oParty (or oParty2, being arbitrary) be assigned to the regular (non-custom) party member. I had tried to do just that, but I am doing something wrong when I try to make subroutines... I think it has to do with where I am declaring my variables :compcry:

 

Anyway, here ya go!

void main()
{
  object oPC=GetFirstPC();
  object oCustom=GetObjectByTag("p_avix");
  object oParty=GetNextPC();
  object oParty2=GetNextPC();
  object oDoor=GetObjectByTag("man26ad_door02");

  if ((oParty != oCustom) && (oParty2 != oCustom))
  {
     SendMessageToPC(oPC,"Something's screwy around here");
  }
  else
  {
     if (oParty != oCustom)
     {
        ActionPauseConversation();
        SetCommandable(TRUE,oDoor);
        SetCommandable(TRUE,oCustom);
        SetCommandable(TRUE,oParty);
        SetCommandable(TRUE,oPC);
        AssignCommand(oDoor, ActionOpenDoor(oDoor));
        ActionWait(1.0);
        AssignCommand(oPC, ActionForceMoveToLocation (Location(Vector(420.65048, 164.75064, 8.00), 0.0)));
        AssignCommand(oCustom, ActionForceMoveToLocation (Location(Vector(423.07117, 163.83559, 8.00), 0.0)));
        AssignCommand(oParty, ActionForceMoveToLocation (Location(Vector(419.32086, 165.04903, 8.00), 0.0)));
        DelayCommand(5.0, AssignCommand(oDoor, ActionCloseDoor(oDoor)));
        ActionResumeConversation();   
     }
     else 
     {
        ActionPauseConversation();
        SetCommandable(TRUE,oDoor);
        SetCommandable(TRUE,oCustom);
        SetCommandable(TRUE,oParty2);
        SetCommandable(TRUE,oPC);
        AssignCommand(oDoor, ActionOpenDoor(oDoor));
        ActionWait(1.0);
        AssignCommand(oPC, ActionForceMoveToLocation (Location(Vector(420.65048, 164.75064, 8.00), 0.0)));
        AssignCommand(oCustom, ActionForceMoveToLocation (Location(Vector(423.07117, 163.83559, 8.00), 0.0)));
        AssignCommand(oParty2, ActionForceMoveToLocation (Location(Vector(419.32086, 165.04903, 8.00), 0.0)));
        DelayCommand(5.0, AssignCommand(oDoor, ActionCloseDoor(oDoor)));
        ActionResumeConversation();   

     }
  }
} 

Link to comment
Share on other sites

What I would like to ask the more knowledgable - how would I subroutine-ize the repeated portion of the code, so that I could just have the main script call it twice rather than having the text there for both instances of use? I know I would need to consolidate variables by making oParty (or oParty2, being arbitrary) be assigned to the regular (non-custom) party member. I had tried to do just that, but I am doing something wrong when I try to make subroutines... I think it has to do with where I am declaring my variables :compcry:

 

Not sure if it's exactly what you wanted, but it doesn't have same code repeated twice anyway. Probably not the best way to do it, but it should work. I think.

void main()
{
  object oPC=GetFirstPC();
  object oCustom=GetObjectByTag("p_avix");
  object oParty=GetNextPC();
  object oParty2=GetNextPC();
  object oDoor=GetObjectByTag("man26ad_door02");

  // Define oProper object, which we'll use instead of oParty/oParty2 later.
  object oProper;

  if(oParty != oCustom && oParty2 != oCustom)
  {
     SendMessageToPC(oPC,"Something's screwy around here");
     return;
  }

  //figure out who's who
  if(oParty != oCustom) {
        oProper = oParty;
   } else {
    oProper = oParty2;
   }

      // your code, with oParty replaced by oProper.
        ActionPauseConversation();
        SetCommandable(TRUE,oDoor);
        SetCommandable(TRUE,oCustom);
        SetCommandable(TRUE,oProper);
        SetCommandable(TRUE,oPC);
        AssignCommand(oDoor, ActionOpenDoor(oDoor));
        ActionWait(1.0);
        AssignCommand(oPC, ActionForceMoveToLocation (Location(Vector(420.65048, 164.75064, 8.00), 0.0)));
        AssignCommand(oCustom, ActionForceMoveToLocation (Location(Vector(423.07117, 163.83559, 8.00), 0.0)));
        AssignCommand(oProper, ActionForceMoveToLocation (Location(Vector(419.32086, 165.04903, 8.00), 0.0)));
        DelayCommand(5.0, AssignCommand(oDoor, ActionCloseDoor(oDoor)));
        ActionResumeConversation();   

}

 

Nice thread by the way QGG - it saved me from boredom of setting up camera angles once more... need to get back to it now, though.

Link to comment
Share on other sites

Alright, I tried your script Zybl and still no luck. I have a script similar to this, except it only involves one person and it's another NPC. It has the NPC walk through a door that is opened a few seconds before he walks and it works fine, what do you think is going wrong with the script you posted?

 

EDIT: I seem to have many scripting troubles, anyway I have this script here:

 

void main() 
{

 object oJerico = GetObjectByTag("n_jercor");

  object oSpeeder = GetObjectByTag("jerico_speeder");


SetGlobalFadeOut(0.5, 1.5);

object oSound=GetObjectByTag("swoopidleloopj");
SoundObjectStop(oSound);

DelayCommand(2.4, DestroyObject(oJerico));

DelayCommand(2.4, DestroyObject(oSpeeder));

DelayCommand(3.0,SetGlobalFadeIn(0.5, 1.5));

}

 

I've been puzzling over it for about twenty minutes for one reason, and one reason alone: It won't fade in. Everything else executes except the fade in. Any ideas?

Link to comment
Share on other sites

void main() 
{

  object oJerico = GetObjectByTag("n_jercor");
  object oSpeeder = GetObjectByTag("jerico_speeder");
  object oSound=GetObjectByTag("swoopidleloopj");

  SetGlobalFadeOut(0.5, 1.5);
  SoundObjectStop(oSound);
  DelayCommand(2.4, DestroyObject(oJerico));
  DelayCommand(2.4, DestroyObject(oSpeeder));
  SetGlobalFadeIn(3.0, 1.5));

}

I think the problem there is that you were trying to double delay something. It is like adding a dimmer and dimming a lightbulb that is already on another dimmer.... it will flicker and not work properly. Just a guess, but try the new version. I simply lengthened the delay that is built into SetGlobalFadeIn to the length of your delay command.

Link to comment
Share on other sites

:yoda: Pass on what you have learned...

 

In this thread, we have discussed Fallen Guardian's walking-through-doorway-dialog. We have worked out some things, although the door behavior to my understanding is less than perfect. I need to play-test and tweak it myself perhaps to see if I can suss it out... Anywho, troubleshooting is not the discussion of this post :D

 

I have been wanting to use "subroutines" in my code writing, but was not 100% sure how to implement them, having failed numerous times with close guesses and not-so-close ones, at how to accomplish this task properly. It mostly comes down to how you can pass variables between the "main" function and the "sub" function. What TimBob was able to show me was that what had been my goal was not wholly satisfied, yet potentially very useful.

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

For starters, I am going to borrow a portion of an excellent starter tutorial done by tk102 (one of many BTW), in this thread. Especially this part, and I quote tk102 without tags here solely for easier reading:

 

Function declaration

Parenthesis present, equals sign absent

object CreateItemOnObject(string sItemTemplate, object oTarget, int nStackSize);
^      ^                  ^                     ^               ^
|      |                  |                     |               |- an integer parameter  
|      |                  |                     |- an object parameter
|      |                  |-a string parameter
|      |-the function
|-data type of what the function returns (an object)[color=darkorange][i] or void if it is an action script[/i][/color]

I place this here so that those less familiar with this discussion can bone up on the basic function of the function :p One thing tk didn't mention here is that you can also make your function "void". Void means that it returns no data at all - it simply does ACTION in the script. Usually, when we write code, we use just one actual function, and so if it is a void function, we use

void main()

However, in the case I was investigating, I needed a subroutine, also void, separate from the main. Why? The logic works simpler, less substitution of variables, etc... you'll see! This is a bit repetitious, but the following is the code we had quasi-working earlier in this thread. Quasi in that the door was still not 100% compliant.

void main()
{
  object oPC=GetFirstPC();
  object oCustom=GetObjectByTag("p_avix");
  object oParty=GetNextPC();
  object oParty2=GetNextPC();
  object oDoor=GetObjectByTag("man26ad_door02");

  if ((oParty != oCustom) && (oParty2 != oCustom))
  {
     SendMessageToPC(oPC,"Something's screwy around here");
  }
  else
  {
     if (oParty != oCustom)
     {
        ActionPauseConversation();
        SetCommandable(TRUE,oDoor);
        SetCommandable(TRUE,oCustom);
        SetCommandable(TRUE,oParty);
        SetCommandable(TRUE,oPC);
        AssignCommand(oDoor, ActionOpenDoor(oDoor));
        ActionWait(1.0);
        AssignCommand(oPC, ActionForceMoveToLocation (Location(Vector(420.65048, 164.75064, 8.00), 0.0)));
        AssignCommand(oCustom, ActionForceMoveToLocation (Location(Vector(423.07117, 163.83559, 8.00), 0.0)));
        AssignCommand(oParty, ActionForceMoveToLocation (Location(Vector(419.32086, 165.04903, 8.00), 0.0)));
        DelayCommand(5.0, AssignCommand(oDoor, ActionCloseDoor(oDoor)));
        ActionResumeConversation();   
     }
     else 
     {
        ActionPauseConversation();
        SetCommandable(TRUE,oDoor);
        SetCommandable(TRUE,oCustom);
        SetCommandable(TRUE,oParty2);
        SetCommandable(TRUE,oPC);
        AssignCommand(oDoor, ActionOpenDoor(oDoor));
        ActionWait(1.0);
        AssignCommand(oPC, ActionForceMoveToLocation (Location(Vector(420.65048, 164.75064, 8.00), 0.0)));
        AssignCommand(oCustom, ActionForceMoveToLocation (Location(Vector(423.07117, 163.83559, 8.00), 0.0)));
        AssignCommand(oParty2, ActionForceMoveToLocation (Location(Vector(419.32086, 165.04903, 8.00), 0.0)));
        DelayCommand(5.0, AssignCommand(oDoor, ActionCloseDoor(oDoor)));
        ActionResumeConversation();   

     }
  }
}

If you look at the code, you will notice that most of the action and :words: are in the conditional statement of the script. Sandwiching the inside else are two segments of almost identical code. I felt entitled to type less and just have to do it once. What I tried to make happen was not working, as I was, amongst other things, not declaring variables correctly in the naming of the function. TimBob12 was kind enough to work with me on this matter, and with my interjections in orange, this is what he showed me:

Variables cannot be shared between functions and main unless declared between the parenthesis of the function name. For this to work it must be declared in the initial function. This also allows custom variables to be used just by putting them straight into the function rather than declaring them (if that makes sense)It does make sense, now!

 

Some variables can be placed straight in the function such as GetFirstPC(); as the parameters for these never change..

 

These then get set with custom values. Indeed, pay attention to the use of iCustom vs oCustom in the code... I think of it as an inCustom and an outCustom, just shortened to i/o.

 

Here is the completed script that compiles with no errors and should work fine I have tweaked it a bit for further simplicity by passing a third variable directly into the sub, eliminating the need for some of the variables TB12 had declared in the subroutine, and eliminating a variable substitution in the main

 

void doorwalker(object iCustom, object iParty, object iDoor);

void doorwalker(object iCustom, object iParty, object iDoor)
{
  object oPC = GetFirstPC();
  object oCustom = iCustom;
  object oDoor = iDoor;
  object oParty = iParty;

  ActionPauseConversation();
  SetCommandable(TRUE,oDoor);
  SetCommandable(TRUE,oCustom);
  SetCommandable(TRUE,oParty);
  SetCommandable(TRUE,oPC);
  AssignCommand(oDoor, ActionOpenDoor(oDoor));
  ActionWait(1.0);
  AssignCommand(oPC, ActionForceMoveToLocation (Location(Vector(420.65048, 164.75064, 8.00), 0.0)));
  AssignCommand(oCustom, ActionForceMoveToLocation (Location(Vector(423.07117, 163.83559, 8.00), 0.0)));
  AssignCommand(oParty, ActionForceMoveToLocation (Location(Vector(419.32086, 165.04903, 8.00), 0.0)));
  DelayCommand(5.0, AssignCommand(oDoor, ActionCloseDoor(oDoor)));
  ActionResumeConversation();   
}

void main()
{
  object oPC = GetFirstPC();
  object oCustom = GetObjectByTag("customnpctag");
  object oParty = GetNextPC();
  object oParty2 = GetNextPC();
  object oDoor = GetObjectByTag("man26ad_door02");

  if (oParty != oCustom && oParty2 != oCustom)
  {
     SendMessageToPC(oPC, "Something's screwy around here");
  }
  else
  {
     if (oParty != oCustom)
     {
        doorwalker(oCustom, oParty, oDoor);
     }
     else 
     {
        doorwalker(oCustom, oParty2, oDoor);
     }
  }
}

So, as you can see, there is still a lot of code there, but perhaps the potential in a larger script for a little more elegance, if that is important to you at all. More importantly, the logic of the main code is simpler and more natural. In a larger script with repetitive behaviors, this kind of sub-routine is exactly what you might like to have lying around for many different NPC's to use as a basis for there environmental behavior.

 

What I somehow missed was what it is I was actually making here... it is an #include file, if I chose to make it one. In this specific a case, I think it is a one-off, and the original code to many folk is actually simpler code, and works equivalently, so this is not necessarily the preferred means. It is however essential stuff for those of you who are trying to find new or better ways to skin a cannok. I only realized this though, when I read the following:

You can put the doorwalker function in a different file name doorwalker.nss, put it in your overide and then #include "doorwalker".

Derp!

 

:lol:

Anyways, I hope that some of you found this helpful, or at least interesting. I know that I learned a bit, thanks again to TimBob12 for taking the time to thoughtfully respond to my call!!

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.


×
×
  • Create New...