m (Text replacement - "[[OFPEC_tags" to "[[Scripting Tags")
(9 intermediate revisions by 2 users not shown)
Line 1:
Line 1:
{{TOC|side}}
{{TOC|side}}
A {{Link|Arma Reforger:World Editor|World Editor}} entity is a scripted entity that can be placed from the World Editor's [[Arma Reforger:World Editor#Create|'''Create''' tab]].
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|TAG_PrintPlayerPositionEntity}} so the file should be {{hl|TAG_PrintPlayerPositionEntity.c}}.
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 Entities classnames must end with the {{hl|Entity}} suffix.}}
{{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!}}
{{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!}}
Line 21:
Line 21:
=== Entity Class ===
=== Entity Class ===
An Entity requires an Entity Class declaration. This allows it to be visible in {{Link|Arma Reforger:World Editor|World Editor}}.
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
{
{
Line 50:
Line 50:
; visible
; visible
: have the bounding box always visible - drawn in {{hl|color}}
: have the bounding box always visible - drawn in {{hl|color}}
; insertable
:
; configRoot
; configRoot
Line 70:
Line 73:
; dynamicBox
; dynamicBox
: enables the entity visualiser using custom dimensions (provided by <enforce inline>_WB_GetBoundBox</enforce>)
: enables the entity visualiser using custom dimensions (provided by <enforce inline>_WB_GetBoundBox()</enforce>)
Line 79:
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.MAX; // trigger Print on start
protected float m_fWaitingTime = float.INFINITY; // trigger Print on start
protected int m_iCycleDuration = 10; // in seconds
protected int m_iCycleDuration = 10; // in seconds
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|World Editor}}, scripts must be compiled and reloaded ''via'' {{Controls|Shift|F7}}.}}
{{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}} ).}}
<span class="p">[</span><span class="nc">Attribute</span><span class="p">(</span>defvalue<span class="p">:</span> <span class="s">"1"</span><span class="p">,</span> desc<span class="p">:</span> <span class="s">"Print a message when player is null"</span><span class="p">)]</span>
<span class="om">Print</span><span class="p">(</span><span class="s">"Only one instance of TAG_PrintPlayerPositionEntity is allowed in the world!"</span><span class="p">,</span> <span class="nc">[./enfusion://ScriptEditor/scripts/Core/generated/Debug/LogLevel.c%3B13 LogLevel]</span><span class="p">.</span><span class="c">WARNING</span><span class="p">);</span>
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.
ⓘ
By convention, all Entity classnames must end with the Entity suffix, here TAG_PrintPlayerPositionEntity.
⚠
An entity script file must be created in the Game module (scripts/Game), otherwise it will not be listed in the Entities list!
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:
[EntityEditorProps(category:"Tutorial/Entities", description:"Prints player's position regularly")]classTAG_PrintPlayerPositionEntityClass:GenericEntityClass{}classTAG_PrintPlayerPositionEntity:GenericEntity{}
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.
classTAG_PrintPlayerPositionEntity:GenericEntity{protectedfloatm_fWaitingTime=float.INFINITY;// trigger Print on startprotectedintm_iCycleDuration= 10;// in seconds//------------------------------------------------------------------------------------------------protectedvoidPrintPlayerPosition(){PlayerController playerController =GetGame().GetPlayerController();if(!playerController)return;IEntity player = playerController.GetControlledEntity();if(!player){Print("Player entity position: no player",LogLevel.NORMAL);return;}Print("Player entity position: "+ player.GetOrigin(),LogLevel.NORMAL);}//------------------------------------------------------------------------------------------------overridevoidEOnFrame(IEntity owner,float timeSlice){m_fWaitingTime+= timeSlice;if(m_fWaitingTime<m_iCycleDuration)return;m_fWaitingTime= 0;PrintPlayerPosition();}//------------------------------------------------------------------------------------------------voidTAG_PrintPlayerPositionEntity(IEntitySource src,IEntity parent){SetEventMask(EntityEvent.FRAME);}}
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.
ⓘ
A singleton is an entity that can only be instanciated once. See Singleton pattern.
For that we will use the static keyword to keep a single reference:
classTAG_PrintPlayerPositionEntity:GenericEntity{// other propertiesprotectedstaticTAG_PrintPlayerPositionEntitys_Instance;// other methods//------------------------------------------------------------------------------------------------voidTAG_PrintPlayerPositionEntity(IEntitySource src,IEntity parent){if(s_Instance){Print("Only one instance of TAG_PrintPlayerPositionEntity is allowed in the world!",LogLevel.WARNING);deletethis;return;}s_Instance=this;// rest of the init code}}
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:
classTAG_PrintPlayerPositionEntity:GenericEntity{[Attribute(defvalue:"1", desc:"Print player position")]protectedboolm_bPrintPlayerPosition;[Attribute(defvalue:"1", desc:"Print a message when player is null")]protectedboolm_bPrintWhenPlayerIsNull;[Attribute(defvalue:"1", uiwidget:UIWidgets.Slider, desc:"Print cycle period (in seconds)", params:"1 30 1")]protectedintm_iCycleDuration;}
The following code contains code with the implemented attributes:
classTAG_PrintPlayerPositionEntity:GenericEntity{[Attribute(defvalue:"1", desc:"Print player position")]protectedboolm_bPrintPlayerPosition;[Attribute(defvalue:"1", desc:"Print a message when player is null")]protectedboolm_bPrintWhenPlayerIsNull;[Attribute(defvalue:"1", uiwidget:UIWidgets.Slider, desc:"Print cycle period (in seconds)", params:"1 30 1")]protectedintm_iCycleDuration;// other properties//------------------------------------------------------------------------------------------------protectedvoidPrintPlayerPosition(){PlayerController playerController =GetGame().GetPlayerController();if(!playerController)return;IEntity player = playerController.GetControlledEntity();if(!player){if(m_bPrintWhenPlayerIsNull)Print("Player entity position: no player",LogLevel.NORMAL);return;}Print("Player entity position: "+ player.GetOrigin(),LogLevel.NORMAL);}// other methods//------------------------------------------------------------------------------------------------voidTAG_PrintPlayerPositionEntity(IEntitySource src,IEntity parent){if(!m_bPrintPlayerPosition){deletethis;return;}// rest of the init code}}
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!
ⓘ
In order for the entity to appear in World Editor, scripts must be compiled and reloaded viaCompile & Reload Scripts function in Build tab ( ⇧ Shift + F7 ).
Final Code
The final file content can be found here:
[EntityEditorProps(category:"Tutorial/Entities", description:"Prints player's position regularly", color:"0 255 0 0")]classTAG_PrintPlayerPositionEntityClass:GenericEntityClass{}classTAG_PrintPlayerPositionEntity:GenericEntity{[Attribute(defvalue:"1", desc:"Print player position")]protectedboolm_bPrintPlayerPosition;[Attribute(defvalue:"1", desc:"Print a message when player is null")]protectedboolm_bPrintWhenPlayerIsNull;[Attribute(defvalue:"1", uiwidget:UIWidgets.Slider, desc:"Print cycle period (in seconds)", params:"1 30 1")]protectedintm_iCycleDuration;protectedfloatm_fWaitingTime=float.INFINITY;// trigger Print on startprotectedstaticTAG_PrintPlayerPositionEntitys_Instance;//------------------------------------------------------------------------------------------------protectedvoidPrintPlayerPosition(){PlayerController playerController =GetGame().GetPlayerController();if(!playerController)return;IEntity player = playerController.GetControlledEntity();if(!player){if(m_bPrintWhenPlayerIsNull)Print("Player entity position: no player",LogLevel.NORMAL);return;}Print("Player entity position: "+ player.GetOrigin(),LogLevel.NORMAL);}//------------------------------------------------------------------------------------------------overridevoidEOnFrame(IEntity owner,float timeSlice){m_fWaitingTime+= timeSlice;if(m_fWaitingTime<m_iCycleDuration)return;m_fWaitingTime= 0;PrintPlayerPosition();}//------------------------------------------------------------------------------------------------voidTAG_PrintPlayerPositionEntity(IEntitySource src,IEntity parent){if(s_Instance){Print("Only one instance of TAG_PrintPlayerPositionEntity is allowed in the world!",LogLevel.WARNING);deletethis;return;}if(!m_bPrintPlayerPosition){deletethis;return;}SetEventMask(EntityEvent.FRAME);s_Instance=this;}}