lfnetwork.com mark read register faq members calendar

Thread: Creating Custom Functions
Thread Tools Display Modes
Post a new thread. Indicate all threads in this forum as read. Subscribe to this forum. RSS feed: this forum RSS feed: all forums
Prev Previous Post   Next Post Next
Old 10-04-2011, 02:17 PM   #1
Qui-Gon Glenn
Necessary Roughneck
 
Qui-Gon Glenn's Avatar
 
Join Date: May 2007
Location: Thessia
Posts: 1,467
Current Game: ME3MP, Arkham Origins
Folder extraordinaire Helpful! Forum Veteran Veteran Modder 
Creating Custom Functions

Originally posted by Me with a lot of help from TB12!

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

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
Code:
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) or void if it is an action script
I place this here so that those less familiar with this discussion can bone up on the basic function of the function 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
Code:
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.
Code:
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 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:

Code:
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:
Derp!


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!!


Want to play a game of ME3MP?
Qui-Gon_Glenn on the software of which we shall not name.... add me and the enemy shall fall in chunks of crimson salsa
Qui-Gon Glenn is offline   you may: quote & reply,
Post a new thread. Indicate all threads in this forum as read. Subscribe to this forum. RSS feed: this forum RSS feed: all forums
Go Back   LucasForums > Network > Knights of the Old Republic > Editing / Modding > Holowan Laboratories > Tutorials: Scripting > Creating Custom Functions

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 10:34 AM.

LFNetwork, LLC ©2002-2011 - All rights reserved.
Powered by vBulletin®
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.