-
Notifications
You must be signed in to change notification settings - Fork 45
JSON guide
The game uses the JSON format to store its data. Here is explained how it works for each object. (In progress...)
The species of OpMons are stored in the data/species folder. The game will load any JSON file in this folder. Every JSON file must represent an array of species (even if it contains only one). Here is an example of the format for one species:
{
"HP":65,
"atk":60,
"atkSpe":30,
"def":58,
"defSpe":52,
"spe":33,
"evolution":{
"level":28,
"species":7,
"type":"level"
},
"evs":[
6
],
"opDex":4,
"types":[
6,
-1
],
"captureRate":45,
"curve":1000000,
"expGiven":93,
"height":0.5,
"weight":20.0
}
Warning: the JSON file has been generated automatically the first time, to spare some time. The fields are not in this order, but JSON works anyway, no matter the order. This example has been sorted to make it more understandable.
- HP: The HP base stat (Integer)
- atk: The attack base stat (Integer)
- atkSpe: The special attack base stat (Integer)
- def: The defense base stat (Integer)
- defSpe: The special defense base stat (Integer)
- spe: The Speed base stat (Integer)
- evolution: Evolution data (Evolution)
- evs: The given EVs when the OpMon is defeated (Array of stats)
- opDex: The OpDex number of the OpMon. It determines the OpMon's name too, searches in the key opmon.name.X where X is the opDex value. If you want to add an OpMon, don't forget to add its name in the keys files. (Integer)
- types: The two types of the OpMon (Two types in an array)
- captureRate: The OpMon's capture rate. If it's low, the OpMon will be hard to capture, and vice versa (Integer)
- curve: The EXP the OpMon will have at level 100 (Standard max EXP)
- expGiven: The base EXP the OpMon will give when defeated (Integer)
- height: The OpMon's height (Floating)
- weight: The OpMon's weight (Floating)
The moves are stored in data/moves. Every file in the folder will be loaded, and must be an array of moves, even if it contains only one. Here is an example of the format:
{
"id" : "Tackle",
"power" : 50,
"type" : 9,
"accuracy" : 100,
"special" : false,
"status" : false,
"criticalRate" : 16,
"neverFails" : false,
"ppMax" : 35,
"priority" : 0,
"effects" : [
{
"null" : true
},
{
"null" : true
},
{
"null" : true
}
],
"animationOrder" : [18],
"opMovementsAtk" : [
{
"translation" : {
"mode" : [ 1, 1 ],
"formulas" : [ [ 3, -6, 1, -5, 0, 30 ], [ 3, 6, 1, -5, 0, -30 ] ]
},
"time" : 10
}
],
"opMovementsDef" : [
{
"translation" : {
"mode" : [ 1, 1 ],
"formulas" : [ [ 3, 6, 1, -5, 0, -30 ], [ 3, -6, 1, -5, 0, 30 ] ]
},
"time" : 10
}
],
"animations" : ["default"]
},
- id: The identifier of the move. It is used to identify it in the code, but also to get its name in the different languages. (String)
- power: The power of the move (Integer)
- type: The type of the move (Type)
- accuracy: The accuracy of the move (Integer)
- special:
true
if it's a special move,false
otherwise (Boolean) - status:
true
if it's a status move (If it doesn't directly damage the opponent),false
otherwise (Boolean) - criticalRate: The odds of getting a critical hit (1 out of the input) (Integer)
- neverFails:
true
if the move never fails (Boolean) - ppMax: The maximum PP of the move (Integer)
- priority: The level of priority of the move (Integer)
- effects: An array of 3 effects. Respectively the effect before the damages, the effect after the damages, and the effect if the move fails. (Effect)
- animationOrder: The order in which the animations will occur (TurnActionType)
- opMovementsAtk: An array of sprite animations for the player's OpMon using the move. (Array of Sprite animations)
- opMovementsDef: An array of sprite animations for the opponent's OpMon using the move. (Array of Sprite animations)
- animations: An array of strings identifying the different screen animations present in the code (Screen animation)
The maps are stored in data/maps. Every file in the folder will be loaded. One file must contains one map object. Example:
{
"id" : "Player's home",
"tileset" : "alpha",
"layers" : [
[ 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 220, 910, 910, 910, 910,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 911, 220, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 220, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 220, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 220, 905, 905, 905, 905,
220, 220, 220, 220, 220, 220, 220, 905, 905, 220, 220, 220, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 910, 910, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 2444, 2445, 2446, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 2508, 2509, 2510, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905,
905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905 ],
[ 0, 0, 1281, 1282, 0, 904, 904, 0, 0, 0, 0, 0, 0, 2308, 0, 0,
1089, 914, 1345, 1346, 911, 911, 911, 911, 911, 911, 2054, 1747, 911, 911, 911, 911,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1747, 0, 0, 0, 2311,
0, 1090, 1091, 1092, 0, 0, 0, 0, 0, 0, 0, 1747, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1747, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1747, 0, 0, 0, 0,
910, 910, 910, 910, 910, 910, 910, 0, 0, 910, 2305, 2306, 0, 0, 0, 0,
911, 911, 911, 911, 911, 911, 911, 0, 0, 911, 2369, 2370, 0, 0, 0, 0,
0, 1230, 1231, 1232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1103, 1104, 1105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2119, 2120, 2121, 2307, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 2307, 2183, 2184, 2185, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2247, 2248, 2249, 2307, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1492, 0, 0, 0, 0, 0, 2511, 2512, 2513, 0, 0, 0, 0, 0, 0, 1492 ],
[ 1025, 850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1026, 1027, 1028, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0,
220, 220, 220, 220, 220, 220, 220, 0, 0, 220, 220, 220, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1166, 1167, 1168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1039, 0, 1041, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2246, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1428,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
],
"size" : [ 16, 16 ],
"indoor" : true,
"music" : "Fauxbourg",
"events" : [
{
"type" : "TP",
"textures" : "alpha",
"trigger" : 1,
"position" : [ 7, 15 ],
"tp" : {
"position" : [ 28, 17 ],
"map" : "Fauxbourg Euvi",
"side" : 0
},
"side" : 2
},
{
"type" : "TP",
"textures" : "alpha",
"trigger" : 1,
"position" : [ 15, 2 ],
"tp" : {
"position" : [ 9, 7 ],
"map" : "Player's room",
"side" : 2
},
"side" : 32
},
{
"type" : "TP",
"textures" : "alpha",
"trigger" : 1,
"position" : [ 0, 11 ],
"tp" : {
"position" : [ 6, 3 ],
"map" : "Mom's room",
"side" : 2
},
"side" : 16
},
{
"type" : "Dialog",
"textures" : "alpha",
"position" : [ 3, 8 ],
"dialog" : ["playerhome.tv"],
"side" : 1
},
{
"type" : "Dialog",
"textures" : "alpha",
"position" : [ 1, 1 ],
"dialog" : ["playerhome.fridge"],
"side" : 1
},
{
"type" : "Dialog",
"textures" : "alpha",
"position" : [ 10, 1 ],
"dialog" : ["trash"],
"side" : 1
},
{
"type" : "Dialog",
"textures" : "alpha",
"position" : [ 2, 8 ],
"dialog" : ["playerhome.tv"],
"side" : 1
},
{
"type" : "TalkingCharacter",
"textures" : "playermom",
"position" : [ 9, 9 ],
"dialog" : ["playermom.dialog"],
"facing" : 0,
"passable" : false
}
]
},
- id: The identifier of the map (String)
- layers: An array containing three arrays of Integers, each one representing a layer of the map. An Integer corresponds to a tile. We use Tiled Map Editor to generate these arrays (It generates an XML file containing all the values, then we copy and paste these values to the JSON file). (Array of arrays of Integers)
- size: An array of two Integers, respectively the width and the height of the map, in number of squares (Array of Integers)
- indoor:
true
if the map is an indoor map,false
otherwise (Boolean) - music: The ID of the music to play when the player is in this map (String)
- animations (Not present in this example): An array containing the identifiers for animated elements on the map. Example in Fauxbourg Euvi :
"animations" : ["windtubine", "smoke"],
(Array of Strings) - events: An array containing the events of the map (Array of Events)
There are several types of evolution. Every Evolution has the "type" field, which can be filled with the type name.
"evolution":{
"level":-1,
"species":-1,
"type":"no"
}
The type "no" means no evolution. "level" and "species" must stay to -1.
"evolution":{
"level":28,
"species":7,
"type":"level"
}
- level: The level at which the OpMon evolves (Number)
- species: The opDex number of the species in which the OpMon evolves (Number)
Each stat is associated to a number, according to the enumeration in src/opmon/model/objects/Enums.hpp :
enum class Stats : int {
ATK = 6,
DEF = 1,
ATKSPE = 2,
DEFSPE = 3,
SPE = 4,
HP = 5,
ACC = 7,
EVA = 8,
NOTHING = 0
};
There isn't EVs for accuracy, evasion and nothing, so putting these values will result in an undefined behavior.
Each type is associated to a number, according to the enumeration in src/opmon/model/objects/Enums.hpp
enum class Type : int {
LIQUID = 3,
BURNING = 6,
VEGETAL = 10,
ELECTRON = 4,
MENTAL = 12,
BAD = 16,
DRAGON = 2,
FIGHT = 1,
MINERAL = 13,
GROUND = 14,
NEUTRAL = 9,
MAGIC = 5,
GHOST = 15,
TOXIC = 11,
METAL = 0,
BUG = 8,
SKY = 17,
COLD = 7,
NOTHING = -1
};
Nothing isn't really a type, so putting this value will result in an undefined behavior.
There is different possible values for max EXP, each one corresponding to a different curve of EXP (Bulbapedia link).
- 800,000: Quick EXP curve
- 1,000,000: Normal EXP curve
- 1,059,860: Parabolic EXP curve
- 1,250,000: Slow EXP curve
- 600,000: Erratic EXP curve
- 1,640,000: Fluctuating EXP curve If some another value is entered, the default curve will be the normal one.
Exemple of effect
{
"null" : false,
"type" : "ChangeStatEffect",
"data" : {
"target" : 1,
"stat" : 6,
"coef" : -1
}
}
Represents an effect present in the code. If "null" is true
, the code ignores the object and assumes there is no effect. Else, there can be different types of effects that must be present into the code, identified by "type". Each effect takes different arguments in "data".
Current list of effects :
- target: The target of the effect change. If 0, the target is OpMon using the move. If 1, it is the OpMon taking the move. (Integer)
- stat: The stat modified by the effect (Stat)
- coef: The coefficient of modification of the stat. It can be from -6 (The stat decreases 6 times) to 6 (The stat increases 6 times). (Integer between -6 and 6)
The enumeration TurnActionType contains a lot of things in the code. Normally, for the animations, you'll only have to use two:
enum class TurnActionType : unsigned int {
[...]
ANIMATION = 17,
OPANIM = 18,
[...]
};
Note: If you want to break the game and use others, see Turn.hpp
- ANIMATION: A screen animation will be played.
- OPANIM: A sprite animation will be played. The animations are taken from first to last initialized in the JSON file. Exemple (The texts between parenthesis are comments, [...] replaces some code describing animations):
"opMovementAtk" : [
{[...]}, (OpAnim 1)
{[...]}, (OpAnim 2)
{[...]}, (OpAnim 3)
],
"opMovementDef" : [[...]], (The same number of animations here)
"animations" : ["sanim1","sanim2"]
In this exemple, if "animationOrder": [18, 17, 18, 17, 18], the order of animations will be OpAnim 1 - sanim1 - OpAnim 2 - sanim2 - OpAnim 3. Warning: Putting more values in "animationOrder" than the number of animations will result in an undefined behavior.
Example of animation:
{
"translation" : {
"mode" : [0,1],
"formulas" : [ [1,5,8,3], [ 3, -6, 1, -5, 0, 30 ] ]
},
"rotation" : {
"mode" : 1,
"formula" : [1, 2.0001, 1, 0, 0, -2.25],
"origin" : [0,0]
},
"scaling" : {
"mode" : [1,1],
"formulas" : [ [2, -1, 3.14, -6.28], [4, 2, 8.15, 0.5, 4, 1, 0, 2] ],
"origin" : [50,50]
},
"time" : 15
}
- time : The duration of the animation, in frames (Integer)
There are three transformations that will compose the final animation. But they have all things in common :
The different transformations use formulas depending on time, in frames. The translation and the scaling use their first formula for the width, and the second for the height. The rotation uses its only formula for the angle of rotation.
The system of formulas in OpMon is constructed with modes of interpretations of arrays. You can input any kind of floating number, positive or negative.
Every item of the array is the coefficient of a polynomial formula. Example: The array [2, 8, 2.6, 7.15] will be treated as 2 + 8t + 2.6t^2 + 7.15t^3
This mode is a bit more complex. It works with the basic format [FUNCTION_ID, arg1, arg2, ..., FUNCTION_ID, arg1...] (You can put several function one after the other). Technically, you can input floating numbers or other numbers than those specified here for FUNCTION_ID, but if you do you'll surely break the program. This system will be improved in the future to allow more functions and formulas. Here is a list of the available functions :
- Use: [0, a]. The formula will interpret it as simply a.
- Example: [0, 2]. The formula will be 2.
- Use: [1, a, b, c]. The formula will interpret it as a·sin(b·t + c).
- Example: [1, 3, -2.4, 0]. The formula will be 3sin(-2.4·t).
- Warning: The sine function works with radians (2pi-periodic).
- Note: If you leave "a" to 0, the function will be 0. If you leave "b" to 0, it will be the constant a·sin(c).
- Use: [2, a, b, c]. The formula will interpret it as a·cos(b·t + c).
- Note: Basically works like the sine function.
- Use: [3, a, b, c]. The formula will interpret it as a·|b·t + c|.
- Note: Also works like the sinus function.
- Use: [4, ... another function ..., a].
- Example: [4, 2, 1.2, 2, -4, 2] will be interpreted as (1.2·cos(2t - 4))^2
- Warning: Unimplemented yet.
The origin is for the rotation and scaling, and it defines the origin of the transformation. You have to enter the coordinates of this origin in the [x,y] format.
These are animations played on the whole screen. It consists of images put one after the other. They must be registered in the code. Currently, none has been created.
{
"type" : "TalkingCharacter",
"textures" : "playermom",
"position" : [ 9, 9 ],
"dialog" : ["playermom.dialog"],
"facing" : 0,
"passable" : false
}
There are several types of events you can add to the maps. If you want to add more, you'll have to do it in the code. Event must contain a "type" field where the type of event will be specified. Each event needs different fields, and some are optional (The non-optional fields will be specified with *).
The event system is composed of two types of events: the base types and the composed types. The first one are like "elementary bricks" to build all the other types. They are currently five.
The other events are built by composition of the base ones: they are called "meta events" in the code. In the JSON data, a meta event must either have all the properties of the events it will contains, or directly contains them. A meta event can contain other meta events. Also, one type of meta event is particular, the "linear meta event", which will be explained later.
An abstract event can't be instanciated and won't be recognized by the game. However, every event (but some exceptions) must or can take the following parameters:
- type*: Indicates to the game the type of the event. Will be specified for every type of event below (String).
- textures*: The ID of the textures used by the event (String).
- trigger: How the event is triggered (EventTrigger). Default value : By pressing the interaction key (PRESS)
- position: An array of two integers representing the position of the event, in squares (Array of Integers). Default value : [0,0]
- passable:
true
if the player can pass through the event (Boolean). Default value :false
- side: The sides from which the player can interact with the event (Interaction side). Default value: all sides (SIDE_ALL)
This event animates itself when triggered, iterating through its array of textures.
{
"type" : "Animation",
"textures" : "movingflower",
"position" : [2,5],
"framerate" : 1,
"loop" : false,
"lastTexture" : false
}
- type*: "Animation" for this type of event.
- framerate: The number of ticks elapsed between two frames of the animation, 0 meaning one frame per tick (positive integer). Default value: 0
- loop: If
true
, the animation will loop, and a new action will stop the animation. Else, the animation will start when the event is triggered, and then stop at the last frame. (Boolean). Default value: false - lastTexture: Only useful if loop is false. If true, the animation will stop at the last frame of the texture array. If false, it will animate one last time to get back on the first frame. (Boolean). Default value: true
This event starts a battle when triggered.
{
"type" : "Battle",
"textures" : "battlerock",
"position" : [15,23],
"trainer" : "rock"
}
- type*: "Battle" for this type of event.
- trainer*: The ID of the trainer to fight (String).
This event represents a NPC walking through the map (or standing still).
{
"type" : "Character",
"textures" : "coolguy",
"position" : [24,25],
"moveStyle" : 1,
"path" : [ [ 1, 10 ], [ -2, 1 ], [ 2, 10 ], [ -2, 1 ] ],
"facing" : 2
}
- type*: "Character" for this type of event.
- moveStyle: How the character moves (MoveStyle). Default value: No movement (NO_MOVE).
- path: If the chosen movement is PREDEFINED, this array sets the movement (Path). Default value: empty array.
An event playing a dialog.
{
"type" : "Dialog",
"textures" : "alpha",
"position" : [ 19, 10 ],
"dialog" : ["fedesc"],
"side" : 1
},
- type*: "Dialog" for this type of event.
- textures*: The identifier of the textures in the code (String).
- position*: An array of two integers representing the position of the event, in squares (Array of Integers)
- dialog*: The dialog played by the event (Dialog)
- side: The sides from which the player can interact with the event (Interaction side). Default value: all sides (SIDE_ALL)
- trigger: How the event is triggered (EventTrigger). Default value : By pressing the interaction key (PRESS)
- passable:
true
if the player can pass through the event (Boolean). Default value :false
This event plays a music or a sound.
{
"type" : "Sound",
"textures" : "alpha",
"position" : [10,10],
"playID" : "boing",
"music" : false,
"toggle" : false
}
- type*: "Sound" for this type of event.
- playID*: The identifier of the sound/music to play (String).
- music: If
true
, the event plays a music, else, the event plays a sound (Boolean). Default: false. - toggle: If
true
, the music/sound is played in a loop that can be (de)activated by triggering the event. Else, the sound/music is played one time until the end when the player triggers the event. (Boolean). Default: false.
An event that teleports the player from one map to another.
{
"type" : "TP",
"textures" : "alpha",
"trigger" : 3,
"position" : [47, 17],
"tp" : {
"position" : [1,38],
"map" : "Road 14",
"side" : 1
},
"side" : 32
}
- type*: "TP" for this type of event.
- tp*: Data about the teleportation :
- position*: The new position of the player after the teleportation, in squares (Array of two Integers)
- map*: The ID of the destination map (String)
- side: Where the player will be facing after the teleportation (Side). Default value: The same as before the teleportation
A TPEvent which has the appearance and the animation of a door.
{
"type" : "Door",
"textures" : "door",
"playID" : "door",
"trigger" : 1,
"framerate" : 1,
"position" : [ 35, 16 ],
"tp" : {
"position" : [ 9, 15 ],
"map" : "Rival's house"
}
}
A door is the composition of three event : an animation, a sound, and a teleportation. Their description in JSON can contain every field used by these three base types of events. The format used for the sprites is 42x36.
- type*: "Door" for this type of event.
A talking NPC.
{
"type" : "TalkingCharacter",
"moveStyle" : 1,
"path" : [ [ 1, 10 ], [ -1, 1 ], [ 2, 10 ], [ -1, 1 ] ],
"textures" : "kid",
"position" : [ 25, 21 ],
"dialog" : ["kid"],
"facing" : 1,
"passable" : false,
"trigger" : 0
}
This event is the composition of a CharacterEvent and a DialogEvent. Their description in JSON can contain every field used by these three base types of events.
- type*: "TalkingCharacter" for this type of event.
A trainer.
{
"type":"Trainer",
"prebattle":{
"textures":"beta",
"position":[11,32],
"dialog":["rt14.beta.pre"],
"facing":2,
"passable":false,
"trainer":"Beta"
},
"postbattle":{
"textures":"beta",
"dialog":["rt14.beta.post"],
"facing":2,
"passable":false
}
}
A trainer is the composition of three events : a talking character event, a battle event, and an another talking character event. This type has only three fields:
- type*: "Trainer" for this type of event.
- prebattle*: The data for the character before being defeated and for the battle. You can put any fields of a talking character event and a battle event.
- postbattle: The data for the character after the battle, basically a talking character event. If this field is not specified, the character after the battle is the same than before. If the position of the post battle character is 0,0 (the default position), the position will be set to be the same as the pre battle character when the battle ends.
LinearMetaEvent is a way to easily build your own meta event.
{
"type" : "LinearMeta",
"events" : [
{<event 1>},
{<event 2>}, ...
{<event n>}
],
"actions" : [false, true, true, ..., false]
}
- type*: "LinearMeta" for this type of event.
- events*: An array of events that will be interpreted as a queue. This array must contain all the event you meta event will process, in order. You can use all types of events, event other meta events or linear meta events. (Array of events)
- actions*: An array of booleans of the same size as the array of event. It determines, for the event at the same position in the array of events, if the linear meta event has to wait for every previous event to end before starting the new one (if
false
) or not (iftrue
). It allows to process several events at the same time. (Array of booleans) Note: If you want the process of your event to pause, you can use an empty event with the type "nullptr"
{ "type" : "nullptr" }
This event will instantly halt the execution of the linear meta event. A warning though, if any event is processing while the linear meta event processes a nullptr event, it will be stopped. So, if you don't want this, make sure the nullptr event is associated with false
in the actions array. The linear meta event will be resumed as soon as the player interacts again with the event.
The linear meta event doesn't stop when reaching the end of the array, it loops back. If you don't want this, just put a nullptr event at the end of the array of events to halt the process.
In the code, TalkingCharaEvent and DoorEvent are two LinearMetaEvents with some modifications but it works the same. So TalkingCharaEvent is made with an array of events [CharacterEvent, DialogEvent, nullptr] and an array of actions [false, false, false], and DoorEvent is made with an array of events [AnimationEvent, SoundEvent, TPEvent, nullptr] and an array of actions [false, true, false, false].
"dialog" : [ "ppHouse", "playername" ],
"dialog" : ["rivalHouse"],
The Dialog type is an array with the first element being the identifier of the dialog in the translation files, and everything that comes after being the different possible completions in the dialog.
- In the first example, the dialog "ppHouse" is, in English, "~'s house.". The ~ character means this has to be replaced by something else in the game. With "playername" specified, the game will replace ~ by the player's name. If there is several ~ in the dialog, you can add more elements after the identifier.
- In the second example, the dialog "rivalHouse" does not contain any ~ character. There is no need to add something after the dialog, so the array only contains one element.
- "playername" : The player's name.
#define SIDE_UP 0x0001 //1
#define SIDE_DOWN 0x0002 //2
#define SIDE_LEFT 0x0010 //16
#define SIDE_RIGHT 0x0020 //32
#define SIDE_ALL (SIDE_UP | SIDE_DOWN | SIDE_RIGHT | SIDE_LEFT)
Each number corresponds to a side, but you can mix numbers to indicate several sides. In the code, indicating "I want my event to be interactable from the sides up and down" would be "SIDE_UP | SIDE_DOWN" where | is the "or" binary operator. However, if you want to indicate that in the JSON, you'll have to manually calculate it.
enum class EventTrigger {
PRESS = 0,/*!< The event is triggered when the player presses the action key.*/
GO_IN = 1,/*!< The event is triggered when the player is moving to the tile.*/
ZONE = 2,/*!< The event is triggered as soon as the player sees it.*/
BE_IN = 3/*!< The event is triggered as long as the player is on its position.*/
};
Each number corresponds to an element of this enumeration.
enum class Side : int {
TO_DOWN = 0,
TO_RIGHT = 1,
TO_LEFT = 2,
TO_UP = 3,
NO_MOVE = -1,
STAY = -2
};
Each number corresponds to an element of this enumeration. For the player's facing direction after a teleportation, using NO_MOVE or STAY will simply be counter as the default value.
enum class MoveStyle : int {
NO_MOVE = 0,/*!< The npc has to stay still.*/
PREDEFINED = 1,/*!< The npc follows a predefined path.*/
RANDOM = 2,/*!< The npc moves randomly.*/
FOLLOWING = 3/*!< The npc follows the player (unimplemented yet).*/
};
Each number correspond to an element of this enumeration.
"path" : [ [ 1, 10 ], [ -2, 1 ], [ 2, 10 ], [ -2, 1 ] ],
Paths are an array of two-element arrays. Each two-element array describes some part of the movement. The first one is a Side element: it informs about where the event has to move. The second one is the number of time the movement has to be repeated. In our example, the NPC will walk 10 times to the right, won't move for one frame, will walk 10 times to the left, and won't move for one frame again. And then the movement repeats itself.
Note: Currently, -1 and -2 (NO_MOVE and STAY) have the same effect.