Aller au contenu

Photo

module size


  • Veuillez vous connecter pour répondre
37 réponses à ce sujet

#1
acomputerdood

acomputerdood
  • Members
  • 219 messages
so, my module is just over 100 meg, and i'm near the 16k toolset limit.  i'm curious because i've heard that there are a LOT of modules much bigger than mine and are not having this problem.  i just wanted to post some of my stats here to get an idea how mine compared to others.

first, a bit of background.
- we don't use any haks other than CEP (which doesn't count towards the resource limit - from what i understand).
- i feel that we have a lot of custom content, but i really have no idea how it compares to other worlds.
- i inherited the module, so i don't fully 100% understand all of the legacy code in there.
- the previous developer's (developers') coding practices i don't fully 100% agree with (lots of code duplication, many 1 purpose scripts instead of code reuse, etc.  i just went through and replaced about 200 unique scripts to open a merchant shop and replaced them with 1 script to read a variable on the NPC to know which shop to open).

anyway, the stats.  i opened up the module in the toolset, and then copied the whole temp0 directory over to my linux box so i could run word count on various things (listed in the order i think are most bloated):

$ ls -l *.nss |wc
   3747   33723  244443

$ ls -l *.ncs |wc
   3579   32211  233394

$ ls -l *.uti |wc
   2842   25578  180246

$ ls -l *.utp |wc
   2302   20718  150320

$ ls -l *.utc |wc
   1688   15192  108874

$ ls -l *.dlg |wc
    314    2826   20020

$ ls -l *.are |wc
    437    3933   29083

$ ls -l *.gic |wc
    437    3933   28646

$ ls -l *.git |wc
    437    3933   29520

oh, and by the way - the first column in each output is the number of files in the directory with that filename suffix.  for example, my temp0 directory had 3747 .nss files in it.  so my totals would be:

- 3747 text scripts
- 3579 compiled scripts
- 2842 items
- 2302 placeables (wow, that does seem high)
- 1688 creatures
- 437 areas (i don't think this is all that many, right?)
- and some other stuff


i was surprised that .nss and .ncs didn't match, but i relalize it's probably because of the various include files that don't actually get complied themselves.

anyway, i guess i'm looking for a comparison to other modules.  i'd love to reduce my resources further, but wanted to get an idea of how i compared to others first.  i read that i could package a bunch of stuff up into another .hak (that was only serverside?), but i'm hoping to avoid doing stuff like that.

i know there is a TON of unused code in there, and i have been advised that the "unused x" tixbox in the build window is a crock of poo.  in another thread, it was suggested that i write myself a letoscript and run it through moneo to cross reference everything.  that is an option, but there's a learning curve associated with it that i didn't want to tackle yet.  anybody else have some good tips?

Modifié par acomputerdood, 04 mai 2012 - 12:10 .


#2
The Amethyst Dragon

The Amethyst Dragon
  • Members
  • 1 875 messages
Any blueprints you don't plan on changing anytime soon you can put into the server copy of cep2_custom.hak...placeables, creatures, items, merchants, triggers, sounds... If you're already using CEP, that hak should be there, and players should have an empty copy of it (so they don't have to download another hak to play).

Script files can also go into that same server-side hak. You'll want to make sure ones you put in there are ones you don't plan on changing anytime soon, since you'd have to extract them from the hak, import them back into the module, then edit them to get an changes to take. Hak resources take precedence over module resources.

Just be sure to use the same cep2_custom.hak file on the computer you're building on, so it's all still accessible in the toolset.

Keep in mind that while it will reduce the number of files contributing to the 16k limit on module resources, this will not reduce the number of blueprints in the game palette that contributes to the other 16k limit that can cause the DM client to crash.

#3
ehye_khandee

ehye_khandee
  • Members
  • 855 messages
These are the current specs on our BETA TEST module ArgentumRegio: City of Dohral. This module is quite possibly "huge", but I'll let you folks judge. It was built from the ground-up to run lean and efficient ... like the OP, I'm a fiend for code that avoids needless repetition and re-uses code where possible. We have moved a few things into our 'top' hak (stuff that was considered 'done'). In total, the module is 15834 items, and so we are due to move more 'completed works' into the hak soon. Unpacked, this module weighs in at [gulp] 190mb.

Areas: 1337+ (49mb total)
.dlg: 394 (8.63mb total)
.ncs 3971 (21.2mb total)
.nss 4081 (12.6mb total)
.utc 1199 (7.0mb total)
.uti 1021 (1.36mb total)
.utp 730 (1.66mb total)

... 'and some other stuff'. Due largely to very frugal coding, the module runs with no lag, no crashes, and no need to reset (e.g. as by lag buildup) - I once left it run for over a month with no crashes.

The nwn engine is an amazing tool. It's been ten years I've tinkered with this thing and I'm still gobsmacked.

Best wishes to all builders.

Be well. Game on!
GM_ODA
http://playnwn.com

#4
acomputerdood

acomputerdood
  • Members
  • 219 messages
i did some tinkering with grep and the unpacked module's temp0 folder. i mainly am now focusing on scripts that aren't needed.

i know the toolset's "unused script" checkbox is worthless (well, nearly so). i actually assumed that stuff NOT in the list was absolutely necessary. that is, stuff IN the list MIGHT not be used - so at the very least, it's a starting point.

i browsed the list quickly until i found a script that i KNEW was being used somewhere - specifically one that was on a custom creature not painted into an area. i did a "grep SCRIPTNAME temp0/*". lo and behold, the creature i knew the script was attached to (and a bunch of others) was in my output.  conversely, a script that i'd never heard of came up with an empty result for grep.

this confirmed to me that i could be using grep on the filenames to detect scripts that weren't anywhere in the module. a few perl scripts later, and i've got a new list (that's a subset of the toolset's ouput) of scripts that i'm pretty darn sure truly aren't being used in the module.

hmmm, now that i think about it, i should probably run my perl script against the CEP .hak files?  never actually worked with those.  can i just open them in the toolset?  what about internal bioware functions? how could i check those?

Modifié par acomputerdood, 04 mai 2012 - 05:16 .


#5
acomputerdood

acomputerdood
  • Members
  • 219 messages
again, poking through my temp0 folder, i see a bunch of creatures that i'm sure we didn't make. do the standard CEP creatures get saved into the temp0 folder as well? i had assumed that they would be read from the hak file? wouldn't the not count towards the limit then?

#6
ehye_khandee

ehye_khandee
  • Members
  • 855 messages
The stuff in haks does NOT get unpacked into the temp folder, you are correct.

This is likely not needed (judging by your username) but still - make a backup before you start plucking things out of your module - just to be safe.

#7
acomputerdood

acomputerdood
  • Members
  • 219 messages
is there an easy way to compare the creatures in the hak file to those in the module? i guess i could somehow unpack the hak and diff the files. i guess there are other utilities that will open up the .utc files, too.

#8
ehye_khandee

ehye_khandee
  • Members
  • 855 messages
The hak version overrides all else, so the version in your module is not actually being used if you have a version in your hak.

Hope that helps.

#9
acomputerdood

acomputerdood
  • Members
  • 219 messages
well, just to update anybody who cares on my quest here:

i have mixed feelings about the "grepping for unused scripts". we use a wild magic system, so each spell has been re-written to include a check for the wild magic override function. each of these scripts has been flagged as unused (by both the toolset and grep) because (i presume) the game calls them with internal functions, rather than directly.

maybe i can find a way to look in there. i tried grepping the whole directory, hoping maybe it was in the data/*.bif files, but nothing came up. maybe they're compressed weird. the string did, however, come up in the chitin.key, xp1.key and such. what are those files for?

other than the files that replace internal nwn ones, i'm actually pretty confident the other ones are truly not used. i also realized that some scripts are being "used" by conversations which they themselves aren't used. so i guess there's really an order of operations i should be working with, most likely starting with conversations. if i were looking to remove creatures (which i'm not), i would probably want to start with those.

#10
acomputerdood

acomputerdood
  • Members
  • 219 messages
i've continued to chop away at the scripts, and i'm getting pretty confident in knowing which files can be deleted. as previously noted, it doesn't seem to be reliable for re-writes of bioware spells (or other re-writes of bioware scripts). i'm continuing with my assumption that it's because they're called internally by the game engine and not by something controllable in the toolset.

so far, i've reduced the resource count from ~16300 (i know!) down to 15666. i still have several hundred scripts listed that i can go through. there's also a compounding effect - some scripts are marked as "used" because they are referenced in an unused script. after the first cut, recompiling an unused script list will then flag those ones, and so forth.

another way to do do it would be to grab each script name out of the temp0 folder and count the number of references in the other files. i suppose there's really no reason to start with the toolset's "unused scripts" check.

i also realized that even with the waypoint spawning system, i can check creature resrefs against the area.git files to see if they're in a waypoint. this, of course, is assuming my spawning system is "standard" where you put the resref of the creature in the "name" of the waypoint and the onenter script spawns them.

and just opening up the .git file in a hex editor, you can easily see the structure of it and the waypoints inside it. it should be pretty trivial to write some scripts to pull this information out. i've seen some tools do this using windows and java, but really nothing for linux and certainly not with perl scripts.

this would let me cross reference the palette with what's actually inside the module. though, i doubt i'll really delete too many creatures from the module. i like having options when i spawn stuff.

another thing i should look into is crawling through my creature/item/placeable blueprints to see where they came from. i see that many in the palette came from the CEP haks, but it seems there are thousands more that were created in the module.

#11
Leurnid

Leurnid
  • Members
  • 271 messages
I am not going to be any help, but I have a question just the same:
Outside of scripts (that I know of), don't only the things on the Custom menus that are not in a HAK count against the 16000 resources?

If that is true, then you could just load builder resources into a HAK and cut down on the count, if I understand this correctly.
If I am mistaken about that, I am still fairly sure you can move resources you don't need to place dynamically while the module is running into a builder only HAK, then when loading the module to build, you add the builder hak, and unload it before saving the server copy...

Like I said, probably no help at all, but I have been watching this thread for a while hoping to learn a few things, and these are some things that sprang to mind.

#12
acomputerdood

acomputerdood
  • Members
  • 219 messages
correct. that's the easy way out. but that would be cheating! hahaha

this has turned into an attempt to figure out how everything is working together, and see if i can develop some tools to cut down on duplication.

#13
acomputerdood

acomputerdood
  • Members
  • 219 messages
so, a (VERY!) simple version of the cross-referencer.pl script i was talking about is as follows:

#!/usr/bin/perl


$DIR = shift;
if($DIR eq ""){
$DIR = "temp0";
}

$OUTPUT = shift;
if($OUTPUT eq ""){
$OUTPUT = "output";
}

`mkdir -p $OUTPUT/unused`;


opendir(TEMP0, $DIR) or die "can't open $DIR";
while(readdir TEMP0){
next if /^\\./;

$filename = $_;
($file, $suffix) = split /\\./;

&check($filename, $file);
}


sub check{
$filename = shift;
$file = shift;
$outputfile = "$OUTPUT/$filename" . ".txt";
$unused = "$OUTPUT/unused/$filename" . ".txt";
print "$filename\\n";


$ret = `/bin/egrep -i --exclude $DIR/$filename $file $DIR/*`;
if($ret){
`echo '$ret' > $outputfile`;
}else{
`echo $filename > $unused`;
}
}


this just takes every file in the temp0 directory, strips off the file extension (to get the resref of the resource), and then checks that resref against every OTHER file (not including itself) to see if it's referenced anywhere.

this should do about as good as the toolset for scripts and dialogs i think, but creatures and items is a huge improvement i think. this will catch the resrefs of items, placeables, and creatures inside of waypoints inside of area files. this is a definitely improvement over what the toolset can accomplish.

anyway, it's very basic right now, but i'm thinking of ways i can add more intelligence to it. it's also not out of the question to start graphing dependencies between all the "resource nodes". that would be a good way to tell if there are "circular dependencies". like if a dozen scripts all reference eachother, but none of them are actually called by anything else, they're still useless.


well, that sounds like a nice place to start next.

#14
acomputerdood

acomputerdood
  • Members
  • 219 messages
i did it!

i modified my perl script above to print stuff out to a slightly different format and used graphviz to read in the data to produce a chart:

http://www.dalakora....s/resources.svg
(trust me, it's there - scroll around a little)

it's pretty ugly to read, but it's at least possible. i limited the number of files to process to only the first 1000, and the script took maybe an hour to run and 12 minutes to render in graphviz. all 16000 files ran over night in the perl script and the rendering would take several orders of magnitude longer i would guess.

i'll run some more tests and clean things up a bit more to see what kind of results i get next.

Modifié par acomputerdood, 15 mai 2012 - 01:40 .


#15
acomputerdood

acomputerdood
  • Members
  • 219 messages
well, i was pretty excited about generating a gigantic map of all the resource nodes in my module and mapping them all out - hell, perhaps i could find a plotter to print it out on and wallpaper my room with it!

but when i try to generate the graph for all 15,000+ resources, graphviz crashes on me. :(

so it's either i need to go back to regular, non-visual analysis or come up with a different way.

#16
_Guile

_Guile
  • Members
  • 685 messages
I had a lot of scripts in my conversations, which, you sir, having - 3579 compiled scripts, seems like a bit much, so I'll make this recommendation.  You can bring all scripting for ALL conversations together in very simple to use include(s), using 2 main includes to return the function needed using switch/case statements.
----------------------------------------

This is the Template Script I created and use for my module (this is the Set Line Option Main Function, for ActionTaken Events)

NOTE:

You can remove these includes, and make your own...

#include "gen_cs_functions"

#include "gen_cs_config"

ALSO, you should remove any custom functions I have within the code of all scripts, sorry didn't have the original template, as I started coding with this template right away...

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

// Script Name: gen_cs_act_inc   (Action Taken Include)
//////////////////////////////////////////////////////////////////////////////
// Created By: Genisys / Guile
// Created On: 10/3/2011
// Contact At: galefer003@hotmail.com
/////////////////////////////////////////////////////////////////////////////
/*
   This Include serves a destinct purpose, it reads the variable on the PC
   to find out which conversation the PC is in & which section they are in
   and also which line they have selected, as this system can be used
   in ANY Conversation in your entire module (integration required).

   this script basically handles ALL Action Taken Event for ALL Conversations
   which utilize the Genisys Custom Conversation System (gen_cs)

   REMEMBER TO DELETE ANY CASE STATEMENTS YOU ARE NOT USING TO AVOID CONFUSION!
*/
/////////////////////////////////////////////////////////////////////////////
//Required Includes

// This is the include you will put all prototype functions within, it will be
// how you save A LOT of space in this script so that you can read it faster.
// it also serves to allow other parts of this script to access the prototypes.
// ANY OTHER INCLUDES should be attached to (gen_ccs_func) NOT THIS SCRIPT!
// As all includes that are part of this system will access (gen_css_func)
#include "gen_cs_functions"
////////////////////////////////////////////////////////////////////////////////

//Declare the ONLY Prototype in this script

//object oPC = GetPCSpeaker();   (ALWAYS!)
//nSection is which section they are in THIS convesation (set by gen_cs_sect_#)
//nLine = The Line they have selected in the conversation
void GetLineActionTaken(object oPC, int nLine);
////////////////////////////////////////////////////////////////////////////////
//Define the Prototype
void GetLineActionTaken(object oPC, int nLine)
{
 //Which convesation is the PC in?
 int nConv = GetLocalInt(oPC, "GEN_CS_CONV");

 //Which section in the conversation is the PC at..
 int nSection = GetLocalInt(oPC, "GEN_CS_SECTION");

 //For Ease of Scripting we will predefine oNPC
 // NOTE: oNPC can be the object the conversation is attached to as well!
 object oNPC = OBJECT_SELF;

 //Declare All Major Variables Here (ones you will use a lot)
 object oItem;
 int nInt, nAdj, iSlot;
 effect eVis, eEffect;

//------------------------------------------------------------------------------
//Which conversation are we in?
switch(nConv)
{
////////////////////////////////////////////////////////////////////////////////
 case 0: { //For Conversation 0 (Template Conversation)
//------------------------------------------------------------------------------

  //Which Section is the PC in, in THIS conversation?
  switch(nSection)
  {
   //--------------------------------------------------------------
   case 1: //Always the First Section of the Conversation
   {
    //------------------------------
    switch(nLine)
    {
     //----------------
     case 0: //This is the Action Taken Event for the NPC's Text Line!
     {
      //Enter Code Here..
     }break;
     //----------------
     case 1: //The First line of the First Section of THIS Conversation
     {
       //Enter Code Here..
     }break;
     //----------------
     case 2: //The Second line of the Frist Section of THIS Conversation
     {
       //Enter Code Here..
     }break;
     //----------------
     //etc...

    //-----------------------------
    } //END switch(nLine)

  //----------------------------------------------------------------
   }break;  //END case 1 (section 1)
  //----------------------------------------------------------------
   case 2: {  //For Section 2...
  //----------------------------------------------------------------

  //Enter code Here

  //----------------------------------------------------------------
   }break; // END Section 2 (case 2)
  //----------------------------------------------------------------
   case 3: {  //For Section 3...
  //----------------------------------------------------------------

  //Enter code Here

  //----------------------------------------------------------------
   }break; // END Section 3 (case 3)
  //----------------------------------------------------------------
  //etc...

  //END switch(nSection)
  }

//------------------------------------------------------------------------------
 } break; //End Conversation 0
////////////////////////////////////////////////////////////////////////////////
 case 1: {  //For Conversation 1
//------------------------------------------------------------------------------

// Enter Code Here

//------------------------------------------------------------------------------
 }break; //End Conversation 1
////////////////////////////////////////////////////////////////////////////////
 case 2: {  //For Conversation 2
//------------------------------------------------------------------------------

 //Enter Code Here

//------------------------------------------------------------------------------
 }break;  //End Conversation 2
////////////////////////////////////////////////////////////////////////////////
 case 3: {  //For Conversation 3
//------------------------------------------------------------------------------

  //Enter Code Here

//------------------------------------------------------------------------------
 }break;  //End Conversation 3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

//ETC....


////////////////////////////////////////////////////////////////////////////////
 } //End switch(nWhich) /i.e. which conversation we are in...
////////////////////////////////////////////////////////////////////////////////
} //End Protoypes
////////////////////////////////////////////////////////////////////////////////

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

This is the include for the Starting Conditional Scripts for all conversations...

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

// Script Name:  gen_cs_sc_inc
//////////////////////////////////////////////////////////////////////////////
// Created By: Genisys / Guile
// Created On: 10/3/2011
// Contact At: galefer003@hotmail.com
/////////////////////////////////////////////////////////////////////////////
/*
   This is the Include Script where you place ALL of your starting conditional
   checks for ALL Conversation for Every Line which uses the (gen_ccs_cs_#)
   scripts. Where # = the Line we are checking...
*/
/////////////////////////////////////////////////////////////////////////////
//Where all of the Custom Functions are placed
#include "gen_cs_functions"

//There is one special function in this script you definitely want to read about!
//  GEN_SPEC_CONDITION(nInt);  <<< This reduces scripting redundancy in THIS SCRIPT!
#include "gen_cs_config"
/////////////////////////////////////////////////////////////////////////////
// The Main Function of this script...

//nLine = the # of (gen_cs_sc_#)
int GetStartingConditionals(object oPC, int nLine);

//Custom Prototype for checking ALL Starting Conditionals in ALL Conversations!
int GetStartingConditionals(object oPC, int nLine)
{
 //Declare any additional Variables Needed Here
 //for example..
 object oNPC = OBJECT_SELF;
 int nInt, nAdj;
 float fFloat, fAdj;

//------------------------------------------------------------------------------
 int iSee = FALSE; //This will be returned to the gen_css_sc_# script(s)
 //By default the PC wilL NOT see the line unless you use the following function
 //in your starting conditional Code (if you want them to see the line that is)
 // e.g.  iSee = TRUE;

 //This tells use which Conversation we are in
 int nConv = GetLocalInt(oPC, "GEN_CS_CONV");

 //This tells us which section they are in every conversation..
 int nSect = GetLocalInt(oPC, "GEN_CS_SECTION");

//------------------------------------------------------------------------------

//Which Conversation are we working with here?
switch(nConv){
////////////////////////////////////////////////////////////////////////////////

case 0: { //For the Template conversation  (FOR EXAMPLE ONLY)
//------------------------------------------------------------------------------
 switch(nSect) { //Which Section in the conversation are we looking at?
 //---------------------------------------------

  case 1: //Section 1 (first section in every conversation)
  {

   switch(nLine){ //Which Line are we checking?
   //-----------------------------------
   case 1: //Line 1
   {
     //Example use of special function
     return GEN_SPEC_CONDITION(4); //DM's can only read this line..

     //Enter Starting Condtional Code for Line 1 here...

   } break;//END Case 1 (Line 1)
   //---------------------------

   case 2:  //Line 2
   {

   //Enter Starting Condtional Code for Line 2 here...

   } break;//END Case 2 (Line 2)
   //---------------------------

   case 3: //Line 3
   {

   //Enter Starting Condtional Code for Line 3 here...

   } break;//END Case 3 (Line 3)

   //etc. ---------------------

   //------------------------------------
   } //END switch(nLine)

  } break; //End Case 1 (Section 1)
  //------------------------------------------------------------------------------
  case 2: //Section 2
  {


  } break; //End Case 2 (Section 2)
  //------------------------------------------------------------------------------
  case 3: //Section 3
  {

  } break; //End Case 3 (Section 3)

  //------------------------------------------------------------------------------

  //etc...

////////////////////////////////////////////////////////////////////////////////
 } //End switch(nSect)
}break; //END case 0: (conversation 0)
////////////////////////////////////////////////////////////////////////////////
case 1: { //conversation 1   (YOUR Conversation)
// -----------------------------------------------------------------------------

//enter code here...

//------------------------------------------------------------------------------
 }break; //END case 1 (conversation 1)
////////////////////////////////////////////////////////////////////////////////
case 2: { //conversation 2   (YOUR Conversation)
// -----------------------------------------------------------------------------

//enter code here...

//------------------------------------------------------------------------------
}break; //END case 2 (conversation 2)
////////////////////////////////////////////////////////////////////////////////

//etc...

////////////////////////////////////////////////////////////////////////////////
} //END switch (nConv)
////////////////////////////////////////////////////////////////////////////////

 //Special Option (if you want the DMs to ALWAYS see ALL Lines in ALL Conversations
 // delete the comment marks ( // ) below

 // if(GetIsDM(oPC) || GetIsDMPossessed(oPC)) { i = TRUE; }

 //Now tell the conversation which lines to show!
 return iSee;

////////////////////////////////////////////////////////////////////////////////
}//Prototype End
////////////////////////////////////////////////////////////////////////////////
/*

NOTES:

When you are finished integrating multiple conversations into this system
this may very well reach into the thousands of lines, but do not fret, this
system is extremely simple to use once you get the hang of it!

you can also use attention lines if you are working on a section (for example)

//################ WORK IN PROGRESS ##################  etc...

This helps you find what you are working on quickly!

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

These Two scripts are examples on how to implement the System
First the Set Line Option

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

// gen_cs_sla_1
///////////////////////////////////////////////////////
// Created By: Genisys / Guile
// Created On: 10/12/2011
///////////////////////////////////////////////////////////////////////////////
// This script is part of the Genisys Custom Conversation System
///////////////////////////////////////////////////////////////////////////////
//Required Include
#include "gen_cs_act_inc"
////////////////////////////////////////////////////////////////////////////////
//Main Script..
void main()
{
  object oPC = GetPCSpeaker();

  //Do the Action Taken set in (gen_cs_act_inc) script.
  GetLineActionTaken(oPC, 1);
}

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

For Checking Starting Conditionals...

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

// gen_cs_sc_1

// Designed by Genisys for his Custom Conversation System

//Required Include (This is where you place the Starting Conditionals)
#include "gen_cs_sc_inc"

int StartingConditional()
{
   object oPC = GetPCSpeaker();

   //Check the Starting Conditionals for this line

   return GetStartingConditionals(oPC, 1);
}

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

Even if you don't use this, I hope someone can..  :wizard:


NOTE TO THOSE HACKERS OUT THERE< that is NOT my email address =]

Modifié par _Guile, 19 mai 2012 - 05:29 .


#17
_Guile

_Guile
  • Members
  • 685 messages
The scripts "gen_cs_sla_1" & "gen_cs_sc_1" are templates, and will need to be incremented (e.g. 1 to 2)

That includes Names of Scripts  & Numbers in Functions

You will need to set the Conversation # in the Conversation & Set the Section Number in the Conversation as well..

You would use the NPC line (red) to set these functions:

Here are some templates for that...

Please NOTE that gen_cs_conv_0 set's the Section # to 1!
Therefore you will want to start with Section 2 in the NEXT Section of the conversation...

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


// Script Name: gen_cs_conv_0  (This is a Template Script!!)
//////////////////////////////////////////////////////////////////////////////
// Created By: Genisys / Guile
// Created On: 10/3/2011
// Contact At: galefer003@hotmail.com
/////////////////////////////////////////////////////////////////////////////
/*
   This script goes in the very first Line (The first red NPC Text Line)
   This is the first ActionTaken Event Script which must go in EVERY
   Conversation which will use this custom system, however every conversation
   needs it's own version of this script!  Therefore, if this is the First
   conversation that you have created that will use this system, this script
   will need to be renamed (gen_cs_conv_1) and you will need to change
   int nConv = 0; to nConv = 1 below...

  ### REMEMBER TO SAVE THIS SCRIPT UNDER A NEW NAME BEFORE YOU EDIT IT! ###
*/
/////////////////////////////////////////////////////////////////////////////
// CRITICAL SETTTING
//Set This to the Conversation Number you will be using for THIS Conversation!
int nConv = 0;  //Default = 0 (The GEN_CS Template Conversation)

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

//###########################################################################
// ### WARNING ### DO NOT ALTER ANYTHING BELOW THIS LINE!!!
//###########################################################################

//Main Script
void main()
{
  object oPC = GetPCSpeaker();

//----------------------------------------------------------------------------

  //Always give the conversation time to set variables!
  ActionPauseConversation();

  //Tell the includes which conversation we are in!
  SetLocalInt(oPC, "GEN_CS_CONV", nConv);

  //Set that we are on the first section
  //This is incremented by +1 every time a PC selects a line
  SetLocalInt(oPC, "GEN_CS_SECTION", 1);  //Always start at Section 1

//------------------------------------------------------------------------------

  //Your Code would go here... (If needed)

//------------------------------------------------------------------------------

  //Resume the Conversation after a very short delay
  DelayCommand(0.3, ActionResumeConversation());

////////////////////////////////////////////////////////////////////////////////
} //End Main Script


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


// Script Name: gen_cs_sect_2
//////////////////////////////////////////////////////////////////////////////
// Created By: Genisys / Guile
// Created On: 10/12/2011
// Contact At: galefer003@hotmail.com
/////////////////////////////////////////////////////////////////////////////
/*
   This script tells all other script which part of the conversation
   the PC is working with, and what the scripts should do...

   We start with Section 2 because (gen_cs_conv) always sets section 1!
   this must go on EVERY NPC Line where you intend to use scripts
   you DO NOT have to go in any particular order if YOU can remember
   which section you are scripting for, truly, however it's best to build
   the conversation entirely first, then start scripting it!
*/
/////////////////////////////////////////////////////////////////////////////
//Required Include
#include "gen_cs_act_inc"
////////////////////////////////////////////////////////////////////////////////
//Don't Touch anything below!
void main()
{
  object oPC = GetPCSpeaker();

  //Always Pause the Covnersation for a short delay to give the scripts
  //time to check everything! (I Tested this, it works wonders!)
  //This can only be done on the Red / NPC Lines!!!!
  ActionPauseConversation();

  //This tells are scripts which section we are on, specifically!
  SetLocalInt(oPC, "GEN_CS_SECTION", 2);

  //Do the Action Taken set in (gen_cs_act_inc) script FOR THIS NPC LINE!!!
  GetLineActionTaken(oPC, 0);

  //Resume the Conversation after a very short delay
  DelayCommand(0.3, ActionResumeConversation());
}

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

Sorry for the double post, but I didn't feel like adding this to the first post....  :unsure:

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

Needlesstosay, there are Pros and Cons to using  a system like this...

Pros:

This system can take 2000++ Conversation scripts and reduce it to about 200 OR LESS scripts...
Code is very efficient, though I'd recommend using Pause/Resume Conversation() functions
in the SetConveration# or Set Section Number Scripts, that gives time for starting conditionals to be checked...
(Otherwise the starting conditionals may not all get checked fast enough...)

Cons: (Other than the above con mentioned about Starting Conditional Checks)

It will take you a loooooong time to bring all the functions into the includes, then even more time to test everything to ensure you didn't make any mistakes. (weeks if not months!)

It will take you much longer to build the module, consider all of the code attached to the template Set Line Option & Get Starting Conditional Scripts, therefore it's recommended that you put these scripts in a hak (like cep2_custom) in order to reduce the # of scripts in your module & make building time much faster... (A tweak to fix the con)  Players would not be required to download YOUR cep2_custom.hak with your scripts in it, provided you don't put anything like edited 2das in there or tlk files...

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

If I think of anything else I'll post it...  Cheers & Enjoy

Genisys / Guile  :wizard:

Modifié par _Guile, 19 mai 2012 - 05:27 .


#18
acomputerdood

acomputerdood
  • Members
  • 219 messages
WOW, now that's impressive!

it's always pained me to write complicated dialogs because i knew it was eating up so many scripts doing dumb little things. in the back of my mind i knew there was a more concise way to do it, but i never took the time to try working something out.

so, trying to summarize what's going on:
- at the start of a conversation, the PC is flagged with the conversation name
- every ncp using this system has the same conversation action scripts attached to it, and using the stored conversation name the giant script will figure out which actions to take
- further actions and checks set other values on the PC to keep state

that's quite impressive.

#19
_Guile

_Guile
  • Members
  • 685 messages
You kind of have the gist of it...

The custom conversation system I designed sets variables on the PC to keep track of what conversation they are in (1), which section of the conversation they are in (2), and checks each starting conditional for that section (3), and then figures out what to do based upon which line the PC selects (4), and all of that comes together in the 2 includes, the other 4 scripts are Tmplates for setting up the conversation # / section # / checking Starting Conditionals / and last & most important performing functions based upon what line the PC selects..

If you get the gist of the system you will see how easy it is to integrate 30 + conversations into these very simple script routines.. (Simple but brilliant I might add)  Though, dont' get me wrong, it may be easy, but it will take you a long time to integrate say, 20 big conversations, especially if you are talking like forge and other nasty conversations...  (It took me over a week! to integrate my main 20+ conversations)

The benefit of the system for me was, taking 2100+ Scripts and reducing them down to just a mere 428!
(Mind you, I could have wittled it down to just 200 scripts if I would have put the forge system in the same include as well)

One last thing you should definitely note, if the main include "gen_cs_act_inc" becomes too long an hard to work with, especially if you have too many includes attached to it, then don't be afraid to take this custom template system and use it for MORE / similar systems, just change the names of script and viola.

I had to do this because my forge has 4 major conversations, and I didn't want to put that with my other main convesations, because the scripting for the forge is HUGE!  To give you an idea of what I'm talking about here, take a look at this..   (And that's not even counting the 10++ includes attached to it, lulz!)

(NOTE: This script system was designed BEFORE I made the custom integrated conversation system above)
(This script uses sections #s followed by Covnersation Numbers, instead of the reverse, which is better!)

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

// gen_forge2_mods
//////////////////////////////////////////////////////////////////////////////
// Created By: Genisys / Guile
// Created On: 10/29/2011
// Contact At: galefer003@hotmail.com
/////////////////////////////////////////////////////////////////////////////
/*
   This is the second revision of the Genisys Forge, this is the main
   include which will handles setting everything in the forge system, including
   the Item Property Removal System, and The Item Changing Forge as well.

    Copy the entire line for for debugging any part of this include...
   SendMessageToPC(oPC, "This Message");  // (For Debugging)
*/
/////////////////////////////////////////////////////////////////////////////
//Required Includes (DO NOT TOUCH!)

//Strictly for the Omega Pool Only... (Note this has all other includes!)
#include "omega_pool_inc"

/////////////////////////////////////////////////////////////////////////////
//Define Prototype
void SET_LINE_OPTIONS(object oPC, int nLine)
{
 //Declare All Major Variables Used
 int nSec = GetLocalInt(oPC, "gf_sec");
 int nConv = GetLocalInt(oPC, "CONV_NUM");
 int nProp = GetLocalInt(oPC, "PROPERTY_TYPE");
 object oItem, oForge, oSlot, oAnvil;
 string sMsg, sColor, sFinal;
 int nAdj;

//==============================================================================
// Strictly for Feats Only (as the code is far too long for this include!)
if(nSec >= 13 && nSec <= 23)
{
 CheckSection(oPC, nSec, nLine);
}
if(nSec == 36)
{
 CheckSection(oPC, nSec, nLine);
}
//=============================================================================
switch(nSec){ //Main Switch  (The entire system works off sections)
//=============================================================================

case 0: //Section 0 (First section in EVERY Conversation)
{
 switch(nConv) //Which Convesation are we in?
 {
  case 0://The Genisys Forge Conversation //---------------------
  {
   switch(nLine)
   {
    case 1: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_RIGHTHAND);
             oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 2: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_LEFTHAND);
             oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 3: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_ARROWS);
             oItem = GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 4: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BOLTS);
             oItem = GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 5: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BULLETS);
             oItem = GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 6: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_ARMS);
             oItem = GetItemInSlot(INVENTORY_SLOT_ARMS, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 7: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_NECK);
             oItem = GetItemInSlot(INVENTORY_SLOT_NECK, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 8: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_CHEST);
             oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 9: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BELT);
             oItem = GetItemInSlot(INVENTORY_SLOT_BELT, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 10: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BOOTS);
             oItem = GetItemInSlot(INVENTORY_SLOT_BOOTS, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 11: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_ARMS);
             oItem = GetItemInSlot(INVENTORY_SLOT_ARMS, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 12: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_CLOAK);
             oItem = GetItemInSlot(INVENTORY_SLOT_CLOAK, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 13: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_HEAD);
             oItem = GetItemInSlot(INVENTORY_SLOT_HEAD, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 14: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_LEFTRING);
             oItem = GetItemInSlot(INVENTORY_SLOT_LEFTRING, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 15: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_RIGHTRING);
             oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 16: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_LEFTHAND);
             oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;
     case 17: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_LEFTHAND);
             oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
             SetLocalInt(oItem, "FORGING", TRUE);} break;

   } //END switch(nLine)
  }break;
  //-------------------------------------------------------------------
  case 1:// Item Property Removal System Only
  {
   switch(nLine) //Which Item the PC Is Working With
   {
      case 1: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_NECK);} break;
      case 2: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_CHEST);} break;
      case 3: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BELT);} break;
      case 4: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BOOTS);} break;
      case 5: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_ARMS);} break;
      case 6: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_CLOAK);} break;
      case 7: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_HEAD);} break;
      case 8: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_LEFTRING);} break;
      case 9: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_RIGHTRING);} break;
      case 10: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_LEFTHAND);} break;
      case 11: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_RIGHTHAND);} break;
      case 12: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_ARROWS);} break;
      case 13: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BOLTS);} break;
      case 14: { SetLocalInt(oPC, "ITEM_SLOT", INVENTORY_SLOT_BULLETS);} break;

   } //END switch(nLine)
  }break;

 //-------------------------------------------------------------------

//====================================================================
 } //END switch(nConv)
}break; //END case 0: for switch(nSec)
//==============================================================================
case 1: //----------------------------------
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   switch(nLine)
   {
    case 1: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ATTACK_BONUS); } break;
    case 2: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_DAMAGE_BONUS); } break;
    case 3: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ENHANCEMENT_BONUS); } break;
    case 4: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE); } break;
    case 5: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_EXTRA_RANGED_DAMAGE_TYPE); } break;
    case 6: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_HOLY_AVENGER); } break;
    case 7: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_KEEN); } break;
    case 8: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_MASSIVE_CRITICALS); } break;
    case 9: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_MIGHTY); } break;
    case 10: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ONHITCASTSPELL); } break;
    case 11: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ON_HIT_PROPERTIES); } break;
    case 12: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_REGENERATION_VAMPIRIC); } break;
    case 13: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_VISUALEFFECT); } break;
    case 14: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ABILITY_BONUS); } break;
    case 15: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_AC_BONUS); } break;
    case 16: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N); } break;
    case 17: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_DAMAGE_REDUCTION); } break;
    case 18: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_DAMAGE_RESISTANCE); } break;
    case 19: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_BONUS_FEAT); } break;
    case 20: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_REGENERATION); } break;
    case 21: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SAVING_THROW_BONUS);
               SetLocalInt(oPC, "option_a", 1); } break;
    case 22: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SAVING_THROW_BONUS);
               SetLocalInt(oPC, "option_a", 2); } break;
    case 23: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SAVING_THROW_BONUS);
               SetLocalInt(oPC, "option_a", 3); } break;
    case 24: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SAVING_THROW_BONUS);
               SetLocalInt(oPC, "option_a", 4); } break;
    case 25: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SKILL_BONUS); } break;
    case 26: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SPELL_RESISTANCE); } break;

   }//END switch(nLine)
  }break;
  //-------------------------------------------------------------------
  case 1://Item Property Removal System Only
  {
   switch(nLine)
   {
     //Set the Property Type they have selected (for later use)
     case 1: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ABILITY_BONUS); } break;
     case 2: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_AC_BONUS); } break;
     case 3: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ARCANE_SPELL_FAILURE); } break;
     case 4: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ATTACK_BONUS); } break;
     case 5: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_BASE_ITEM_WEIGHT_REDUCTION); } break;
     case 6: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_BONUS_FEAT); } break;
     case 7: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N); } break;
     case 8: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_CAST_SPELL); } break;
     case 9: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_DAMAGE_BONUS); } break;
     case 10: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_DAMAGE_REDUCTION); } break;
     case 11: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_DAMAGE_RESISTANCE); } break;
     case 12: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE); } break;
     case 13: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ENHANCEMENT_BONUS); } break;
     case 14: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE); } break;
     case 15: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_EXTRA_RANGED_DAMAGE_TYPE); } break;
     case 16: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_FREEDOM_OF_MOVEMENT); } break;
     case 17: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_HASTE); } break;
     case 18: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_HOLY_AVENGER); } break;
     case 19: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS); } break;

   } //END switch(nLine)
  }break;
  //------------------------------------------------------------------
  case 2://Item Changing Forge
  {
   //SendMessageToPC(oPC, "Weapon Type Set");  // (For Debugging)
   SetLocalInt(GetPCSpeaker(), "WEAPON_CHANGE_TYPE", nLine);
   //SendMessageToPC(oPC, "Wpn Line Set");
  }break;
 //-------------------------------------------------------------------
  case 3://The Omega Pool Forge
  {
   switch(nLine)
   {
    case 1: { SetLocalInt(oPC, "SpellLevel", 0); } break;
    case 2: { SetLocalInt(oPC, "SpellLevel", 1); } break;
    case 3: { SetLocalInt(oPC, "SpellLevel", 2); } break;
    case 4: { SetLocalInt(oPC, "SpellLevel", 3); } break;
    case 5: { SetLocalInt(oPC, "SpellLevel", 4); } break;
    case 6: { SetLocalInt(oPC, "SpellLevel", 5); } break;
    case 7: { SetLocalInt(oPC, "SpellLevel", 6); } break;
    case 8: { SetLocalInt(oPC, "SpellLevel", 7); } break;
    case 9: { SetLocalInt(oPC, "SpellLevel", 8); } break;
    case 10: { SetLocalInt(oPC, "SpellLevel", 9); } break;
    case 11: { SetLocalInt(oPC, "SpellLevel", 10); } break;

   } //END switch(nLine)
  }break;
  //------------------------------------------------------------------

//====================================================================
 } //END switch(nConv)
}break; //END case 1: for switch(nSec)
//==============================================================================
case 2: //-------------------------------
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   switch(nLine)
   {
    case 1: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE); } break;
    case 2: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL); } break;
    case 3: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL); } break;
    case 4: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL); } break;
    case 5: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS); } break;
    case 6: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ARCANE_SPELL_FAILURE); } break;
    case 7: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_BASE_ITEM_WEIGHT_REDUCTION); } break;
    case 8: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_FREEDOM_OF_MOVEMENT); } break;
    case 9: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_HASTE); } break;
    case 10: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMPROVED_EVASION); } break;
    case 11: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 1); } break;
    case 12: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 2); } break;
    case 13: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 3); } break;
    case 14: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 4); } break;
    case 15: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 5); } break;
    case 16: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 6); } break;
    case 17: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT);  SetLocalInt(oPC, "option_a", 7); } break;
    case 18: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_TRUE_SEEING); } break;

   } //END switch(nLine)
  }break;
  //-------------------------------------------------------------------
  case 1://Item Property Removal System Only
  {
   switch(nLine)
   {
     case 1: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL); } break;
     case 2: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL); } break;
     case 3: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL); } break;
     case 4: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_IMPROVED_EVASION); } break;
     case 5: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_KEEN); } break;
     case 6: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_LIGHT); } break;
     case 7: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_MASSIVE_CRITICALS); } break;
     case 8: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_MIGHTY); } break;
     case 9: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ON_HIT_PROPERTIES); } break;
     case 10: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_ONHITCASTSPELL); } break;
     case 11: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_USE_LIMITATION_class); } break;
     case 12: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_REGENERATION); } break;
     case 13: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SAVING_THROW_BONUS); } break;
     case 14: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SKILL_BONUS); } break;
     case 15: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_SPELL_RESISTANCE); } break;
     case 16: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_TRUE_SEEING); } break;
     case 17: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_REGENERATION_VAMPIRIC); } break;
     case 18: { SetLocalInt(oPC, "PROPERTY_TYPE", ITEM_PROPERTY_VISUALEFFECT); } break;
   } //END switch(nLine)
  }break;
  //------------------------------------------------------------------
  case 2://Item Changing Forge
  {
   SendMessageToPC(oPC, "Other Items Set");
   switch(nLine)
   {
      case 1: { SetLocalInt(GetPCSpeaker(), "WEAPON_CHANGE_TYPE", 32); } break;
      case 2: { SetLocalInt(GetPCSpeaker(), "WEAPON_CHANGE_TYPE", 33); } break;
      case 3: { SetLocalInt(GetPCSpeaker(), "WEAPON_CHANGE_TYPE", 34); } break;
      case 4: { SetLocalInt(GetPCSpeaker(), "WEAPON_CHANGE_TYPE", 35); } break;
      case 5: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 0); } break;
      case 6: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 1); } break;
      case 7: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 2); } break;
      case 8: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 3); } break;
      case 9: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 4); } break;
      case 10: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 5); } break;
      case 11: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 6); } break;
      case 12: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 7); } break;
      case 13: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 8); } break;
      case 14: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 9); } break;
      case 15: { SetLocalInt(GetPCSpeaker(), "ARMOR_CHANGE_TYPE", 10); } break;
      case 16: { SetLocalInt(GetPCSpeaker(), "SHIELD_CHANGE_TYPE", 0); } break;
      case 17: { SetLocalInt(GetPCSpeaker(), "SHIELD_CHANGE_TYPE", 1); } break;
      case 18: { SetLocalInt(GetPCSpeaker(), "SHIELD_CHANGE_TYPE", 2); } break;
    }
  }break;
 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
    SetLocalInt(oPC ,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 2: for switch(nSec)
//==============================================================================
case 3: //------------------------------
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;
  //-------------------------------------------------------------------
  case 1://Item Property Removal System Only
  {
     SetLocalInt(oPC, "option_b", nLine);
  }break;
  //-------------------------------------------------------------------
  case 2://Item Changing Forge
  {
      object oForge = GetNearestObjectByTag("gen_wpn_forge", oPC);
      int nChange;
      object oWpn;
      string sWhich;
       sWhich = "WEAPON_CHANGE_TYPE";
       nChange = GetLocalInt(oPC, sWhich);
       oWpn = GetFirstItemInInventory(oForge);
       while(GetIsObjectValid(oWpn)) {
        //Alter the torso of the armor only..
       ChangeWeapon(oWpn, oForge, nChange, oPC);
       break; //Do ONE TIME!
       oWpn = GetNextItemInInventory(oForge);       }
        //Make the PC Pay for the change (take gold)
        int nGP = GetLocalInt(oPC, "WC_GOLD_COST");
        TakeGoldFromCreature(nGP, oPC, TRUE);

  }break;
 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 3: for switch(nSec)
//==============================================================================
case 4:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 24 + nLine;
   SetLocalInt(oPC, "option_a", nAdj);

  }break;
  //-------------------------------------------------------------------
  case 2://Item Changing Forge
  {
       object oForge = GetNearestObjectByTag("gen_wpn_forge", oPC);
       int nChange;
       object oWpn;
       string sWhich;
       sWhich = "ARMOR_CHANGE_TYPE";
       nChange = GetLocalInt(oPC, sWhich);
       oWpn = GetFirstItemInInventory(oForge);
       while(GetIsObjectValid(oWpn)){
        //Alter the torso of the armor only..
       ChangeArmor(oWpn, oForge, nChange, oPC);
       break; //Do ONE TIME!
       oWpn = GetNextItemInInventory(oForge);       }
       //Make the PC Pay for the change (take gold)
       int nGP = GetLocalInt(oPC, "WC_GOLD_COST");
       TakeGoldFromCreature(nGP, oPC, TRUE);

  }break;
 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   int nMod = 20 + nLine;
   SetLocalInt(oPC,"MODCODE", nMod);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 4: for switch(nSec)
//==============================================================================

case 5:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 48 + nLine;
   SetLocalInt(oPC, "option_a", nAdj);
  }break;
  //-------------------------------------------------------------------
  case 2://Item Changing Forge  (Last Section)
  {
       object oForge = GetNearestObjectByTag("gen_wpn_forge", oPC);
       int nChange;
       object oWpn;
       string sWhich;
       sWhich = "SHIELD_CHANGE_TYPE";
       nChange = GetLocalInt(oPC, sWhich);
       oWpn = GetFirstItemInInventory(oForge);
       while(GetIsObjectValid(oWpn)){
       //Alter the torso of the armor only..
       ChangeShield(oWpn, oForge, nChange, oPC);
       break; //Do ONE TIME!
       oWpn = GetNextItemInInventory(oForge);       }
       //Make the PC Pay for the change (take gold)
       int nGP = GetLocalInt(oPC, "WC_GOLD_COST");
       TakeGoldFromCreature(nGP, oPC, TRUE);

  }break;
 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);

  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 5: for switch(nSec)
//==============================================================================

case 6:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 72 + nLine;
   SetLocalInt(oPC, "option_a", nAdj);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   int nMod = 20 + nLine;
   SetLocalInt(oPC,"MODCODE", nMod);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 6: for switch(nSec)
//==============================================================================

case 7:  // (Sector 7 is Re-Used throughout the Forge to set the int ("option_a", nLine)
{
 switch(nConv)
 {
  case 0://Forge Only
  {
    SetLocalInt(oPC, "option_a", nLine);
    //For Bonus Spell Slots Only
    if(nProp == ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N)
    {
     switch(nLine)
     {
      case 1: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_BARD); } break;
      case 2: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_CLERIC); } break;
      case 3: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_DRUID); } break;
      case 4: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_PALADIN); } break;
      case 5: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_RANGER); } break;
      case 6: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_SORCERER); } break;
      case 7: { SetLocalInt(oPC, "PROPERTY_class", IP_CONST_class_WIZARD); } break;
     }
    }

  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 6: for switch(nSec)
//==============================================================================

case 8:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nLine);
   //If we are looking at Bonus Feats..
   if(nProp == ITEM_PROPERTY_BONUS_FEAT)
    {
      SetLocalInt(oPC, "WPN_FEAT", nLine);
    }

  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   int nMod = 20 + nLine;
   SetLocalInt(oPC,"MODCODE", nMod);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 6: for switch(nSec)
//==============================================================================

case 9:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nLine);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 9: for switch(nSec)
//==============================================================================

case 10:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nLine); // Immunity to Spells by Level (option B)
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 10: for switch(nSec)
//==============================================================================

case 11:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   int nMod = 20 + nLine;
   SetLocalInt(oPC,"MODCODE", nMod);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 11: for switch(nSec)
//==============================================================================

case 12:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nLine);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 12: for switch(nSec)
//==============================================================================

case 13: // Bonus Feats...
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 13: for switch(nSec)
//==============================================================================

case 14:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 24 + nLine;
   SetLocalInt(oPC, "option_a", nAdj);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 14: for switch(nSec)
//==============================================================================

case 15:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);

   switch(nLine)
   {
    case 6: { SetLocalInt(oPC, "EDR_TYPE", 1);  } break;
    case 7: { SetLocalInt(oPC, "EDR_TYPE", 2);  } break;
    case 8: { SetLocalInt(oPC, "EDR_TYPE", 3);  } break;
    case 9: { SetLocalInt(oPC, "EDR_TYPE", 4);  } break;
    case 10: { SetLocalInt(oPC, "EDR_TYPE", 5); } break;
   }
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 15: for switch(nSec)
//==============================================================================

case 16:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
   switch(nLine)
   {
    case 14: { SetLocalInt(oPC, "SPELL_FOCUS", 1); } break; ///Epic Spell Focus
    case 16: { SetLocalInt(oPC, "SPELL_FOCUS", 2); } break; ///Greater
    case 21: { SetLocalInt(oPC, "SPELL_FOCUS", 3); } break; ///Normal
   }
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool
  {
   SetLocalInt(oPC,"MODCODE", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 16: for switch(nSec)
//==============================================================================

case 17:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nAdj);
  }break;

 //-------------------------------------------------------------------
  case 3://The Omega Pool  (Last Section)
  {
   switch(nLine)   //Uses Per Day
   {
    case 1: { SetLocalInt(oPC,"Mods",IP_CONST_CASTSPELL_NUMUSES_1_USE_PER_DAY);} break;
    case 2: { SetLocalInt(oPC,"Mods",IP_CONST_CASTSPELL_NUMUSES_2_USES_PER_DAY);} break;
    case 3: { SetLocalInt(oPC,"Mods",IP_CONST_CASTSPELL_NUMUSES_3_USES_PER_DAY);} break;
    case 4: { SetLocalInt(oPC,"Mods",IP_CONST_CASTSPELL_NUMUSES_4_USES_PER_DAY);} break;
    case 5: { SetLocalInt(oPC,"Mods",IP_CONST_CASTSPELL_NUMUSES_5_USES_PER_DAY);} break;
    case 6: { SetLocalInt(oPC,"Mods",IP_CONST_CASTSPELL_NUMUSES_UNLIMITED_USE);} break;
   } //END switch(nLine)

  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 17: for switch(nSec)
//==============================================================================

case 18:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 18: for switch(nSec)
//==============================================================================
// Sections 19 - 23 are used in the first statement of this script!
//==============================================================================

case 24:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 25:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 24 + nLine;
   SetLocalInt(oPC, "option_a", nAdj);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 26:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 48 + nLine;
   SetLocalInt(oPC, "option_a", nAdj);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 27:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 28:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   switch(nLine)
   {
    case 1: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_ACID); } break;
    case 2: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_BLUDGEONING); } break;
    case 3: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_COLD); } break;
    case 4: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_DIVINE); } break;
    case 5: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_ELECTRICAL); } break;
    case 6: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_FIRE); } break;
    case 7: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_MAGICAL); } break;
    case 8: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_NEGATIVE); } break;
    case 9: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_PIERCING); } break;
    case 10: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_POSITIVE); } break;
    case 11: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_SLASHING); } break;
    case 12: { SetLocalInt(oPC, "DAMAGE_TYPE", IP_CONST_DAMAGETYPE_SONIC); } break;
   }
   SetLocalInt(oPC, "option_a", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 29:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 30:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 31:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);  //Massive Criticals Option A (checked)
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 32:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 33:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_a", nLine);  // SR = Option A (dbl checked)
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================

case 34:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   SetLocalInt(oPC, "option_b", nLine);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================
case 35:
{
 switch(nConv)
 {
  case 0://Forge Only
  {
   nAdj = 20 + nLine;
   SetLocalInt(oPC, "option_b", nAdj);
  }break;

//====================================================================
 } //END switch(nConv)
}break; //END case 19: for switch(nSec)
//==============================================================================
//For Weapon Feats (Type of Weapon)
case 36:
{
 SetLocalInt(oPC, "option_a", nLine);
} break;

//=============================================================================
//=============================================================================
} //END switch(nSec)
//=============================================================================
} //END PROTOTYPE
////////////////////////////////////////////////////////////////////////////////

Modifié par _Guile, 20 mai 2012 - 03:20 .


#20
_Guile

_Guile
  • Members
  • 685 messages
As complex as a Forge Script can get, I simply set variables on the pc to tell the main forge script which actually applies the properties, which properties the PC has selected, which lines they have selected (e.g. variables "option_line_a" / "option_line_b" set as an Int / 1 - 60), and set variables for constants of the property which will be applied to the item. Indeed you can keep track of anything, including, but definitely not limited to what you will find in the above script..

Like which item the PC is altering / forging / crafting / etc..

The list goes on and on and definitely on and on.. :D

Genisys = Genius Systems.. 
(Though I'm not a genius mind you) :D


Anyway, I had a download available (updating it presently), which indluded all of my systems integrated into this conversation system on the nwvault.ign.com, if you are interested in getting a copy of that module & erf, just let me know (pm me)...

Cheers & Enjoy

Genisys / Guile

Modifié par _Guile, 20 mai 2012 - 03:16 .


#21
henesua

henesua
  • Members
  • 3 858 messages
The amount of work that Guile put into these scripts is indeed impressive.

One simple way that I have used to reduce converstion scripts is to remove hardcoded data. For example if you have scripts that check for presence/absence of particular items, create one that gets the resref or tag of the object from the conversing creature, and then search for that. If some converstations look for more than one object, create a series of generic "hunt for item" scripts, and number the consecutively. Likewise the local strings would be numbered consecutively.

The same can be done for skill checks.

That method alone will allow you to reduce the number of scripts in your module. And it is easy to implement.

However... I became so obsessed with this method of handling things that I simply decided to create conversations that were entirely run by one master script. Presently I am using Z-dialog. I had written my own system, but decided to use z-dialog instead, as it was more developed than my own.

#22
_Guile

_Guile
  • Members
  • 685 messages
You can definitely attach all of the custom includes you want to the Integrated Conversation System, indeed, I have my own private function scripts (many of them) which I use in multiple other scripts as well...

It's always a good idea to create function scripts for "general things", like an xp_functions include script, etc...

Thanks for the compliment btw. :D

#23
henesua

henesua
  • Members
  • 3 858 messages

_Guile wrote...
Thanks for the compliment btw. :D


its better that people treat one another with decency and respect.

#24
_Guile

_Guile
  • Members
  • 685 messages
Always :D

#25
acomputerdood

acomputerdood
  • Members
  • 219 messages
well, my dream of mapping the dependencies of all the nodes has been dying. i'm just not sure that graphviz can handle 15k nodes with numerous connections between them. let alone the horrible mess that the ensuing graph will look like if it actually finishes. too bad - that would have been REALLY cool.

so i was last plugging away at my spells. all of the standard spells were overwritten to include a wild magic check. i'm assuming this is legacy from before the patch that adds the spell hook. so i'm re-rewriting the spells to put the wild magic check in the spell hook.

i've eliminated a few hundred spell scripts by combining them all into two giant spellhook scripts. i got tired of doing it, so i stopped. the spells i had modified were all working flawlessly in the game, and i was quite happy. but then one of my players posted that he couldn't create wands anymore. when he would target the bone wand with certain spells, it would say invalid target.

but get this - only the spells i DIDN'T transfer to the new system were giving the error! they were previously working until i started using the spellhook. but now, spells that were untouched from before are suddenly not working. so i had to resume my efforts of converting more spells to the new system.

i think i have most of those fixed up. still several hundred spell scripts to go, but they're the less common spells that players don't make wands and such out of.

i'm intrigued by guile's conversation script, as there can be huge savings there. but first i think i'm going to start with eliminating the identical conversations. i've got dozens of individual conversations that say "hello so and so, would you like to see my wares?".