I think it's time to start thinking about the scripting API.
In my opinion the scripting should be event driven.
At the moment there can be one script for every GameObjectEventType there is per block.
When there's a script for a certain event, that script will be executed instead of the default behaviour.
I think it might be best to extend this a bit and add more events for which scripts can be written.
After loading the level, allowing the levelmaker to start action sequences, etc...
One thing I noticed is that GameObjectEvent_PlayerLeave is never used, so that needs to be implemented.
A script should be able to do the following things:
- Add/delete/move a block
- Change properties of a block
- Move the player and shadow
- Retrieve information from the player/shadow/block (e.g. location, in-view, block standing on, etc...)
- Start/stop music and sfx
- Change certain aspects of the theme
- Interact with the player by showing messages (and perhaps images?)
- Store values for use in other/later scripts
For the block manipulating I think there should be a few methods which will take an index as additional parameter.
- {l Code}: {l Select All Code}
setBlockLocation(x,y,index)
The index will correspond with the index in the levelObjects vector and acts as a handle.
A handle should be retrievable by id, something like this:
- {l Code}: {l Select All Code}
//Get handle based on id.
handle = getBlockById('blockid')
//Get handle based on player or shadow location.
handle = getPlayerStandingOn()
The creation of a block will probably be quite simple:
- {l Code}: {l Select All Code}
//Create a new block.
handle = createBlock(type,x,y)
//Set a certain property of the block
setBlockProperty(handl,'id',10)
I'm not sure how music/sfx/theme interact should be done, but I don't think it's a good idea to allow loading stuff from within scripts.
Resources should be managed at level or even at levelpack level.
This way the needed files can already be loaded and accessed by name when needed, a missing file should only be a warning and not interrupt the level.
- {l Code}: {l Select All Code}
//Play sfx
playSFX('resource')
//Change music, fading set to true.
changeMusic('resource', true)
There are still some problems that I'm not 100% sure how to fix.
All handles will can become invalid when adding/removing blocks or changing the levelObjects vector in any other way.
One solution is making proper handles that point to the gameobject instead of the index.
On the other hand could we make this a warning, meaning that it's the levelmakers responsibility to make sure the handle is correct.
This may sound bad, but since the scripting is event driven it is known when the handle change.
From the start to the end of a script the levelObjects vector is untouched, unless the script changes it, in which case the levelmaker should be careful.
Another way this could go wrong, though, is if the script stores a handle for later use.
In that case it's near impossible to tell what has changed in between the scripts, so handles should never be stored, the id should be stored instead.
Also I think we shouldn't at any form of random behaviour in, for the following reasons:
- It makes the replay incorrect (can be solved by storing the used seed)
- Determining a target time/recording will be a lot harder.
- Simply doesn't fit the puzzle aspect of the game.
These can be used in many ways, but IMHO should only be used for enhancing the playing experience and NOT influence the level/game mechanics.
Finally there is a problem that the LevelEditor only allows linking triggers to "suitable" targets, in which case only those blocks can react with a script to these events.
I think we should allow linking to all blocks for more flexibility.
Maybe we should consider an "expert" mode for the LevelEditor, which allows such linkage and scripting, etc...
In the simple mode those things will be hidden from the user?
Suggestions and feedback are welcome!