This tutorial will try to explain how to add different player view weapons to the existing PV models, thus maintaining the existing set of animations. At the end of this tutorial, you should be able to do the following:
- add new attachments to the existing PV weapon models, like silencers, new scopes, a grenade launcher to the shotgun etc.
- replacing the existing weapons with new ones
In this tutorial, I’ll cover replacing the original disc with the shuriken
Raptor Red made.
The principle: muzzle flashes, incinerator’s pilot light etc.
All muzzle flashes, or the pilot light on the incinerator, all these are called player view special effects, PVFX-es to keep ot short. A PVFX usually is a binding between a scale FX (yep, another word, but stay with me) and a socket. ScaleFX-es can be either sprites or (and pay atention here) models. Yep, those .abc files. Sockets are entities in the player view model, used to attach items to the model. Sockets will also be animated, and they will follow the movement of the pv model part they were assigned to. So far, sockets and PVFX-es were used to add the muzzle flash to fire arms or, in the case of the incinerator, to place that blue flame (pilot light) at the end of the barrel.
Ok, if the PVFX can point (using the scale FX it contains) to a model, why not replace the entire weapon model with such an FX?
Step 1: Editing the weapon definition in Weapons.txt
The first step in our enterprise is to edit the weapon definition, in the attributes file. So, open Weapons.txt with you favourite text editor, and find the disc definition:
[Disc] Type = "Weapon" NameId = 7015 DescriptionId = 7065 AniType = 0 Icon = "Interface\StatusBar\Predator\inv_disc.pcx" PickupIcon = "" // the ammo will display, doing a weapon and ammo // is counter intuitive. PickupName = "Weapon_PDisc" Pos = <0.000000, -1.110000, 0.400000> PVModel = "Models\Weapons\Predator\pDisc_pv.abc" PVSkins0= "Skins\Weapons\Predator\pLeftHand_%s_pv.dtx" PVSkins1= "Skins\Weapons\Predator\pRightHand_%s_pv.dtx" PVSkins2= "" PVSkins3= "Skins\Weapons\Predator\pDisc_pv.dtx" HHModel = "Models\Weapons\Predator\pDisc_hh.abc" HHSkins0 = "Skins\Weapons\Predator\pDisc_hh.dtx" HHModelScale = <1.000000, 1.000000, 1.000000> AlphaFlag = 0 SelectSnd = "Sounds\Weapons\Predator\Disc\Select.wav" DeselectSnd = "Sounds\Weapons\Predator\Disc\Deselect.wav" Barrel0 = "Disc_Barrel" CounterType = 0 TargetingType = 5 LoopFireAnim = 0 LoopAltFireAnim = 0 /************************************************** * shuriPVFX points the shuriken scale FX * and thus links us to the new model ***************************************************/ PVFXName0 = "shuriPVFX" TargetingSprite = "" TargetingSpriteScale= <0.000000, 0.000000, 0.000000> CrosshairImage = "Interface\StatusBar\Predator\Xhair_pred.pcx" CrosshairScale = 1.000000 CrosshairAlpha = 0.600000 AimingPitchSet = 1 Melee = 1 SpeedMod = 1.000000 Save = 1 CacheInMP = 0
As you can probably see, I’ve added a new player view FX to the weapon definition. I’ve underlined the name of the PVFX, because we’ll need to:
- create a PVFX having this name, in FX.txt
- send ON (when selecting the disc) and OFF (when throwing the disc) messages to it, from the existing player view model.
So, write it down somewhere.
Step 2: Creating the PVFX and the ScaleFX objects
Well, for this task, we’ll have to open the FX.txt attribute file. To keep track of all changes made, we’ll first add the PVFX:
[PVFX19] Name = "shuriPVFX" // name, as set in the disc definition Socket = "Socket0" // the socket where the scale will appear // in our case, the socket we'll add to the pv model ScaleName0 = "shuri" // the name of the scale FX, see line 14500 SoundName0 = ""
And that gives us another couple of things to write down:
- the name of the socket: we’ll have to create a new socket in the existing pv model, and name it exactly as we named it here
- the name of the scale FX: we’ll have to create the scale in this very file, using the name written here.
One more thing: the numbering part from [PVFX19] must be the next number in line, ie: if the last existing PVFX was numbered 22, ours will be the 23rd and so on.
Next, we’ll need to create the scaleFX itself, and thus bring in the new model. The definition of the ScaleFX for the shuriken is placed at the end of the existing scaleFX descriptions. Just like the PVFX, the numbering part is actually the last number incremented:
/** * The new PV model will be attached as a player view s[pecial effect * However, the pvFX must use a scale FX * The following scale defines the shuriken, player view: * */ [ScaleFX325] Name = "shuri" // this is the name the shuriPVFX will ask for as // scale FX Type = 0 // => we want an .abc model as scale => type = 0 File = "Models\PDISC_HH.ABC" // obviously, the model and skin must Skin = "Skins\PDISC_HH.DTX" // exist on the specified location /** * The model is usually pretty big, so I'dd recomend to use a small * scale. Both scale values are equal, we don't want the weapon to * morph ... right? * */ InitialScale = <0.070000, 0.07, 0.07000> FinalScale = <0.070000, 0.07, 0.07000> /** * Funny, although the flag UseColors is 0, the colors are actually * taken in account. * */ UseColors = 0 InitialColor = <100, 100.000000, 150.000000> FinalColor = <100, 100.000000, 150.000000> /** * We want our new weapon opaque at all times * */ InitialAlpha = 1 FinalAlpha = 1 /** * No offset, no movement * */ DirOffset = 0 DirROffset = 0.0 DirUOffset = 0.0 Velocity = <0.000000, 0.000000, 0.000000> /** * The scale must have an infinite life time. Having your * weapon simply disappear is not funny, not to mention * not realistic * */ LifeTime = -1 DelayTime = 0.0 /** * If you set this one to 1, the scale will play the first animation * of the model. In our case, the first animation of the model * represents the model staying still, horizontally * */ Loop = 1 AlignToSurface = 1 NoZ = 0 /** * I have noticed that putting ReallyClose to 1 makes the scale * disappear. So, we'll have it set to 0. * */ ReallyClose = 0 /** * Blending types. Toy with them. * */ Additive = 1 Multiply = 1 /** * No rotation, and there's no point to force it to always face * the camera. * */ Rotate = 0 FaceCamera = 0 RotationAxis = 0 MinRotVel = 0.00 MaxRotVel = 0.00
The definition is petty long, but that’s because it has lots of comments in it. Read them, since they might explain why your model replacement might not show up. Another thing, regarding the skin. I didn’t want to use the alpha channel of the texture, so I removed it by compressing the texture 8x . At this point, our job with the attributes files is done. Just make sure that the model and skin you’re pointing to are there.
ModelEdit time …
Step 3: ModelEdit
Now, in order to make the shuriken visible, we’ll need to do the following:
- create the socket
- move the existing disc outside of the player’s view
- edit the animations, to send the ON and OFF commands to the PVFX
One of the first things you should do after opening ModelEdit is to make yure
you can see sockets. So, go Options -> Show Sockets:
Creating a socket is easy. Just select the node you’dd want the socket to follow in it’s animations, and click Socket->add socket. But wait! On which node should I add my socket?
At all times, you’ll have two choices:
- add the socket to one of the nodes from the existing weapon
- add the socket to one of the hands
In our case, I decided to add it to the right wrist:
After adding the socket, you’ll notice that the socket is placed right inside the wrist. The new shuriken will look like it’s cutting the hand of the predator. We’ll have to move the socket a bit. So, in preparation to move the socket:
- select the idle or fire animation (in the Animations frame)
- select the new socket (in the Sockets frame)
- in the “Transform Edit” frame (lower part of MEDit) check the “Global” box, and toggle the radio button to socket.
I wanted to move the socket a bit forward (positive sense on the Z – blue – axis). So, what I did was to click on the blue “Translation” square and dragged the mouse. You’ll notice the socket moving. No problem if the socket moved in the wrong direction, just change the dragging direction, say from going right to going left.
The main idea is to have the socket laying in the center of the existing disc, because the socket will mark where the new weapon will be shown.
Speaking of the existing disc, we should move it away now that our socket was placed. To do that, you’ll need to:
- select one of the animations, preferably idle or fire
- select the nodes making the disc (use SHIFT for multiple selections)
- in the “Transform Edit” frame (lower part of MEDit) check the “Global” box, and toggle the radio button to relation.
Now, just like we did for the socket, click and drag the blue translation square so that the disc is placed waaaay back:
As a final touch, you’ll need to edit the Frame String (bottom of MEDit) of the Select, Fire0 and Fire1 animations. What you really want to do is:
- turn on the PVFX at the begining of the Select animation (I used the second frame of the animation):
- turn off the disc after it has been launched (I used the second frame after
the fire_key frame):
A last touch might be changing the string from the last frame in the fire animations, from “force_last_weapon_key” to “force_next_weapon_key”, but it’s not mandatory:
Moose Head’s finishing touch
The following information was extracted from an e-mail received from Moose_Head. Thank you, Moose.
So far, the attached models can follow the sockets only if the amplitude of the movement is small. Even for small movements, the attachment still looks like it’s floating over the original model. To fix this behavior, you must set the FOV offset of the attached .abc model to 0, 0. To do this, you must set the final command string of the model to FOVXOffset 0; FOVYOffset 0; So, open the .abc model of the attachment, and select Model->Command String:
Put the value of 0 in both FOV Offset fields (for both X and Y):
Save the model and you’re done …
The archive contains a small .rez file and the document. The .rez has a small custom map, for testing. It can be accessed from the custom level menu, after placing the .rez in the command line. Enjoy.