Weapon scripts can do everything that map scripts can, they just don't have as many objects
The most confusing thing about a weapon script is probably the fact that it's
an object of type idWeapon. That means you don't have to specify an object
name when you send an event, because it sends the event to itself. Seasoned C++
programmers will recognize it as the hidden this pointer.
Normally you would say $something.hide();
but when the function is defined in an object, you can just say hide();
and it will automatically know what the object is. In the case of a weapon script,
the object is the weapon itself. You will see this again when looking at AI scripts
(the object will be the monster).
Let's analyze the weapon_pistol.script for a bit. Right after the #define section, we forward
declare the weapon_pistol object, and say it's going to inherit from weapon_base.
The inheritance allows us to put some common functions in weapon_base and have them available
to all weapons. We specify what variables and functions are going to be in our weapon. After
the object definition, we find declarations for all the functions we said we were going to have.
When a weapon is selected (with an impulse command or by picking it up), the init function is
called on the weapon object. Generally this will read some default values from the weapon
entityDef and set the weapon state to "Raise".
The weaponState function is the key to driving the weapon code. This function controls
transitioning from various weapon states, which are defined by member functions in the
weapon object. The first parameter is the name of the state to switch to (which should be
a function name), the second parameter is the number of frames over which to blend the
animation during the state change.
A good example of a state change is in weapon_pistol::Reload. The
function starts the reload animation and waits for it to finish. It then adds some bullets to
the clip and transitions to the Idle state. The animDone function takes a blend count as the
second argument. In this case the blend count is 4, so it will return true when there are only
4 frames left in the animation to play. We pass this same value to the weaponState function
so it knows that there are still 4 frames left to play in the current animation. The weaponState
function stores this information so when the idle animation starts playing, the first 4 frames
are blended with the last 4 frames of the previous animation (which was reload).
This animation blending allows smooth transitions between completely different animations without
really ugly jerky movements.
Handy Weapon Functions
|getOwner||Returns the player entity holding this weapon
|nextWeapon||Cycles to the next weapon in the player inventory
|weaponState [state], [blend]||(Described above)
|useAmmo [amount]||Subtracts ammo from the clip
|addToClip [amount]||Adds ammo to the clip
|ammoInClip||Returns how much ammo is in the clip
|ammoAvailable||Returns how many shots are left
|totalAmmoCount||Returns how much ammo is left
|clipSize||Returns the size of a clip
|weaponOutOfAmmo||Tells the game code that the weapon is out of ammo
|weaponReady||Tells the game code that the weapon is ready to fire
|weaponReloading||Tells the game code that the weapon is reloading
|weaponHolstered||Tells the game code that the weapon is lowered
|weaponRising||Tells the game code that the weapon is rising
|weaponLowering||Tells the game code that the weapon is lowering
|flashlight [enable]||Enable or disable a constant muzzle flash
Launches the projectile defined by "def_projectile" in the weapon entityDef.
It also subtracts the appropriate amount of ammo from the clip, sets up the
muzzle flash and smoke, alerts nearby AI, kicks the view back, and resets
shader parms 4 and 5 (diversity and timeOffset).
numProjectiles specifies how many projectiles are launched.
spread specifies the spread angle (in degrees).
fuseOffset specifies how far in the fuse should start (for grenades this
is how long you held the fire button).
launchPower is a value that is multiplied by the projectile
velocity (so 1.0 is normal velocity for the projectile). The grenades use this
to make it so holding down the button longer makes them go faster.
dmgPower is like launchPower but for the damage.
Creates and returns a new projectile entity defined by "def_projectile". It doesn't actually do
anything with the projectile except return it. You'll probably want to use launchProjectiles
almost every time. This function is currently only used by the hand grenade to have something
to attach the sound to.
|ejectBrass||Randomly tosses some debris entities defined by the "def_ejectBrass" key in the weapon entityDef.
|melee||Checks for entities within "melee_distance" range and does whatever is defined by "def_melee". This includes pushing, stealing, and damaging the other entity (as well as performing the sound). Returns true if something was hit.
|getWorldModel||Returns the entity for the actual animated weapon model.
Currently only used by the chaingun to spin the barrel on the model.
|allowDrop [allow]||Pass true to prevent the player from dropping the weapon.
Currently only used when the BFG overcharges.
|isInvisible||Returns true if the player has the invisibility powerup
|autoReload||Returns true if the player has "ui_autoReload" set.
|netReload||This function will cause the server send a reload event to the clients. The reload event signals WEAPON_NETRELOAD, which the weapon script catches to reload on the client side. This is needed so you can see when other clients are reloading their weapons. It should always be called before changing to the "Reload" weaponState.
|netEndReload||Similar to netReload, but called when the weapon is finished reloading.
Currently only used by the shotgun (because you can abort a reload).