My First Weapon - Scripting

Overview

Continuing on from Part 1 of this tutorial, this article will guide you through the basic setup for weapon scripts in order to make your new weapon usable in the engine.

Bare Essentials Script

To keep this as simple as possible, we're going to start by creating a new weapon script that contains only what is absolutely necessary for the weapon to function.

Start by opening up your text editing tool. I'd recommend using the awesome (and free) Notepad++.

Copy the following code block into the new document and save it to the following folder: <GameFolder>\Scripts\entities\items\XML\weapons\newgun.xml

<item name="newgun" class="Weapon" category="primary" priority="1" weaponParams="1"> 
<!-- Name the weapon the same as the file. Class is used for GameCode. Priority 1 so it's selected first -->
<!-- weaponParams required to load specific weapon parameters (because we're in the Item system and its not always needed) -->

  <params>
        <param name="display_name" value="NewGun" /> <!-- Name of the weapon that will showup in the HUD for item pickup -->
        <param name="giveable" value="1" /> <!-- Indicates whether the item can be bought/picked up, "given" to the player -->
        <param name="selectable" value="1" /> <!-- Indicates whether the item can be selected in the player's inventory -->
        <param name="itemClass" value="rifle" /> <!-- Used by Mannequin as an additional tag "weaponType" -->
    <param name="suffix" value="shoulder" /> <!-- Used for animation, "shoulder" is the default aim mode, as opposed to ironsight, sniperscope, etc -->
        <param name="mass" value="2" /> <!-- The weight of the item (in kg) when dropped -->
        <param name="tag" value="SDKRifle" /> <!-- Main Mannequin tag used to indicate which fragments to play on this weapon -->
        <param name="adb" value="rifleWeaponAnims.adb" /> <!-- Load the mannequin animation database file -->
        <aimanims/> <!-- Bug that this is required and will be fixed -->
    </params>

  <ammos>
        <ammo name="RifleBullet" amount="60" capacity="60" /> <!-- Give the weapon 60 bullets when picked up. 60 is max capacity for inventory -->
    </ammos>

  <geometry>
        <firstperson name="objects/weapons/newgun/newgun_tp.cgf" /> <!-- Point to our new geometry -->
        <thirdperson name="objects/weapons/newgun/newgun_tp.cgf" /> <!-- For now, FirstPerson (1P/FP) and ThirdPerson (3P/TP) are the same -->
    </geometry>

  <firemodes>
        <firemode type="default"> <!-- Default or first selected firemode for the weapon -->
            <fire>
                <param name="hit_type" value="RifleBullet" /> <!-- Used to define behavior of objects when hit by this weapon -->
                <param name="ammo_type" value="RifleBullet" /> <!-- Ammo to be used by this weapon (typically would be same as <Ammos> defined earlier -->
                <param name="rate" value="600" /> <!-- Rate of fire for the weapon. 600 rounds per minute -->
                <param name="damage" value="300" /> <!-- Damage each bullet does to its target -->
                <param name="clip_size" value="30" /> <!-- Clip size of the weapon, 30 clip size/60 given ammo, gives us 2 clips basically -->
            </fire>
        </firemode>
        <firemode name="Rapid" type="Rapid"> <!-- Name can be whatever you want. Type is the Firemode from GameCode -->
            <fire>
                <param name="tag" value="rapid"/> <!-- Used by Mannequin to change the tag state so different sounds/anims execute -->
            </fire>
            <rapid> <!-- These used to define weapon behavior when firing. Rapid fire has accel/decel rates to define how quickly the weapon starts/stops firing -->
                <param name="min_speed" value="0.001" />
                <param name="max_speed" value="0.001" />
                <param name="acceleration" value="2.35" />
                <param name="deceleration" value="-3.0" />
            </rapid>
        </firemode>
    </firemodes>

</item>

Each function is labelled (commented out) in the script to give you an idea on what is required and why.

Sandbox Testing

Open Sandbox, create a new level and look for your weapon in the RollupBar. It should be located under Entity -> Items -> newgun


If you don't see it, check the console log and retrace your steps in this tutorial. Make sure you've saved your files, etc.

You should now be able to drag your weapon into the level:

Jump in game and pick it up! Fire off a few rounds and test the functionality:

Weapon IdleWeapon Firing
Weapon ReloadWeapon Idle Break (wiggle)

Adding Zoom Modes

One thing an astute tester may have noticed is that the weapon currently lacks an ironsight zoom mode, so the right mouse button currently doesn't do anything.

Copy the following code block into your newgun script, below the firemodes block (before the closing </item> line) and save the file:

    <zoommodes>
        <zoommode name="ironsight" type="IronSight">
            <stereo>
                <param name="eyeDistance" value="0.002" />
                <param name="convergenceDistance" value="0.01" />
            </stereo>
            <aimLookParams>
                <param name="fp_offset" value="-0.0535, -0.08, -0.012" />
                <param name="fp_rot_offset" value="0.0, 0.0, 0.0" />
                <param name="zoom_transition_angle" value="28.647889757" />
                <param name="look_offset" value="0.5,0.25" />
                <param name="horiz_look_rot" value="0.0,-1.0,-1.5" />
                <param name="vert_look_rot" value="0.1,0.0,0.0" />
                <param name="strafe_offset" value="0.2, 0.2, 0.1" />
                <param name="side_strafe_rot" value="0.0, 0.5, 0.0" />
                <param name="front_strafe_rot" value="0.5, 0.0, 0.0" />
                <param name="idle_speed" value="0.5" />
                <param name="idle_magnitude" value="0.2" />
                <param name="run_speed" value="0.75" />
                <param name="run_magnitude" value="0.2" />
            </aimLookParams>
            <zoom>
                <param name="suffix" value="iron" />
                <param name="suffixAG" value="_iron" />
                <param name="dof" value="1" />
                <param name="dof_mask" value="textures/weapons/ironzoom_blurmask.dds" />
                <param name="dof_focusMin" value="1.0" />
                <param name="dof_focusMax" value="100.0" />
                <param name="dof_focusLimit" value="300.0" />
                <param name="dof_shoulderMinZ" value="0.15" />
                <param name="dof_shoulderMinZScale" value="4.0" />
                <param name="dof_minZ" value="0.25" />
                <param name="dof_minZScale" value="0.6" />
                <param name="zoom_in_time" value="0.25" />
                <param name="zoom_out_time" value="0.25" />
                <param name="zoom_out_delay" value="0.15" />
                <param name="muzzle_flash_scale" value="0.55"/>
                <param name="shoulderMovementAnimFactor" value="0.8" />
                <param name="ironsightMovementAnimFactor" value="0.7" />
                <stages>
                    <stage value="1.4" />
                </stages>
            </zoom>
            <zoomSway>
                <param name="maxX" value="0.006" />
                <param name="maxY" value="0.008" />
                <param name="stabilizeTime" value="3.0"/>
                <param name="minScale" value="0.5"/>
                <param name="crouchScale" value="0.25"/>
                <param name="holdBreathScale" value="0.1" />
                <param name="holdBreathTime" value="0.5" />
            </zoomSway>
            <spreadMod>
                <param name="min_mod" value="0.001" />
                <param name="max_mod" value="0.1" />
                <param name="attack_mod" value="1.2" />
                <param name="decay_mod" value="1.0" />
                <param name="end_decay_mod" value="1.0" />
                <param name="speed_m_mod" value="0.25" />
                <param name="speed_holdBreathActive_m_mod" value="1.0" />
                <param name="rotation_m_mod" value="0.5" />
                <param name="spread_crouch_m_mod" value="0.75" />
                <param name="spread_jump_m_mod" value="1.0" />
                <param name="spread_slide_m_mod" value="1.0"/>
                <param name="spread_holdBreathActive_m_mod" value="0.75" />
            </spreadMod>
            <recoilMod>
                <param name="max_recoil_mod" value="1.0" />
                <param name="attack_mod" value="0.6" />
                <param name="first_attack_mod" value="0.6" />
                <param name="decay_mod" value="2.0" />
                <param name="end_decay_mod" value="1.5" />
                <param name="maxx_mod" value="1.25" />
                <param name="maxy_mod" value="1.75" />
                <param name="impulse_mod" value="1.0" />
                <param name="angular_impulse_mod" value="1.0" />
                <param name="back_impulse_mod" value="1.0" />
                <param name="recoil_crouch_m_mod" value="0.75" />
                <param name="recoil_jump_m_mod" value="1.0" />
                <param name="recoil_holdBreathActive_m_mod" value="1.25" />
            </recoilMod>
        </zoommode>
    </zoommodes>

In the interest of time/simplicity, we're going to cheat and copy/paste from the Rifle script. The parameters should be fairly self-explanatory. Ask away if not!

Now if we reload the script by going to Tools -> Reload Scripts -> Reload Item Scripts (or you can use i_reload in console) and jump in to check out our gun again, we now have ironsights!

Also check out your third person setup by pressing F1 to go into third person view.

You can also use g_DetachCamera 1 to leave the camera in its current location which allows you to position the player for different viewing angles. Remember to set it back to '0' when leaving/entering gamemode.

Third Person "Shoulder"Third Person "IronSight"
Third Person ReloadingThird Person Crouched Ironsight

It's now starting to show more clearly that our weapon model needs a bit more work! We're missing materials, textures, the shape doesn't quite work for the animations we've got as it's clipping through the camera, etc.

So head over to the next article for information on how to refine your weapon model.