Author Topic: Using a Local String on an object (placeable or item) for storing encoded instructions  (Read 379 times)

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0


               

I had this crazy idea yesterday, and wonder if anyone else ever pursued this.


 


The use case I was considering was an item which acted as a kind of locked container. Say you give a PC a box that they can't open at first, but it has some things inside that they will want later, and these things are randomly generated from a list.


 


Well I couldn't figure out how to make a locked carriable container, so I created a "Crate" item using a box icon I had in Miscellaneous Medium (its a custom icon). And when this crate is dropped on the ground it becomes a Crate placeable (an unopenable crate) that can be "taken" as part of its use action in which it becomes an item again. Having the item become a placeable is useful because it allows the PC to smash the crate to open it, and I can spawn objects in its death script.


 


All this was fine except I didn't have a clean way to track the things stored inside the crate.


 


Then it occurred to me. What if I had one string in which I could encode various directives in sequence? And since its just one string, I can easily copy this string from item to placeable to item. I don't have a ton of local variables to propagate back and forth.


 


Has anyone done this? The idea is that the string would be kinda like JSON data. A big string of code that can be executed.


 


it would be structured something like this:


DIRECTIVE directivetype : ARGUMENTS arg1 . arg2 . arg3 . : *


 


DIRECTIVE is a tag so that I know the text between DIRECTIVE and : is an identifier for the kind of directive.


ARGUMENTS is a tag noting that the string between it and the : is composed of arguments to be used by directivetype.  different kinds of directives would take different arguments, and have a . as a delimter.


 


the * is a delimiter allowing multiple DIRECTIVES to be chained together


 


 


Anyway… its a silly idea, but if I had a nice framework for it, a single string could allow an item or placeable to do all kinds of things.


 


 


For storing items in an object I was thinking of having an inventory directive with an argument which is a label of a persistent container in the database which contains the object's contents. The death event and other "userdefined" open the box events would access the inventory directive.


 


Example:


Death event executes.


 


string sDirectives = GetLocalString(OBJECT_SELF, "SPECIAL_DIRECTIVES");


if(FindSubString(sDirectives,"INVENTORY")!=-1)


{


     // parse directive string for inventory directives and execute them here


}



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0


               

You may be over-engineering this it seems. How about a semicolon separated list of resrefs? Or pairs of resref;count;resref;count ...


Then you just parse the string and create the appropriate items.


 


For the more general question, there are a number of systems that do something like that for their specific domain


(NESS spawn names, NPC activities names etc).  What kind of things are you expecting will be DIRECTIVES?


               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0


               

Why not just throw the crate into a database and retrieve it later?



               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0


               


You may be over-engineering this it seems. How about a semicolon separated list of resrefs? Or pairs of resref;count;resref;count ...


Then you just parse the string and create the appropriate items.


 


For the more general question, there are a number of systems that do something like that for their specific domain


(NESS spawn names, NPC activities names etc).  What kind of things are you expecting will be DIRECTIVES?




I guess that is what NESS does.


 


Is this over-engineered? Maybe. But I like the idea of one string for all that I need, because it is so easy to parse a string with the patterns I am using above, and I don't need to keep adding local variables to an object and updating my variable propagating script when an item is copied or changes type.


 


Other directives? Not sure yet. One idea is that I could have a system that identifies which events it responds to, and hooks up userdefined events to particular kinds of interaction, and then stick all of the code in one userdefined event script. Seems like an elegant way to do it. You could have one set of default scripts, a string of directives that configure which user defined events extend the default events, and then one user defined script to handle all the special cases.


 


I had considered making this only solve the inventory problem, but rather than a list of resrefs I prefer to hook a pseudo container to a saved "container" in the database. This allows the stored items to be dynamic and customized.


 




Why not just throw the crate into a database and retrieve it later?




 


Not sure what you mean. In one respective thats what I mentioned doing above for this one case. The string however would be one way of hooking the pseudo-container to a "container" in the database. The first part says that the object has inventory, and the second would be a database address to retrieve that inventory.


 


This allows me to create other ways of interacting with the crate and opening up this persistent inventory when the Player solves the lock or whatever.


 


 


 


----


 


 


And basically to clarify the problem that I am trying to solve:


 


local variables on an item are basically stored in an array on the object, but we don't access to the array in NWScript, so its a PITA to handle all the local variables on an object.


 


I use a boat load of local variables for a variety of things. For example, I have a conversation framework in which I pull out standard conversation phrases into data, and customize per NPC. I also have data for identifying type of NPC (Merchant, Inn Keeper, Leader, Priest whatever), strings which describe the NPC in the particular capacity and on and on and on.


 


Then I have my modification of Ambiguous Interactive Dungeons (basically a dumbed down interactive fiction parser) which relies on local variables on placeables to extend the object's functionality, hidden descriptions and so on.


 


With this much data piling up to customize everything, it has the potential to become unwieldy when I need to propagate the data from one object to another. If we had access to the array which stores all this it would be no problem.


 


So I was thinking… what if I had ways of compressing the data to essential strings…..


and this is what i came up with. And considering all that… maybe its time that I really started using NWNX. I keep trying to solve everything in NWScript. And at this point I basically need a web application to make it easier to build areas, and NPCs and so on with all the extra data i am using to define objects in the game. With a webapp hooked to the module and NWNX I could do all this on the module on the server. So many others do this, and as usual i am late to the party.



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0


               

(You talk about item variables but your example is NPCs which are more interesting anyway...)


 


Seems you are just pushing the problem around. Instead of having to set 10 or 20 variables on an NPC you have to set one long string variable carefully made up of 10 or 20 pieces information.  Personally I'd do it the other way. It's not a problem to have scripts handle variables. Now you have to put your metal effort into building all the complicated strings correctly.


 


NWNX does give you access, at least for reading, to the variables (I don't know if you can manipulate them or not when enumerating them). But then so do Set/GettLocal*.  But you can certainly use it to write code to loop through all the variables on an object and re created them on a different object.


 


If you have external code that can set a local string you could also have external code that sets local ints and floats.  If you can do that from your webapp you would not need to do anything with parsing in nwscript.


 


How often do you really need to copy those complex configuration variables from one object to another?  Besides the use case you have mentioned about the chest, but in that case it could just be a single variable with the database reference of the real container.


 


You could fairly easily make an NPC database table in an SQL database and populate rows in that as needed. Nwnscript could read those entries and set the corresponding variables on objects. Then NPC on spawn could do that ... actually, that's not unappealing... those could all be changed while the server was running, taking effect next time the NPC spawned somewhere... anyway, just thinking out loud a bit...


               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0


               

I do actually have a number of cases in which I have to copy data between objects.


I mentioned the AID placeables (which have tons of data on them), and some of these placeables can be pushed around which means copy, propagate data and inventory, then delete old to simulate moving things around by pushing.


I also have items like the crate that can become placeables and back again. Another example are the chairs and stools that a PC can pick up, hit someone with, put back down and sit on. I also have lanterns and candles that can be placed to shed light, and later picked up again. Each of these things have data that moves around with them.


 


As far as how difficult it might be to set a single complex data string by hand, I agree. but often i am applying data by script. Example with this crate: i actually have a few pieces of data i'd like to set on the crate for a particular quest. I'd like to provide a unique identifier on it in addition to its tag. I would like to associate a persistent container with it. And I would like to track whether it appears tampered with when a PC opens it. Rather than extending this behavior to all crates (although I could do this) I'd like to customize its behavior. Since the crate moves between item state and placeable state sticking all this ad hoc data in a single string would make it trivial to propagate the data.


 


All that said however none of this matters if I hook the item copy function to NWNX and propagate local variables automatically without having to predict all the labels i need to copy.


 


I obviously need to get in the NWNX groove, and build a webapp which does stuff that I can't do easily in the toolset. Creating a webapp for building unique NPCs out of generic blueprints and setting spawnpoints in module areas for them would be awesome.



               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0


               

Then it occurred to me. What if I had one string in which I could encode various directives in sequence? And since its just one string, I can easily copy this string from item to placeable to item. I don't have a ton of local variables to propagate back and forth.

 

Has anyone done this? The idea is that the string would be kinda like JSON data. A big string of code that can be executed.


 

 

Meaglyn called it NSS.  but is this  not  what NWNx does?   But tht is not really keeping it in NWN script is it.    

 

 
it would be structured something like this:

DIRECTIVE directivetype : ARGUMENTS arg1 . arg2 . arg3 . : *


DIRECTIVE is a tag so that I know the text between DIRECTIVE and : is an identifier for the kind of directive.

ARGUMENTS is a tag noting that the string between it and the : is composed of arguments to be used by directivetype.  different kinds of directives would take different arguments, and have a . as a delimter.

 

the * is a delimiter allowing multiple DIRECTIVES to be chained together

 




Since the string is to be executed , why not just leave it in a format that you and other are use to.  


 


Function/DirectiveName ( arg1,arg2...); 


 


EDIT: Did not fully understand you format at first.   Interesting.   


I think however that I would place different  directive types in different strings.  that way if the string exists you execute and dont have to separate it from the rest of the code.   


 


 


Example:

Death event executes.

 

string sDirectives = GetLocalString(OBJECT_SELF, "SPECIAL_DIRECTIVES");

if(FindSubString(sDirectives,"INVENTORY")!=-1)

{

     // parse directive string for inventory directives and execute them here

}

 



 


 


 


I am not really a big fan of winding up with a big "  if then else then " statement here.


 


How about going a little more resource intensive with ease of expansion.   


 


**without scripting the parser/functions fully out.  


 


 sFunction = GetfirstToken();  


 SetLocalInt(OBJECT_SELF, "Args", ParceStringForArgs());


ExecuteScript(sFunction,OBJECT_SELF); 


 


 


You could even combine the Idea to use RunScriptAndReturnAnInt   If you wanted to add control structures to the language.  


Just a thought. 



               
               

               
            

Legacy_Guest_TrillClinton_*

  • Newbie
  • *
  • Posts: 11
  • Karma: +0/-0


               

if you are treating this like each directive represents an object of some kind, then JSON would be the idea notation.


 


{ "Directive" : 


      { DirectiveName : "Inventory": argument : arg1, argument2 : arg2,argument3 : arg3}


},


 


{ "Directive" : 


      { DirectiveName : "SomethingElse": argument : arg1, argument2 : arg2,argument3 : arg3}


},


 


 


 


code to get this in a function would be to call them recursively each time you encounter a new directive. The question is do you really need it? JSON is great for standardizing exchange of data between endpoints but does a local script for a few elements really need it? If your platform comes with the libraries then so be it but they are simpler notations of doing this. Not to mention you know you this is directives only and not being used as a universal notation.


 


If this was larger scale software, I would have used a broadcast pattern to transport all of my messages to my classes http://sourcemaking....terns/observer instead of the nested but if it is for a local script that has doesn't need to scale then it is fine.


 


Otherwise keep on coding! It is one of the greatest things in life



               
               

               
            

Legacy_meaglyn

  • Hero Member
  • *****
  • Posts: 1451
  • Karma: +0/-0


               


 

Meaglyn called it NSS.  but is this  not  what NWNx does?   But tht is not really keeping it in NWN script is it.    




 


?!?


 


I said the NESS spawn names could be considered a similar system for the specific domain of controlling a spawn point.  The tags are effectively directive<arguments> separated by _.


 


And I did mention that NWNX does let you walk through the variables. But that was a different thought.


 


I like the ExecuteScript idea.