Home   Help Search Login Register  

Author Topic: Properties for objects  (Read 5320 times)

0 Members and 1 Guest are viewing this topic.

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Properties for objects
« on: 22 Feb 2005, 06:49:07 »
I've been pining for the 'dot' notation that C++ uses to access data for a particular object. In flashpoint script, you either have to use one of the commands in the comref (getpos for example), or store your data in a whole bunch of variables in script (_soldier1startloc, _soldier2startloc, _car23owner and so on). It can get cumbersome (for me) to keep track of/use/update all these variables in script sometimes especially in large .sqs files. Plus there is the additional problem of global variables being the only way that scripts can 'communicate' - otherwise they are completely cut off from each other. With global variables again there is the problem of keeping track of names, plus the fact that they all seem to be public and overwritten perfectly easily, and from anywhere. The fact that the script is parsed means there is no compiler error if you accidentally attempt to overwrite a 'private' variable (or at least one that somebody intended to be private) which is used some other script(s). Having masses of global variables seems... unsafe, and a bit uncomfortable at times.

So my idea, if original, is to store data pertaining to an object  (you define the data, and its tag) in an n-dimensional array. This would reduces the number of global variables to just one.

Example: say you had 2 scripts for a C&H game. The first monitored the capture points for east/west presence and updated who owned what. The second was an ai script that told a group of soldiers where to move next and what to do. When the first script detected that a capture point was taken, it would update the waypoint for the soldiers to the next objective. The second (ai) script would tell them to move to the objective/patrol and guard once they were there.

Problem: how do the 2 scripts communicate? The mission designer might understandably want the soldiers to patrol through certain waypoints at one objective, and another another set at the next. Or he might want them to mount a certain machine gun at the first objective, and a tank at the next. How does the mission designer store all these variables: objectives, positions, machine guns etc? It's possible but difficult to do this with conventional waypoints and switch commands, and it gets trickier the more objectives there are. Generally the mission designer will script, and use variable names.
In flashpoint, you might name them something like this: CurrentObjective, WayP1GuardPoint1, WayP1GuardPoint2, WayP2MG1, WayP2MG2 and so on. (The variables might be local or global, depending on how the scripts are structured). Here it gets messy, especially if the variables are global, because they'll need original names to stop them getting accidentally overwritten by competing scripts.

Solution: In C++, you might be able to store/retreive the data like this: currentobjective.patrolpoints [ 0 ] (for the first patrol point in a series for this objective), currentobjective.defences.machineguns (for a list of machinegun defences associated with this objective) etc. It's 'object orientated' in that the code revolves around various objects which contain data and functions that modify that data. These functions can also modify other object's data (if that object allows it), which makes it powerful. Apologies if you know all this already.

How to implement something this in OFP? As I mentioned before, with an n-dimensional 'array'. Since 'array's in ofp are very flexible, you can store this data like this:

[ [ AnObject,["dataname1",data1],["dataname2",data2] ] , [ AnotherObject,["dataname1",data1] ] , ... ]

With a simple check, you could find, say, AnObject 's second piece of data by searching firstly for AnObject in the array, and secondly for "dataname1" in it's various data arrays. Effectively you get 'AnObject.Dataname1', which equals 'data1'. In this way, you can store/retrive any number of pieces of info associated with a single object. Only 2 functions would be required for this which I can write quite easily- one to store new data, one to retreive it.

Advantages:

1. You can assign your own properties to an object without ever needing to name it, or know it's name. Simply because the object itself resides in the array. So you could assign a piece of data to an unnamed object, and run into it sometime later (e.g. with a nearestobject command) and find it's data again.

2. You can assign as many properties as you like to an object (within the various limitations of the game).

3. Drastically cuts down on the number of variable names needed.

Disadvantages:

1. The functions that find the data and the object iterate through all the elements. This means that the more pieces of data you add, and the more objects you add, the longer the check would take. The 'retreive data' functions are much slower than simply accessing a variable by name. Translation: More objects with more properties = slower to find one property.

2. Probably there are others.


Sorry for this long and rambling post. If you're still with me, please let me know what you think, or if this has been done before. If you have a question also please tell me.  ;)

 
« Last Edit: 22 Feb 2005, 06:51:28 by Fragorl »

Offline General Barron

  • Former Staff
  • ****
  • Semper Fi!
Re:Properties for objects
« Reply #1 on: 22 Feb 2005, 07:38:57 »
   I've thought about doing this exact same thing as well. AFAIK, this hasn't been done in the past, or atleast it hasn't been done much. When the CoC's Unified Artillery first came out, I thought they must have done something like this, since they seemed to have variables 'attatched' to units and nothing else. However, it turns out they used the call and format command to create dynamic global variables. While that is also a useful technique, I believe this one would be more usable on a larger scale, especially due to the savegame bug that occurs when you have too many variables.

   Perhaps we could turn this idea into a usable function/script suite? I actually am working on a script/addon that will require exactly this trick anyway.
HANDSIGNALS COMMAND SYSTEM-- A realistic squad-control modification for OFP
kexp.org-- The best radio station in the world, right here at home! Listen to John Richards!

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #2 on: 22 Feb 2005, 07:59:09 »
Great! I'm pleased to hear it's in the works, and i'd be glad to help out. I'm not surprised that the idea's been thought up, though, it's fairly simple.

About CoC, I gueesed that they'd need some form of mass-handling of variables, but never got around to actually checking how. Using global variables like is an interesting idea, but as you say suffers from the savegamebug plus the ones I mentioned.

I hadn't thought about implementation, except vaguely on an individual-mission basis. function/script suite sounds better.  :)

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #3 on: 24 Feb 2005, 11:56:21 »
OK anyhow here are a couple of (tested) functions, that add and modify the aforementioned 'properties'.

E.g. You want to add a property called "age" to the player.

[player,"age",38] call SetProperty

You want to retrieve the player's "age":

[player,"age"] call GetProperty

-- If you have defined "age", like in the above, you will get 38 returned.
-- if you havent, the function will return **EDIT (see below) -- objnull

Another e.g: You want to modify the property "Nearest Soldier" of the leader of the player's group.

[leader (group player),"Nearest Soldier",nearestobject [leader (group player),"SoldierWB"]] call Addproperty


*****Notes*****
Just one global variable needed. It's an array, called 'properties'. Careful not to modifiy it elsewhere (if you're using this system).

Just two functions you need: SetProperty.sqf, Getproperty.sqf. The global variable 'properties' is automatically set up the first time you run either of these.

If the object doesn't have any properties defined and you add a property to it, this will work. The object will be instantiated in the array, 'properties'

If the object has the property that you're trying to add already (ie the name is the same), it will be modified.

If the object has properties, but none under the name you're specifying, that property will be added.

EDIT: object no longer required. Works with a second string.
« Last Edit: 04 May 2005, 10:47:16 by Fragorl »

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #4 on: 24 Feb 2005, 11:57:27 »
Attachment deleted. Functions now at editor's depot.
« Last Edit: 04 May 2005, 10:47:48 by Fragorl »

Offline General Barron

  • Former Staff
  • ****
  • Semper Fi!
Re:Properties for objects
« Reply #5 on: 24 Feb 2005, 21:16:40 »
Wow, very nice. I wouldn't have thought to use strings like you did (I was thinking of just setting/returning an array and letting the scripter decide what to do with it), but your method is very intuitive. I have one suggestion to the second function though: instead of returning false when nothing is found, it should return null. The reason is, if I want to have some sort of error checking in my script, it would have to look like this with your current function:

Code: [Select]
_result = .... call getProperty
? !_result : goto "error"
...blah blah....

This will return an error if _result is successfully returned (unless it is actually a boolean that is returned). If _result is an object, number, or whatever, it will cause an error. But if you return null on an error, then you don't have that problem:

Code: [Select]
_result = .... call getProperty
? isnull _result : goto "error"
...blah blah....

That shouldn't ever cause an error, no matter what _result is.

Other than that, they look pretty good, and should be submitted to the functions page, IMO. :)
HANDSIGNALS COMMAND SYSTEM-- A realistic squad-control modification for OFP
kexp.org-- The best radio station in the world, right here at home! Listen to John Richards!

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #6 on: 24 Feb 2005, 22:09:00 »
Good point!  :o Yes, I didn't really think about that...
I think 'Isnull <bool/string/etc>' causes errors too though, coz isnull is just for groups and objects. I just tested that. I'll have to think about this...
« Last Edit: 24 Feb 2005, 22:36:40 by Fragorl »

Offline General Barron

  • Former Staff
  • ****
  • Semper Fi!
Re:Properties for objects
« Reply #7 on: 25 Feb 2005, 00:43:49 »
It does? Hmm... oh well, it can still be used. Instead of 'isnull', you would just need to check if the returned value is equal to itself:

? _return == _return : goto "returnisok"

If _return is null, then it will not be equal to itself. If it is anything else, then it will be equal to itself.
HANDSIGNALS COMMAND SYSTEM-- A realistic squad-control modification for OFP
kexp.org-- The best radio station in the world, right here at home! Listen to John Richards!

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #8 on: 25 Feb 2005, 08:06:57 »
Tricksey! ;D I'll have to put a note in with the function for scripters that this is the check needed.
Now to advertise this...
« Last Edit: 25 Feb 2005, 08:17:09 by Fragorl »

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #9 on: 04 May 2005, 10:45:57 »
Finally, I have got around to puting the two functions in the editors' depot.

I have removed the functions from this page as they are slightly out of date, and of course now redundant. Get them here.

Any questions/comments welcome.

Chad

  • Guest
Re:Properties for objects
« Reply #10 on: 04 May 2005, 13:59:37 »
Or you could make a compiler that takes higher language syntax like java and convert that syntax into the ofp game script engine.

// Author Chad Lion
// Version: 1.00
// Date: May 3, 2005
//
// This document is for demonstration purposes.
// Its to reflect a ongoing development of two current projects
// One the object orientated compiler and the next is the
// A.I. Heuristic
public class Demo{
    public static void main( object parmunit, object target ){
      object unit[] = units group parmunit;  
      boolean found = true;
     
      while( found ){
         for( int i = 0; i < (count unit); i=i+1 ){
            object tmp = unit;
         
            if(  alive tmp ){
               if( ((tmp knowsabout target) > 0 ) && ( found != false ) ){
                  telleveryone( unit, target );
                  found = false;
                  print( "Finish telling units" );
               }
            }
         }    
      }    
    }
   
    public static void telleveryone( object unit[], object target ){
         for( int i = 0; i < (count unit); i=i+1 ){
            object tmp = unit;
            if( alive tmp ){
               Soilder s = new Soilder( tmp, target );
               s.startthread();  
            }
         }
    }
}
public class Soilder{
   private object me;
   private object target;
   
   public Soilder( object me, object target ){
      this.me = me;
      this.target = target;
   }
   
   public void startthread(){
      me setBehaviour "COMBAT";
      me setdir DirToObj( me, target );
      me allowfleeing 0;
     
           
   
      while( ( alive target ) && ( alive me ) ){
         if( me hasweapon "M60" ){
            if( (me hasweapon "M60") && ((me distance target) < 400 ) ){
               dostop me;
               me setUnitPos "down";
               while( ( alive target ) && ((me distance target) < 400 ) ){
                     me dofire target;
                     ~1;
               }
            }else{
               me domove getpos target;            
            }
         }else{
            if( (me distance target) < 200 ){              
               dostop me;
               me setUnitPos "down";
               me dofire target;
            }else{
               me domove getpos target;            
            }        
         }
         ~10;
      }
      freeheap( this );    
   }
   
   
   // calculate the direction from the ai to the target engaged
   // thanks gen
   public int DirToObj( object me, object target ){
      int ai[] = getpos me;
      int thetarget[] = getpos target;
      int result = 0;
     
result = (thetarget[0] - ai[0]) atan2 (thetarget[1] - ai[1]);
      if( result < 0 ){
         result = result + 360;
      }
     
      freeheap(ai);
      freeheap(thetarget);
      return result;
   }  
}  
The above is an example, and it compiels to a script file that ofp executes and runs. Full ability out of game error checking, increase performance well degreasing development time. Increase flexability with incapsulation and abstraction. All the problems within ofp script engine are handeld by the compiler. It means you spend more time in production than worrieing about the underlying language and issues.

I am the lead developer.

But i have allready said to much.
« Last Edit: 04 May 2005, 14:01:08 by Chad »

Chad

  • Guest
Re:Properties for objects
« Reply #11 on: 04 May 2005, 14:05:14 »
btw in regards to you first questions, within the compiler you can make your own static methods that resemble the commands you wish to excute, giving you the functionality that you wish with dot notation.

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Properties for objects
« Reply #12 on: 05 May 2005, 01:02:43 »
H'm. My original aim was to create a more effective way of managing global variables- the variables themselves.

Can you explain what you are doing with this code? I can follow it, but it is missing sections and I want to know more about it.

The above is an example, and it compiels to a script file that ofp executes and runs. Full ability out of game error checking, increase performance well degreasing development time. Increase flexability with incapsulation and abstraction. All the problems within ofp script engine are handeld by the compiler.
Now this really interests me. You say that the above compiles to a script file, .sqs. I can understand that you might interpret that content into a script file, but it would be very complex. It interprets all your 'while's and 'for's into a script file? Well, for each loop you have, you will need to have 2 new labels, if you're working with script. So perhaps your compiler adds labels for each loop statement it encounters?

     while( found ){
        for( int i = 0; i < (count unit); i=i+1 ){ .....
        }
      }

---> interpreted to

     #label1
     ?!_found: goto "endlabel1"
         #label2
         ?_i>=count _unit:goto"endlabel2"
         ...
         ...
         _i=_i+1
         goto"label2"
         #endlabel2
      ...
      ...
      goto "label1"
      #endlabel1    

where each loop you add involves two new arbitrarily named labels which your compiler adds. I can imagine that you might be able to somehow simulate 'else' statements, which script does not support. As for simple returning methods, I imagine you can simulate them too, using either .sqf files, or even in your .sqs file using yet more labels.

But i have allready said to much.
You may need to explain some more. Am I generally correct as to what you are doing? Or barking up the wrong tree altogether? Do you output one .sqs file for each class?

Remeber that as long as you're outputting script files, you're still subject to the limitations of the OFP game engine. Any limitations that apply to script will apply to the products of your compiler. But maybe you have a more effective way of organising your script files?

Anyhow, let me restate the purpose of my two .sqf functions:

They are designed to manage global variables in a more effective way, cutting down on the total number and providing an easier way to exchange them between script files (which is 100% possible as it is). They help secure variables against overwriting, and also provide a way to 'attach' properties to game objects.

Maybe my spiel at the beginning about C++misled you. That is all I set out to do here.

Offline Planck

  • Honoured
  • Former Staff
  • ****
  • I'm never wrong ....I'm just not always right !
Re:Properties for objects
« Reply #13 on: 05 May 2005, 01:09:35 »
Quote
I can imagine that you might be able to somehow simulate 'else' statements, which script does not support.

Are you sure about this?

I've never used it but the comref does list else.

ifCode else elseCode


Perhaps you have tried it and it didn't work?


Planck
I know a little about a lot, and a lot about a little.

Chad

  • Guest
Re:Properties for objects
« Reply #14 on: 05 May 2005, 02:37:38 »
You are very much right on the mark considering the while and #goto statements.

I will exsplain how the compiler works.

The compiler takes higher language syntax like java, the first pass it checks the syntax of the document well building up a data tree structure of you objects, methods, member fields, and local variables within your code. It will come to a in-game statement for example,    dostop. It will then do an xml parser check with the 3 different xml files provided with the comref documentation. If a match is found then its flaged as being a ofp command to execute.

The next stage of the compiler is doing type checking on the 2nd pass of the code. Once it has built up the data structure more like code structure to make it simple. It then checks the data types against each other. This is to provent people from mistakenly compairing an object against a string. This is where the functionality of out of game error checking and syntax anyalysing comes into play. During the same second pass it emits assembly code.

Assemlby code? what?

yes, but a more advanced method of actualy doing it than what people may think. The compiler contains an interface, that sits between different languages. This interface is just a assembly code matcher, what sits behind the interface is whats amazing. The interface provides the ability  for the compiler to emit the same instruction then that instruction is matched to different languages.

Think of it like this way, i can swap the instruction set from assembly to pascal to ofp, and so on. This functionality enables the compiler to have a level of abstraction.

The compiler emits two main files, these being one file called
com.sqs
and
comt.sqs

The com.sqs file is the main file you execute within the game with
[] exec "com.sqs"

To pass parameters from the game into the compiler you would do this
[ this, "string" ] exec com.sqs
Then to access those variables within your higher language you would do this.

public static void main( object me, string mystring )

Or a more perffered method of doing this is the following

object me = (object) chad
string mystring = (string) mystring

the difference being, that you can now access global variables within the game then data cast them into the correct types so the compiler knows they exsists.

So in conclusion, optimisation can be done within the compiler without effecting the syntax at all. So technicaly, loops can be create at compile time into sqf function and such be called, without any modification to the code.

At this current stage, the complexity of the compiler and the technology used is pretty advanced. I have worked on the project for the last 1 year, and now its at completion i am in development of the ai hurristic with this tool.

I have run tests corresponding to object code, and performance compaired to original script files writen by hand. Although writen by hand script files run about 2% faster than the emited game code the compiler produces. But, its not about the speed its about the functionality the compiler gives to an organisation to produce training similation tools thats the major difference.

Because the compiler uses xml files and parsers them on the fly. All current and ongoing commands can be easly copied and pasted into the xml files. without effecting the main compiler.

The last topic i have left to last, is memory optimisation. The maximum number of variables the compiler uses for a script is only 8. So each time you run the script it will only use 8 private variables no more.

For example.
_reg1
_reg2
_reg3
_reg4 ect..

Thats the rundown of the system, I havent decided what i am going to do with the compiler in regards if BIS would be intrested in it. But at this current time it was produced to develop the ogn ai hurristic system.