Sample RF Object Script

Discuss the development of Reality Factory 2
User avatar
paradoxnj
RF2 Dev Team
Posts: 1328
Joined: Wed Mar 01, 2006 7:37 pm
Location: Brick, NJ
Contact:

Sample RF Object Script

Post by paradoxnj » Thu Aug 27, 2009 8:44 pm

I thought I would show some progress. I am doing the object system at the moment. The object system will allow you to create an entire level using only script. It will also allow you to define your own objects based on "Object Classes". These object classes will use predefined fields and will also support dynamic fields. Dynamic fields will allow you to define data specific to the object.

The object classes that are planned are as follows:
Actor
Logic
Debris
2D Sound
3D Sound
Terrain
Armor
ParticleEmitter
Light
Item
Weapon
WheeledVehicle
Trigger
Player
Precipitation
Decal
Lightning
Camera
Splash
SpawnMarker
Here is a sample of an actor.

Code: Select all

// Use only predefined fields for now.  The Actor class will look only at the predefined fields.  The dynamic fields can be access only in script using obj->getDataAs<Type>() functions.

Merlin <- {
	className = "Actor",
	meshName = "merlin.mesh",
	hp = 100,
	mp = 50
}

function Merlin::onCreate(obj)
{
	print("Initializing Merlin...");
}

function Merlin::onCollision(obj)
{
	print("collide!!");
	local h = obj.getDataAsInt("hp");
	h -= 20;
	obj.setDataInt("hp", 20);
	
	print(obj.getDataAsInt("hp"));
}

RFRegisterObjectType("Merlin");
So to create a Merlin actor in the world, you would do the following:

Code: Select all

m = RFActor("Merlin01", "Merlin"); // First param is the name, second is the instance data table

hp = m.getDataAsInt("hp");
print("Merlin\'s HP is " + hp);
This object is also accessible from other scripts so you can get the object explicitly and interact with it. That would be like this:

Code: Select all

m = RFGetWorld().getObject("Merlin01");
m.suicide();  // Let's kill Merlin
You don't have to define any event functions. If the event functions are not defined, the shell will use the default event function which on most objects will be blank. Keep in mind that if you don't define event functions, your object will not react to events.

I'd like constructive input on this. I'm mainly looking for ways I can improve it.
Many Bothans died to bring you this signature....

User avatar
darksmaster923
Posts: 1857
Joined: Wed Jan 03, 2007 10:32 pm
Location: Huntington Beach, California, USA
Contact:

Re: Sample RF Object Script

Post by darksmaster923 » Thu Aug 27, 2009 9:23 pm

This is using Squirrel, correct?
Herp derp.

User avatar
zany_001
Posts: 1047
Joined: Fri Mar 02, 2007 8:36 am
Location: Aotearoa

Re: Sample RF Object Script

Post by zany_001 » Thu Aug 27, 2009 9:28 pm

Woo! Vehicles! Me wants hummer...

Anyway, the first bit, I assume that defines merlin in the data instance table? Or possibly the RFRegister bit.

Other than that it looks pretty understandable.
Once I was sad, and I stopped being sad and was awesome instead.
True story.

User avatar
paradoxnj
RF2 Dev Team
Posts: 1328
Joined: Wed Mar 01, 2006 7:37 pm
Location: Brick, NJ
Contact:

Re: Sample RF Object Script

Post by paradoxnj » Thu Aug 27, 2009 10:30 pm

@Darksmaster: Yes...that is Squirrel.

@Zany: The first bit is the equivalent to placing an entity and filling in the fields. Except that this allows you to define an object and place it many times without filling in the fields each time. It also allows you full control of how that object reacts to the environment. You have the choice to do nothing or be very creative. The RFRegister() will tell the in-game editor that the object exists and to enumerate it's fields so that you can place it in the world. It's not needed if you don't want to use the in game editor and just create objects via script.

[EDIT] Elaborate a bit more [/EDIT]
You may have a generic bad guy...let's say a zombie. I'm sure you won't have just one zombie...so you'll want to place the same one over and over again in your scene at different locations. In RF, you would have to place a Pawn entity and fill in the fields for each and every location that you want a zombie in. In RF2, you would define your object data template and use it throughout the world (granted you want all the zombies to behave the same).
Many Bothans died to bring you this signature....

Allanon
Posts: 493
Joined: Mon Aug 29, 2005 8:23 am

Re: Sample RF Object Script

Post by Allanon » Thu Aug 27, 2009 10:35 pm

Will there be user defined events or will you have to use a predefined event to monitor variables and use if statements to execute user code? I envision something like this:

Code: Select all

.
.
.

function Merlin::onCreate(obj)
{
   print("Initializing Merlin...");

   obj.CreateUserEvent("Mana_Low", VARIABLE_MONITOR, MP, 10, LESS_THEN); // Params = (name of event, predefined type of event, variable to monitor, value, predefined comparison operator)

   obj.CreateUserEvent("Fire_Spell", KEY_MONITOR, 'A', KEY_DOWN);  // Params =  (name of event, predefined type of event, key to monitor, predefined condition)

   obj.CreateUserEvent("Flying", BOOLEAN_MONITOR, Flying, True);  // Params =  (name of event, predefined type of event, Variable to monitor, boolean operator)
}


function Merlin::onUserEvent(obj, "Mana_Low")
{
    print("Merlin's Mana is Low");
}

function Merlin::onUserEvent(obj, "Fire_Spell")
{
    print("Merlin casts the fire spell");
}

function Merlin::onUserEvent(obj, "Flying")
{
    print("Merlin is Flying");
}
.
.
.

User avatar
paradoxnj
RF2 Dev Team
Posts: 1328
Joined: Wed Mar 01, 2006 7:37 pm
Location: Brick, NJ
Contact:

Re: Sample RF Object Script

Post by paradoxnj » Thu Aug 27, 2009 11:02 pm

Actually...that would be done like this:

Code: Select all

Merlin <- {
   className = "Actor",
   meshName = "merlin.mesh",
   hp = 100,
   mp = 50,

   flying = false // Dynamic variable
}

// onUpdate() is called every frame
function Merlin::onUpdate(obj)
{
    if (obj.getDataAsInt("mana") < 5) {
        Merlin.onManaLow(obj);
    }

    if (Merlin::isFlying(obj)) {
        print("Merlin is flying!!");
    }
}

function Merlin::onManaLow(obj)
{
    print("Merlin's mana is low");
}

function Merlin::isFlying(obj) {
    return obj.getDataAsBool("flying");
}
The event system is a global event system which is in the shell code (C++) and should not be manipulated by script to avoid cheating and hacking as this will house network code also.

As for pressing a key to cast a spell. That is what I call an InputDeviceDefinition. It would work something like this:

Code: Select all

MyDef <- {
    a = Merlin::onFireSpell,
    esc = quit
}

RFInputSetActiveDef("MyDef");
I don't really see casting a spell as an event. I see that as a game specific task. Not all games have magic (e.g racing). Remember that the shell only sees these as generic objects with different data. The event system sees them at an even lower level.

I like the idea though. If the shell had an event called ScriptEvent and the function was more like:

obj.createScriptedEvent("Mana_Low", "Merlin::checkMana", "Merlin::onManaLow");
// Event Name, Check function, fired event function

...it would be more flexible. I could definitely set that up without changing the design to allow both methods to be used.
Many Bothans died to bring you this signature....

Allanon
Posts: 493
Joined: Mon Aug 29, 2005 8:23 am

Re: Sample RF Object Script

Post by Allanon » Thu Aug 27, 2009 11:34 pm

The createScriptedEvent you describe would be fine for user defined events. The use of a conditional function was a good idea, it simplifies things.

edit:

You might also allow the user to pass parameters to the conditional function.

Example:

Code: Select all

function Merlin::onCreate(obj)
{
   print("Initializing Merlin...");

   obj.createScriptedEvent("Mana_Full", "Merlin::checkMana", 100, "Merlin::onManaFull");
   obj.createScriptedEvent("Mana_Low", "Merlin::checkMana", 10, "Merlin::onManaLow");
}

function Merlin::checkMana(obj, param)
{
    return (obj.getDataAsInt("mana") == param);
}

function Merlin::onManaLow(obj)
{
    print("Merlin's mana is low");
}

function Merlin::onManaFull(obj)
{
    print("Merlin's mana is full");
}

Or maybe allow two paramerters for even more generic conditional functions:

Example:

Code: Select all

function Merlin::onCreate(obj)
{
   print("Initializing Merlin...");

   obj.createScriptedEvent("Mana_Full", "Merlin::checkEqual", obj.getDataAsInt("mana") , 100, "Merlin::onManaFull");
   obj.createScriptedEvent("Mana_Low", "Merlin::checkEqual", obj.getDataAsInt("mana") , 10, "Merlin::onManaLow");
}

function Merlin::checkEqual(obj, param1, param2)
{
    return (param1 == param2);
}

function Merlin::onManaLow(obj)
{
    print("Merlin's mana is low");
}

function Merlin::onManaFull(obj)
{
    print("Merlin's mana is full");
}

User avatar
paradoxnj
RF2 Dev Team
Posts: 1328
Joined: Wed Mar 01, 2006 7:37 pm
Location: Brick, NJ
Contact:

Re: Sample RF Object Script

Post by paradoxnj » Fri Aug 28, 2009 1:48 pm

One of the great features of Squirrel is the ability to have variable arguments and query all the argments (and their types) using the C++ API code. I can tell how many arguments a function has. So we could say the function has at least 3 arguments. If there are more than 3, then pass those arguments to the functions passed in the first 3 arguments.
Many Bothans died to bring you this signature....

User avatar
paradoxnj
RF2 Dev Team
Posts: 1328
Joined: Wed Mar 01, 2006 7:37 pm
Location: Brick, NJ
Contact:

Re: Sample RF Object Script

Post by paradoxnj » Tue Sep 01, 2009 10:38 pm

No one else has an opinion? I'm asking for input for the design of a critical system in the shell. No one has an opinion other than Allanon?
Many Bothans died to bring you this signature....

User avatar
zany_001
Posts: 1047
Joined: Fri Mar 02, 2007 8:36 am
Location: Aotearoa

Re: Sample RF Object Script

Post by zany_001 » Wed Sep 02, 2009 12:01 am

It already looks good, and I doubt I know enough to have anything useful to offer.
Once I was sad, and I stopped being sad and was awesome instead.
True story.

Allanon
Posts: 493
Joined: Mon Aug 29, 2005 8:23 am

Re: Sample RF Object Script

Post by Allanon » Wed Sep 02, 2009 12:43 am

Are you going to add functions that will make it easy to save and load games?

User avatar
paradoxnj
RF2 Dev Team
Posts: 1328
Joined: Wed Mar 01, 2006 7:37 pm
Location: Brick, NJ
Contact:

Re: Sample RF Object Script

Post by paradoxnj » Thu Sep 03, 2009 3:38 am

Yes. Squirrel will have access to all game data and you can use the I/O module to output to file.

Zany, think of it this way...how would you envision the editor placing objects. How would you like to define your objects? Keep it at a high level. No need to get technical.
Many Bothans died to bring you this signature....

User avatar
bernie
RF Moderator
Posts: 1249
Joined: Tue Nov 15, 2005 10:07 am
Location: Ireland

Re: Sample RF Object Script

Post by bernie » Thu Sep 03, 2009 12:27 pm

Well what I would like to see is and editor like rf1's editor and scripting added afterwards. I still don't understand Simkin properly yet so I am going to have to start over with squirrel when it's introduced. "Games without programming" is what I want to see, not being a programmer myself. I know scripting expands the usefulness of RF but the first thing should be an Editor like RF1's editor.

User avatar
zany_001
Posts: 1047
Joined: Fri Mar 02, 2007 8:36 am
Location: Aotearoa

Re: Sample RF Object Script

Post by zany_001 » Thu Sep 03, 2009 12:29 pm

OK I'll give it a shot. Assuming we are only talking about scripting here:

Actor creation should have at least two ways with scripting. One would create it at a particular point e.g. createActor(x,y,z)

Or at a particular script point e.g. createActorAt(zanypoint)

An easy way to modify what information is needed for each command would be good, although that may be too complicated. E.g. You want to create a actor and you want it to have health, mana, stamina, AND zaniness. But the default createActor only lets you pass location coords, and lets the script for that pawn handle HP and MP. If it was customizable you could have createActor(x,y,z,HP,MP,ST,ZN)
However that might be easier if the game maker just recoded the one command.

However from looking at those samples I think it won't be handled like what I thought, but rather you have a script like

Code: Select all

Zanything <- {
className = "Player", 
meshName = "zanything.mesh",
Hp = 100, 
MP = 20,
Stmna = 50,
ZNYNS = 1337
}
to define it each time you create it, so that would be easily customizable.

But if I'm wrong then that is the main definition of the zanything, so I want it so you can easily change and add statistics on creation and during the game.

How much would we need to do for, say, animation? Would we tie in keys to particular animations and movement speeds, like

Code: Select all

rollRight <- {
e = zanything::rollRight 
}
And in the zanything script:

Code: Select all

Zanything <- {
className = "Player", 
meshName = "zanything.mesh",
Hp = 100, 
MP = 20,
Stmna = 50,
ZNYNS = 1337
}
function
Zanything::rollRight(obj) {
obj.playAnimation('rollRight')
}
Once I was sad, and I stopped being sad and was awesome instead.
True story.

User avatar
bernie
RF Moderator
Posts: 1249
Joined: Tue Nov 15, 2005 10:07 am
Location: Ireland

Re: Sample RF Object Script

Post by bernie » Thu Sep 03, 2009 12:59 pm

Paradox: Are we going to get an editor or is to just going to be another language and making games by scripting ?

Post Reply