Jump to content
  • Advertisement
Sign in to follow this  
BradDaBug

Designing my scripting engine

This topic is 4804 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This has probably been discussed before, but searching for "event scripting" isn't exactly helpful. I've already got Lua embedded in my game and it's working, to a point. When the game starts up it runs "startup.lua," which tells the game to load various data files, setup the display, etc. Now it's time to get more complicated and actually start scripting the game itself. How do you I make my engine know to call XYZ script when ABC event occurs? Do I look for all .lua files and try to call an Init() function, which is supposed to register all the events that have scripts, then when the event occurs I call that function that the script registered? Also, how do I store per-player state info? Say I wanted to script a quest. For every single player on my server (I'm not talking MMORPG here, maybe 30-40 tops) I'd have to store info about every single quest for every player (completed, received, etc). Where do I store that data? The game engine doesn't know or care about this "quest" stuff since all that is script-side so I don't think it should have to store the data, but I don't see any way the script can store the data. Should the game engine have some sort of database where it stores script defined data that scripts can retrieve?

Share this post


Link to post
Share on other sites
Advertisement
I've been thinking about this and here's the system I've come up with.

There are these things called "Scriptable Entities," represented by a CScriptableEntity class. These scriptable entities have events and properties associated with them.

Properties can be anything that the entity wants. An entity can give itself a property of "IQ" or whatever it wants. There are also special properties (like position, etc) that have special meaning that affect the physical attributes of the entity, assuming they're attached to some dynamic object.

Events are mostly predefined. The game engine constantly checks for various events (I don't really like polling like this since there could be LOTS of events generated each frame and only a handful are actually cared about), and if one of those events affects a scriptable entity then that entity is tested to see whether that event is defined for that entity. If it is, then the script procedure defined for that event is called.

Say you wanted to have a light switch that turns a light on and off. The lightswitch would be a scriptable entity, and the light itself would be another. The switch would store some type of reference to the light's scriptable entity as a property, as well as the switch's current state. When the user clicks on the button, a "CLICK" event is generated on the button. The switch is tested for the "CLICK" event, and then the switch's "OnClick" event function is executed. This function checks the current state of the light, toggles it, and then sends an event (like "turnOn" or "turnOff", which are custom events the light defined for itself) to the light. By keeping the light a seperate scriptable entity it could have other states that determines whether the light actually turns on or not. Maybe the light recieved a "SHOOT" event earlier when the player shot out the light, so it considers itself destroyed, so when the switch tries to turn on the light the light shoots out some sparks instead.

There's a little bit more to it, but that's the meat of it. How does all that sound?

Share this post


Link to post
Share on other sites
I have some code that does pretty much this. It's an entity class that has embedded states, variable properties and has an event system. PM me if you would like it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Why use polling? Why not just dispatch the event at the moment it is generated?

I don't mean that the scriptable entities poll for events, I mean that the engine itself has to keep checking for events. Like if you've got x scriptable entities and y total events the engine is going to have to test the environment for y events and dispatch those to x possible entities, so there's O(xy).

Of course this is ultimate worst case since many events will be generated and you don't have to check for them each frame, like shooting an object will only occur when a bullet or something collides with it, so it'd just be a matter of informing the scriptable entity that it's been shot when it's been shot, etc. Hmm, in fact, maybe most events would be like this. Maybe it's not that bad of a setup.
Quote:
Original post by evolutional
I have some code that does pretty much this. It's an entity class that has embedded states, variable properties and has an event system. PM me if you would like it.

Thanks. I've already got a good bit of code written though.

The tricky part seems to be getting this system to work with what I already have. I've already got two main types of objects, static objects (trees, buildings, etc) and dynamic objects (pretty much everything else, dynamics are controled by ODE). Not all these objects are going to be scriptable entities, so I don't think that these objects should be inherited from the scriptable entities. I guess that each object should have a pointer to a scriptable entity (has-a relationship) that can be NULL or not depending on if it's needed.

Another thing I'm wondering about is sub objects. Say I've got a lamp with a button on it that you can turn on and off. The button can move depending on the state of the light. So this lamp is made of three objects, the button, the lamp itself, and the light. The light and the button are scriptable entities, but that means the engine needs to know about both and they can't be hidden away in some kind of heirarchy. That means every single object (since every single object potentially has a scriptable entity associated with it) has to be explicitly stored in the database. I guess I could make it so that normally objects own their subobjects unless a subobject has a scriptable entity, in which case the database owns it, but that seems kinda ugly.

Is there anything really wrong with storing every single object in the main database and not using object heirarchy? I'm using an stl map to store stuff so lookups wouldn't really be any slower. But then doing frustum culling on objects would be much slower. Maybe I could keep both the objects heirarchy and store everything in the database so I could draw/cull using the object heirarchy and do the event stuff with the main database?

I'd better stop talking before I go any further off topic.

Share this post


Link to post
Share on other sites
Quote:
Original post by BradDaBug
inheritance...sub objects...hierarchy...database...

Yipe! Dial it back. Yeah, you COULD do some insanely complicated system where a lamp consists of multiple parts and delegates events based on an ownership hierarchy, but that seems like way too much scaffolding for way too little of an effect.

How 'bout this. Your light switch is an object. Its "use" script toggles the switch's internal state, and then calls the light bulb's "turnOn" or "turnOff" script. The light bulb's "turnOn" script will not turn on if the bulb's "shotout" property is set. The light bulb's "collideweapon" script turns on the "shotout" property, and turns off the light. Including declarations, it's about ten lines of coding. Moreover, unlike the sort of OO scaffolding you were describing, it is incredibly easy to add special cases and modify behavior. It's slightly more likely than the OO method to have corner cases you didn't think of (what if you forgot to turn the light off in "collideweapon"?), but that's what QA is for.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Sneftel
Quote:
Original post by BradDaBug
inheritance...sub objects...hierarchy...database...

Yipe! Dial it back. Yeah, you COULD do some insanely complicated system where a lamp consists of multiple parts and delegates events based on an ownership hierarchy, but that seems like way too much scaffolding for way too little of an effect.

How 'bout this. Your light switch is an object. Its "use" script toggles the switch's internal state, and then calls the light bulb's "turnOn" or "turnOff" script. The light bulb's "turnOn" script will not turn on if the bulb's "shotout" property is set. The light bulb's "collideweapon" script turns on the "shotout" property, and turns off the light. Including declarations, it's about ten lines of coding. Moreover, unlike the sort of OO scaffolding you were describing, it is incredibly easy to add special cases and modify behavior. It's slightly more likely than the OO method to have corner cases you didn't think of (what if you forgot to turn the light off in "collideweapon"?), but that's what QA is for.



You do have to have the code that ties the two objects together ( Define Switch, Define Bulb, and then cross ties ref links between them). Similar code possibly for removing/destructor too. The Switch has to specify all events/signals it reacts to and interlocks/states/other factors that effect its logic behavior, as well as the signals it sends, visual/sound events it spawns.

The Bulb has similar code/data components - including linkage to visual effects like a light field in 3D (itself possibly an entity which may tie to a sensory mechanisms used by smart objects -- if you go that far).

Both objects are also connected (at least spatially) to other scenery or building objects (and any chunk hierarchy used).

It seems the association between the Bulb and Switch would have to be organized
around another 'entity'/object -- at least to facilitate construction/initialization.

I wont even go into the complications of when a switch controls more than one
light bulb (one-to-many relationship) or if more than one switch can control the same set of bulbs.


Having a script language like LUA will probably require data on both the server side and the script side for each object/sub-object. If there is more than one thread operating on these objects, there may be a synchronization problem between the data on either side of the interface which has to be provided for.





Share this post


Link to post
Share on other sites
Personally, I like a message-dispatch-handle approach.

When one entity triggers an event, the event (or entity based on how you set it up) will send a message to another entity, which will in turn handle the event.

For instance, say you have a CBullet *bullet. During any given frame you update the bullet via bullet->update(). In that function it detects that it hit a player, CPlayer *player. Then the bullet would send a message to player that it has been hit by a bullet for X damage, and the bullet will kill itself. The player receives the message that it was hit for X damage and responds appropriately.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!