Creating Weapons

This page will be dedicated to the process of creating a weapon in Lua.

First basic weapon
This is the process of creating a very basic weapon, such as the sword.

The first step is to create two files, Archetypes/Weapons/Model.txt and LuaScripts/Weapons/.lua. For example, I would create Archetypes/Weapons/SwordModel.txt and LuaScripts/Weapons/Sword.lua

The first file is used to create the model of the weapon in game, the file for the sword looks like this: Transform {  Position { 0 1 0 } Scale { 1.5 1.5 1.5 } Rotation { 0 0 0 } } Light {  Ambient { 0 0 0 0 } Diffuse { 247 182 41 0 } Specular { 247 182 41 0 } SpotPrams { 0 0 2 } Direction { 0 -1 0 } Range 3 Attenuation { 0 0 0.1 } LightType LightType::Point } SkinnedMesh {  Material {    Ambient 1 Emissive 0.05 SpecularPower 10 Diffuse { 224 178 78 255 } Specular { 255 255 255 0 } DiffuseTexture "" }  Model "sword" } Animation {} Hierarchy { } Any attributes on this archetype will be transferred to the object that the player holds.

Now onto creating the script that the weapon will use to interact with the game. First off, this line MUST be at the top of every weapon script: --Get current weapon local Weapon = ... This line gets the weapon class so that you can add variables and functions to it. Without this line your weapon will not work.

After adding that, it is useful to declare variables on the weapon so that aspects of the weapon can be easily modified by anyone looking at the file. For example, this is the header for the sword: --Weapon Stats Weapon.Archtype = "Sword" Weapon.Damage = 2 Weapon.OuterLength = 1.5 Weapon.InnerLength = 0 Weapon.Angle = 114 Weapon.PrimaryAttackTime = 0.4 None of these variables are required, however if another person wants to change the range or damage of the sword, these variables give them an easy way to do so.

After those lines, there are three functions that have to be added to the weapon for it to be functional. First is the OnBind function: function Weapon:OnBind --Code to bind the weapon to the player here end This function is called when the player first picked up a weapon. It is usually used to create models of the weapon/weapons in the players hand. To add that functionality, the OnBind function should look something like this: function Weapon:OnBind self:BindWeapon("Sword", "Hand1") end To briefly go into this function, the first argument is the archetype to add to the player. Note that "Model" will automatically be appended to the end of the given string. So in the above example the archetype "SwordModel" will be created and bound to the "Hand1" bone of the player. For more details into what bones are available to bind to, check the Skeletons page.

The last two functions that need to be overridden is the OnPrimaryAttack and OnSecondaryAttack functions, which look like this: function Weapon:OnPrimaryAttack --Code for primary attack here end function Weapon:OnSecondaryAttack --Code for secondary attack here end This is where a majority of the code will go to script the weapon. I will go through both of the functions for the sword weapon, and explain what it is doing.

Here is the OnPrimaryAttack for the sword: function Weapon:OnPrimaryAttack self:PlayAnimation("Attack", 0.35) WaitSeconds(0.2) self:DamageArc(self.Damage, self.Angle, self.OuterLength * self.Owner.Transform.Scale.x, self.InnerLength) self:EndPrimaryAttack(0.2) end The OnPrimaryAttack is pretty basic for the sword, it plays an animation on the player. Then creates a damage arc and ends the attack with a cooldown.

Here is the OnSecondaryAttack for the sword: function Weapon:OnSecondaryAttack local anim = self:PlayAnimation("Charge", 0.2):Loop(true) local chargeTime = self:ChargeWeapon if chargeTime > 0.2 then self.Owner.Space.Sound:PlayEffect("Swing") self:BuildArc(self.Damage, self.Angle, self.OuterLength * self.Owner.Transform.Scale.x, self.InnerLength) local numSpins = 1 numSpins += math.floor(chargeTime / 0.1) OverTime(numSpins * 0.1, function(percent)      self.Owner.Transform.Rotation = Quaternion(Vector3D(0,1,0), 360 * (numSpins) * percent)     end) --Disable collider self.ColliderObject:RemoveComponent(self.ColliderObject.ColliderArc) else self:OnPrimaryAttack end self:EndSecondaryAttack end This one is a lot more complicated, so I'll break it into separate chunks. The first line is playing a charging animation, which will loop when it is finished playing. We then get to these lines: local chargeTime = self:ChargeWeapon if chargeTime > 0.2 then self:ChargeWeapon is a pre-built function that will wait until the attack button has stopped being pressed, and then return the amount of time the weapon was charged for. If it was charged for more then 0.2 seconds, then the inside code triggers: self:BuildArc(self.Damage, self.Angle, self.OuterLength * self.Owner.Transform.Scale.x, self.InnerLength) This function builds an arc collider to deal damage, but unlike self:DamageArc this function does not delete the arc after a frame, allowing us to control what the arc does. local numSpins = 1 numSpins += math.floor(chargeTime / 0.1) OverTime(numSpins * 0.1, function(percent)  self.Owner.Transform.Rotation = Quaternion(Vector3D(0,1,0), 360 * (numSpins) * percent) end) These lines are calculating how much the player should spin, then spinning for that amount of time and spinning the player around. Since the arc collider is attached to the player, it will also spin during this time and deal damage to anything it touches. --Disable collider self.ColliderObject:RemoveComponent(self.ColliderObject.ColliderArc) Since we created the arc collider, we have to destroy it. self.ColliderObject references the object the arc collider is attached to.

Finally the script ends with self:EndSecondaryAttack, which ends the attack without an internal cooldown.

That ends the tutorial for a basic weapon, for more information check out the Weapon Documentation page.