Create an Entity – Arma Reforger
Lou Montana (talk | contribs) (Page creation) |
Lou Montana (talk | contribs) m (Text replacement - "[[OFPEC_tags" to "[[Scripting Tags") |
||
(23 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{TOC|side}} | {{TOC|side}} | ||
A {{Link|Arma Reforger: | A {{Link|Arma Reforger:World Editor}} entity is a scripted entity that can be placed from the World Editor's [[Arma Reforger:World Editor#Create|'''Create''' tab]]. | ||
In this example, we will create an Entity that once placed in the world, will print the player's position with a certain frequency. | In this example, we will create an Entity that once placed in the world, will print the player's position with a certain frequency. | ||
Line 9: | Line 9: | ||
=== Entity === | === Entity === | ||
Create a new file and name it as your entity - here, we will go with {{hl| | Create a new file and name it as your entity - here, we will go with {{hl|[[Scripting Tags|TAG_]]PrintPlayerPositionEntity}} so the file should be {{hl|[[Scripting Tags|TAG_]]PrintPlayerPositionEntity.c}}. | ||
{{Feature|informative|By convention all | {{Feature|informative|By convention, all Entity classnames must end with the {{hl|Entity}} suffix, here {{hl|[[Scripting Tags|TAG_]]PrintPlayerPosition'''Entity'''}}.}} | ||
{{Feature|important|An entity script file '''must''' be created in the '''Game''' module ({{hl|scripts/Game}}), otherwise it will not be listed in the Entities list!}} | |||
<enforce> | <enforce> | ||
class TAG_PrintPlayerPositionEntity : GenericEntity | class TAG_PrintPlayerPositionEntity : GenericEntity | ||
{ | { | ||
} | } | ||
</enforce> | </enforce> | ||
=== Entity Class === | === Entity Class === | ||
An Entity requires an Entity Class declaration. This allows it to be visible in {{Link|Arma Reforger: | An Entity requires an Entity Class declaration. This allows it to be visible in {{Link|Arma Reforger:World Editor}}. | ||
The name must be '''exactly''' the Entity name suffixed by {{hl|Class}}, here {{hl|TAG_PrintPlayerPosition'''Class'''}}. | The name must be '''exactly''' the Entity name suffixed by {{hl|Class}}, here {{hl|TAG_PrintPlayerPosition''Entity''<nowiki/>'''Class'''}}. | ||
An Entity Class is usually placed just above the Entity definition as such: | An Entity Class is usually placed just above the Entity definition as such: | ||
<enforce> | <enforce> | ||
[EntityEditorProps(category: "Tutorial Entities", description: "Prints player's position regularly")] | [EntityEditorProps(category: "Tutorial/Entities", description: "Prints player's position regularly")] | ||
class TAG_PrintPlayerPositionEntityClass : GenericEntityClass | class TAG_PrintPlayerPositionEntityClass : GenericEntityClass | ||
{ | { | ||
} | } | ||
class TAG_PrintPlayerPositionEntity : GenericEntity | class TAG_PrintPlayerPositionEntity : GenericEntity | ||
{ | { | ||
} | } | ||
</enforce> | </enforce> | ||
The class is decorated using {{Link| | The class is decorated using {{Link/Enfusion|armaR|EntityEditorProps}}; the {{hl|category}} is where the Entity will be found in World Editor's '''Create''' tab - see {{Link|#EntityEditorProps|below}}. | ||
==== EntityEditorProps ==== | |||
; category | |||
: the "Create" tab's category in which the Entity can be found | |||
; description | |||
: '''unused''' (for now) | |||
; color | |||
: the bounding box's unselected line colour - useful only when {{hl|visible}} is set to {{hl|true}} | |||
; visible | |||
: have the bounding box always visible - drawn in {{hl|color}} | |||
; insertable | |||
: | |||
; configRoot | |||
: '''unused''' | |||
; icon | |||
: '''unused''': direct path to a {{hl|png}} file, e.g {{hl|WBData/EntityEditorProps/entityEditor.png}} | |||
; style | |||
: can be "none", "box", "sphere", "cylinder", "capsule", "pyramid", "diamond" | |||
; sizeMin | |||
: bounding box's lower dimensions | |||
; sizeMax | |||
: bounding box's higher dimensions | |||
; color2 | |||
: the bounding box's surface colour | |||
; dynamicBox | |||
: enables the entity visualiser using custom dimensions (provided by <enforce inline>_WB_GetBoundBox()</enforce>) | |||
Line 44: | Line 82: | ||
=== Add Code === | === Add Code === | ||
Let's use the {{hl|IEntity}}'s constructor to call code. | Let's use the {{hl|IEntity}}'s constructor to set flags and call code. | ||
<enforce> | <enforce> | ||
class TAG_PrintPlayerPositionEntity : GenericEntity | class TAG_PrintPlayerPositionEntity : GenericEntity | ||
{ | { | ||
protected float m_fWaitingTime = float.INFINITY; // trigger Print on start | |||
protected int m_iCycleDuration = 10; // in seconds | |||
//------------------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------------------ | ||
protected void PrintPlayerPosition() | protected void PrintPlayerPosition() | ||
Line 64: | Line 105: | ||
Print("Player entity position: " + player.GetOrigin(), LogLevel.NORMAL); | Print("Player entity position: " + player.GetOrigin(), LogLevel.NORMAL); | ||
} | |||
//------------------------------------------------------------------------------------------------ | |||
override void EOnFrame(IEntity owner, float timeSlice) | |||
{ | |||
m_fWaitingTime += timeSlice; | |||
if (m_fWaitingTime < m_iCycleDuration) | |||
return; | |||
m_fWaitingTime = 0; | |||
PrintPlayerPosition(); | |||
} | } | ||
Line 69: | Line 121: | ||
void TAG_PrintPlayerPositionEntity(IEntitySource src, IEntity parent) | void TAG_PrintPlayerPositionEntity(IEntitySource src, IEntity parent) | ||
{ | { | ||
SetEventMask(EntityEvent.FRAME); | |||
} | } | ||
} | } | ||
</enforce> | </enforce> | ||
Line 78: | Line 129: | ||
Let's assume we do not want the {{hl|Print}} to be displayed multiple times in the case someone placed multiple Entities in the world. | Let's assume we do not want the {{hl|Print}} to be displayed multiple times in the case someone placed multiple Entities in the world. | ||
{{Feature|informative|A singleton is an entity that can only be instanciated once. See {{ | {{Feature|informative|A singleton is an entity that can only be instanciated once. See {{Link|https://en.wikipedia.org/wiki/Singleton_pattern}}.}} | ||
For that we will use the {{Link|Arma Reforger:Scripting: Keywords#static 2|static}} keyword to keep a single reference: | For that we will use the {{Link|Arma Reforger:Scripting: Keywords#static 2|static}} keyword to keep a single reference: | ||
Line 85: | Line 136: | ||
class TAG_PrintPlayerPositionEntity : GenericEntity | class TAG_PrintPlayerPositionEntity : GenericEntity | ||
{ | { | ||
// other properties | |||
protected static TAG_PrintPlayerPositionEntity s_Instance; | protected static TAG_PrintPlayerPositionEntity s_Instance; | ||
// | // other methods | ||
//------------------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------------------ | ||
Line 107: | Line 156: | ||
// rest of the init code | // rest of the init code | ||
} | } | ||
} | } | ||
</enforce> | </enforce> | ||
Line 120: | Line 169: | ||
protected bool m_bPrintPlayerPosition; | protected bool m_bPrintPlayerPosition; | ||
[Attribute(defvalue: "1", desc: "Print | [Attribute(defvalue: "1", desc: "Print a message when player is null")] | ||
protected bool | protected bool m_bPrintWhenPlayerIsNull; | ||
[Attribute(defvalue: "1", uiwidget: UIWidgets.Slider, desc: "Print cycle period (in seconds)", params: "1 30 1")] | [Attribute(defvalue: "1", uiwidget: UIWidgets.Slider, desc: "Print cycle period (in seconds)", params: "1 30 1")] | ||
protected int m_iCycleDuration; | protected int m_iCycleDuration; | ||
} | } | ||
</enforce> | </enforce> | ||
The following code contains | The following code contains code with the implemented attributes: | ||
<enforce> | <enforce> | ||
Line 136: | Line 185: | ||
protected bool m_bPrintPlayerPosition; | protected bool m_bPrintPlayerPosition; | ||
[Attribute(defvalue: "1", desc: "Print | [Attribute(defvalue: "1", desc: "Print a message when player is null")] | ||
protected bool | protected bool m_bPrintWhenPlayerIsNull; | ||
[Attribute(defvalue: "1", uiwidget: UIWidgets.Slider, desc: "Print cycle period (in seconds)", params: "1 30 | [Attribute(defvalue: "1", uiwidget: UIWidgets.Slider, desc: "Print cycle period (in seconds)", params: "1 30 1")] | ||
protected int m_iCycleDuration; | protected int m_iCycleDuration; | ||
// other properties | |||
//------------------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------------------ | ||
Line 154: | Line 203: | ||
if (!player) | if (!player) | ||
{ | { | ||
if ( | if (m_bPrintWhenPlayerIsNull) | ||
Print("Player entity position: no player", LogLevel.NORMAL); | Print("Player entity position: no player", LogLevel.NORMAL); | ||
return; | return; | ||
Line 161: | Line 210: | ||
Print("Player entity position: " + player.GetOrigin(), LogLevel.NORMAL); | Print("Player entity position: " + player.GetOrigin(), LogLevel.NORMAL); | ||
} | } | ||
// other methods | |||
//------------------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------------------ | ||
Line 173: | Line 224: | ||
// rest of the init code | // rest of the init code | ||
} | } | ||
} | } | ||
</enforce> | </enforce> | ||
Now all there is to do is to place one {{hl|TAG_PrintPlayerPositionEntity}} entity in the world and see the player's position printed in logs! | Now all there is to do is to place one {{hl|TAG_PrintPlayerPositionEntity}} entity in the world and see the player's position printed in logs! | ||
{{Feature|informative|In order for the entity to appear in {{Link|Arma Reforger:World Editor}}, scripts must be compiled and reloaded ''via'' [[Arma_Reforger:Script_Editor#Menu_Bar|'''Compile & Reload Scripts''']] function in '''Build''' tab ( {{Controls|Shift|F7}} ).}} | |||
== Final Code == | == Final Code == | ||
Line 183: | Line 237: | ||
<spoiler text="Show File Content"> | <spoiler text="Show File Content"> | ||
<enforce> | <enforce> | ||
[EntityEditorProps(category: "Tutorial Entities", description: "Prints player's position regularly", color: "0 255 0 0")] | [EntityEditorProps(category: "Tutorial/Entities", description: "Prints player's position regularly", color: "0 255 0 0")] | ||
class TAG_PrintPlayerPositionEntityClass : GenericEntityClass | class TAG_PrintPlayerPositionEntityClass : GenericEntityClass | ||
{ | { | ||
} | } | ||
class TAG_PrintPlayerPositionEntity : GenericEntity | class TAG_PrintPlayerPositionEntity : GenericEntity | ||
Line 193: | Line 247: | ||
protected bool m_bPrintPlayerPosition; | protected bool m_bPrintPlayerPosition; | ||
[Attribute(defvalue: "1", desc: "Print | [Attribute(defvalue: "1", desc: "Print a message when player is null")] | ||
protected bool | protected bool m_bPrintWhenPlayerIsNull; | ||
[Attribute(defvalue: "1", uiwidget: UIWidgets.Slider, desc: "Print cycle period (in seconds)", params: "1 30 1")] | [Attribute(defvalue: "1", uiwidget: UIWidgets.Slider, desc: "Print cycle period (in seconds)", params: "1 30 1")] | ||
protected int m_iCycleDuration; | protected int m_iCycleDuration; | ||
protected float m_fWaitingTime = float.INFINITY; // trigger Print on start | |||
protected static TAG_PrintPlayerPositionEntity s_Instance; | protected static TAG_PrintPlayerPositionEntity s_Instance; | ||
Line 211: | Line 267: | ||
if (!player) | if (!player) | ||
{ | { | ||
if ( | if (m_bPrintWhenPlayerIsNull) | ||
Print("Player entity position: no player", LogLevel.NORMAL); | Print("Player entity position: no player", LogLevel.NORMAL); | ||
return; | return; | ||
Line 217: | Line 273: | ||
Print("Player entity position: " + player.GetOrigin(), LogLevel.NORMAL); | Print("Player entity position: " + player.GetOrigin(), LogLevel.NORMAL); | ||
} | |||
//------------------------------------------------------------------------------------------------ | |||
override void EOnFrame(IEntity owner, float timeSlice) | |||
{ | |||
m_fWaitingTime += timeSlice; | |||
if (m_fWaitingTime < m_iCycleDuration) | |||
return; | |||
m_fWaitingTime = 0; | |||
PrintPlayerPosition(); | |||
} | } | ||
Line 235: | Line 302: | ||
} | } | ||
SetEventMask(EntityEvent.FRAME); | |||
s_Instance = this; | s_Instance = this; | ||
} | } | ||
} | } | ||
</enforce> | </enforce> | ||
</spoiler> | </spoiler> | ||
{{GameCategory|armaR|Modding|Tutorials| | {{GameCategory|armaR|Modding|Tutorials|Scripting}} |
Latest revision as of 12:01, 2 October 2024
A World Editor entity is a scripted entity that can be placed from the World Editor's Create tab.
In this example, we will create an Entity that once placed in the world, will print the player's position with a certain frequency.
Declaration
Entity
Create a new file and name it as your entity - here, we will go with TAG_PrintPlayerPositionEntity so the file should be TAG_PrintPlayerPositionEntity.c.
Entity Class
An Entity requires an Entity Class declaration. This allows it to be visible in World Editor. The name must be exactly the Entity name suffixed by Class, here TAG_PrintPlayerPositionEntityClass. An Entity Class is usually placed just above the Entity definition as such:
The class is decorated using EntityEditorProps; the category is where the Entity will be found in World Editor's Create tab - see below.
EntityEditorProps
- category
- the "Create" tab's category in which the Entity can be found
- description
- unused (for now)
- color
- the bounding box's unselected line colour - useful only when visible is set to true
- visible
- have the bounding box always visible - drawn in color
- insertable
- configRoot
- unused
- icon
- unused: direct path to a png file, e.g WBData
/EntityEditorProps /entityEditor.png
- style
- can be "none", "box", "sphere", "cylinder", "capsule", "pyramid", "diamond"
- sizeMin
- bounding box's lower dimensions
- sizeMax
- bounding box's higher dimensions
- color2
- the bounding box's surface colour
- dynamicBox
- enables the entity visualiser using custom dimensions (provided by _WB_GetBoundBox())
Filling
The Entity is now visible in World Editor, the next step is to make it do something.
Add Code
Let's use the IEntity's constructor to set flags and call code.
Make It Unique
Let's assume we do not want the Print to be displayed multiple times in the case someone placed multiple Entities in the world.
For that we will use the static keyword to keep a single reference:
Add Properties
Now, we can declare properties with the Attribute in order to be able to adjust some settings from the World Editor interface. The following code only contains the added attributes:
The following code contains code with the implemented attributes:
Now all there is to do is to place one TAG_PrintPlayerPositionEntity entity in the world and see the player's position printed in logs!
Final Code
The final file content can be found here: