## Engine
Class Weapon

source: C:\XIII\Engine\Classes\Weapon.uc

    Core.Object
       |
       +--Engine.Actor
          |
          +--Engine.Inventory
             |
             +--Engine.Weapon

Direct Known Subclasses:XIIIWeapon

class Weapon
extends Engine.Inventory

    //=============================================================================
    // Parent class of all weapons.
    //=============================================================================

Variables
`float` | `AIRating` used for shakes on AltFire
`Rotator` | `AdjustedAim` how far instant hit trace Altfires go (Units = Meters sorry for the non-metric system guys)
`class` | `AltAmmoName` Type of Alt ammo used.
`Ammunition` | `AltAmmoType` Inventory Alt Ammo being used.
`float` | `AltFireNoise` Noise made by the weapon when firing
`vector` | `AltFireOffset` Offset from first person eye position for projectile/trace start
`byte` | `AltFlashCount` when incremented, draw alt muzzle flash for current frame (on-line used)
`int` | `AltPickupAmmoCount` Amount of Alt ammo initially in pick-up item.
`byte` | `AltReloadCount` Amount of Alt ammo depletion before reloading. 0 if no reloading is done.
`float` | `AltShakeCycles` used for shakes on AltFire
`float` | `AltShakeMag` used for shakes on AltFire
`vector` | `AltShakeSpeed` used for shakes on AltFire
`float` | `AltShakeTime` used for shakes on AltFire
`vector` | `AltShakeVert` used for shakes on AltFire
`float` | `AltTraceDist` how far instant hit trace Altfires go (Units = Meters sorry for the non-metric system guys)
`vector` | `AltViewFeedBack` to make view change when altfiring, X = horiz, Y = Vert,
`class` | `AmmoName` Type of ammo used.
`Ammunition` | `AmmoType` Inventory Ammo being used.
`Texture` | `CrossHair` Crosshair Texture
`bool` | `DBDual` when incremented, reload for clients
`bool` | `DBWeap` when incremented, reload for clients
`name` | `EmptyAltFiringAnim` texture to use for Zoomed mode to show stability
`name` | `EmptyFiringAnim` texture to use for Zoomed mode to show stability
`vector` | `FPMFRelativeLoc` FirstPersonMuzzleFlash relative Location
`Rotator` | `FPMFRelativeRot` FirstPersonMuzzleFlash relative Rotation
`float` | `FireNoise` Noise made by the weapon when firing
`vector` | `FireOffset` Offset from first person eye position for projectile/trace start
`name` | `FiringMode` firing mode to use, sent to the pawn to play right anim
`InventoryAttachment` | `FirstPersonMF` FirstPerson Muzzle Flash actor
`class` | `FirstPersonMFClass` FirstPerson Muzzle Flash actor class
`byte` | `FlashCount` when incremented, draw muzzle flash for current frame (on-line used)
`float` | `FlashTime` time when muzzleflash will be cleared (set in RenderOverlays())
`name` | `LoadedAltFiringAnim` texture to use for Zoomed mode to show stability
`name` | `LoadedFiringAnim` texture to use for Zoomed mode to show stability
`Texture` | `MFTexture` first-person muzzle flash sprite
`string` | `MeshName` to allow dynamic load of mesh (optimize memory)
`string` | `MessageNoAmmo` Playing on Active Waiting
`Weapon` | `MySlave` the actor being the slave if bHaveSlave.
`name` | `NextSlaveState` Used to handle Salve unsynchronized behaviour
`int` | `PickupAmmoCount` Amount of ammo initially in pick-up item.
`float` | `ReLoadNoise` Noise made by the weapon when ReLoading
`byte` | `ReloadClientCount` when incremented, reload for clients
`byte` | `ReloadCount` Amount of ammo depletion before reloading. 0 if no reloading is done.
`int` | `RumbleFXNum` Rumble FX effect to use for this weapon.
`float` | `ScopeFOV` FOV to use in zoom
`float` | `ShakeCycles` used for shakes on Fire
`float` | `ShakeMag` used for shakes on Fire
`vector` | `ShakeSpeed` used for shakes on Fire
`float` | `ShakeTime` used for shakes on Fire/
`vector` | `ShakeVert` used for shakes on Fire
`float` | `ShotTime` How long we wait after a shoot to go again // Used by IA controllers
`Actor` | `Silencer` the silencer object to put on weapon.
`Weapon` | `SlaveOf` the actor being the master if bIsSlave.
`Texture` | `StabilityTex` texture to use for Zoomed mode to show stability
`float` | `StopFiringTime` repeater weapons use this
`float` | `TraceAccuracy` Accuracy of the traces (in 21211447f TraceDist)
`float` | `TraceDist` how far instant hit trace fires go (Units = Meters sorry for the non-metric system guys)
`vector` | `ViewFeedBack` to make view change when firing, X = horiz, Y = Vert,
`Emitter` | `WRE` WaterRingsEmmiter, to setup the HitSoundType on the emitter.
`Texture` | `ZCrosshair` texture to use for Zoomed Crosshair
`Texture` | `ZCrosshairDot` texture to use for Zoomed Crosshair (the dot)
`bool` | `bAllowEmptyShot` some weapons don't allow empty shot.
`bool` | `bAllowShot` lock Shot for Semi-auto weapons if keeping fire pressed (must press fire again)
`bool` | `bAltEmptyShot` True if we tried to Altshoot a weapon without ammo
`bool` | `bAutoReload` Should we reload just after firing ?
`bool` | `bCanHaveSlave` Can we have a slave ? (Dual weapons)
`bool` | `bCanThrow` if true, player can toss this weapon out
`bool` | `bChangeWeapon` Used in Active State
`bool` | `bDrawAltMuzzleFlash` enable first-person muzzle flash for AltFire
`bool` | `bDrawCrosshairOutZoom` To be used for sniping weapons (no crosshair if not in zoom)
`bool` | `bDrawMuzzleFlash` enable first-person muzzle flash
`bool` | `bDrawZoomedCrosshair` if we need to draw the zoomed crosshair (because Interaction draw after HUD = bug of zoomed CH masking everything else)
`bool` | `bEmptyShot` True if we tried to shoot a weapon without ammo
`bool` | `bEnableSlave` to allow use of Altfire to switch between single/dual weapon
`bForceFire,` | `bForceAltFire` Used to handle forcing fire in Finish
`bool` | `bForceReload` used to handle reload in Finish
`bool` | `bHaveAltFire` this weapon have a AltFire
`bool` | `bHaveBoredSfx` To enable bored effect
`bool` | `bHaveScope` Do we have a zoom on this weapon (used by Altfire)
`bool` | `bHaveSlave` do the weapon have a slave ? (Dual Weapons)
`bool` | `bHeavyWeapon` Used to slow pawn when holding this
`bool` | `bIsSlave` is this weapon a slave ? (dual Weapons)
`bool` | `bMeleeWeapon` Weapon is only a melee weapon
`bool` | `bMuzzleFlash` if !=0 show first-person muzzle flash
`bool` | `bRapidFire` used by pawn animations in determining firing animation, and for net replication
`bool` | `bRendered` used to be unhidden only when rendering overlays
`bool` | `bSetFlashTime` reset FlashTime clock when false
`bool` | `bShouldGoThroughTraversable` true if we want the shoots go through the XIIIMover with bTraversable=True
`bool` | `bTraceBullets` Do we trace bullets
`bool` | `bUnderWaterWork` true if the weapon works underwater.
`bool` | `bUseSilencer` true if the weapon can use the silencer.
`bool` | `bZoomed` to use zoom
`enum` | `eWeaponHand` used to be unhidden only when rendering overlays
`enum` | `eWeaponMode` used to be unhidden only when rendering overlays
`float` | `fAltZoomValue[3]` Values of the Fov factors for each levels of Alt zooming system
`float` | `fTraceBulletCount` to decide if we should trace the bullet using bool bTraceBullets
`float` | `fVarAccuracy` variable accuracy (low for First shot, up to TraceAccuracy in 5 shots)
`sound` | `hActWaitSound` Playing on Active Waiting
`sound` | `hAltFireSound` Playing on AltFire
`sound` | `hFireSound` Playing on Fire
`sound` | `hNoAmmoSound` Playing on EmptyFire
`sound` | `hReloadSound` Playing on Reload
`sound` | `hSelectWeaponSound` Playing on SelectWeapon
`sound` | `hZoomSound` Playing on Zooming (params for zoom/unzoom/stop)
`int` | `iAltZoomLevel` Number of zooming levels (for Alternative zooming system)
`int` | `iBoredCount` For special 'i'm bored' effect :)
`int` | `iBurstCount` to handle burst mode
`sWeaponModeSemiAuto,` | `sWeaponModeBurst` Rumble FX effect to use for this weapon.

States
PendingClientWeaponSet, ClientFiring, DownWeapon, Active, while, Reloading, Idle, NormalAltFire, NormalFire

Function Summary
`simulated` | `AltFire(float Value)`
    /* AltFire()
    Weapon mode change.
    */
`float` | `AmmoStatus()`
    //_____________________________________________________________________________
    //return percent of full ammo (0 to 1 range)
`simulated` | `AnimEnd(int Channel)`
`simulated` | `BringUp()`
    //_____________________________________________________________________________
`simulated` | `BringUpNoSlave()`
    //_____________________________________________________________________________
`void` | `CauseAltFire()`
`simulated` | `ClientFinish()`
`void` | `ClientForceReload()`
`void` | `ClientReLoad()`
    //_____________________________________________________________________________
    // Need this to force the server to reload.
`simulated` | `ClientWeaponSet(bool bOptionalSet)`
    //_____________________________________________________________________________
    // Compare self to current weapon.  If better than current weapon, then switch
`simulated` | `DisplayDebug(Canvas Canvas, out float, out float)`
    //_____________________________________________________________________________
    // list important controller attributes on canvas
`void` | `DropFrom(vector StartLocation)`
    //_____________________________________________________________________________
    // Toss this weapon out
`void` | `Finish()`
    // Finish a sequence
`simulated` | `Fire(float Value)`
`simulated` | `ForceReload()`
    /* Force reloading even though clip isn't empty.  Called by player controller exec function,
    and implemented in idle state */
`string` | `GetAmmoText(out int)`
    //_____________________________________________________________________________
`vector` | `GetFireStart(vector X, vector Y, vector Z)`
    //_____________________________________________________________________________
    simulated
`vector` | `GetFireStart(vector X, vector Y, vector Z)`
    //_____________________________________________________________________________
    simulated
`vector` | `GetFireStart(vector X, vector Y, vector Z)`
    //_____________________________________________________________________________
    simulated
`simulated` | `GiveAltAmmo(Pawn Other)`
    //_____________________________________________________________________________
    // ELR ADD Possibility that PickUpAmmoCount < ReLoadCount (else Bug)
`void` | `GiveAmmo(Pawn Other)`
    //_____________________________________________________________________________
`void` | `GiveTo(Pawn Other)`
    //_____________________________________________________________________________
`bool` | `HandlePickupQuery(Pickup Item)`
    //_____________________________________________________________________________
    // If picking up another weapon of the same class, add its ammo.
    // If ammo count was at zero, check if should auto-switch to this weapon.
`bool` | `HasAltAmmo()`
    //_____________________________________________________________________________
`bool` | `HasAmmo()`
    /*
    simulated
`bool` | `HasAmmo()`
    /*
    simulated
`bool` | `HasSilencer()`
    //_____________________________________________________________________________
`simulated` | `IncrementAltFlashCount()`
    //_____________________________________________________________________________
    //Tell WeaponAttachment to cause client side weapon firing effects
`simulated` | `IncrementFlashCount()`
    //_____________________________________________________________________________
    //Tell WeaponAttachment to cause client side weapon firing effects
    // 473
`simulated` | `IncrementReloadClientCount()`
    //_____________________________________________________________________________
    //Tell WeaponAttachment to cause client side weapon firing effects
`simulated` | `LocalFire()`
`bool` | `NeedsToReload()`
`void` | `NewWeaponNotify(Pawn Other)`
    //_____________________________________________________________________________
`Weapon` | `NextWeapon(Weapon CurrentChoice, Weapon CurrentWeapon)`
    //_____________________________________________________________________________
`Weapon` | `PrevWeapon(Weapon CurrentChoice, Weapon CurrentWeapon)`
    //_____________________________________________________________________________
    // Find the previous weapon (using the Inventory group)
`void` | `ProjectileFire()`
    {
        if ( bZoomed )
          return (Instigator.Location + Instigator.EyePosition() + FireOffset.X * X);
        else
          return (Instigator.Location + Instigator.EyePosition() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z);
    }
    */
`float` | `RateSelf()`
    //_____________________________________________________________________________
    // sets appropriate weapon configuration, and returns rating based on that configuration
`Weapon` | `RecommendWeapon(out float)`
`simulated` | `RenderSlaveOverlays(Canvas Canvas)`
    //_____________________________________________________________________________
    // If this is called then just setup pos & render because primary weapon is already rendered
`bool` | `RepeatFire()`
    //**************************************************************************************
    //
    // Firing functions and states
    //
`simulated` | `RumbleFX()`
    //_____________________________________________________________________________
    // Prototype
`void` | `ServerAltFire()`
`void` | `ServerFire()`
`void` | `ServerForceReload()`
`void` | `ServerRapidFire()`
`void` | `ServerReLoad()`
    //_____________________________________________________________________________
    // Need this to force the server to reload.
`void` | `ServerStopFiring()`
`simulated` | `SetHand(float Hand)`
    //_____________________________________________________________________________
    // set which hand is holding weapon
`void` | `SetUpDual(Weapon Dual, Pawn other)`
    //_____________________________________________________________________________
`simulated` | `SetupMuzzleFlash()`
    //_____________________________________________________________________________
`bool` | `ShouldDrawCrosshair(optional Canvas)`
    //_____________________________________________________________________________
`simulated` | `SlaveBringUp()`
    //_____________________________________________________________________________
`simulated` | `SlaveFire()`
    //_____________________________________________________________________________
`void` | `StaticParseDynamicLoading(LevelInfo MyLI)`
    //_____________________________________________________________________________
`float` | `SwitchPriority()`
    // Return the switch priority of the weapon (normally AutoSwitchPriority, but may be
    // modified by environment (or by other factors for bots)
`void` | `TraceFire(float Accuracy, float YOffset, float ZOffset)`
`void` | `Transfer(Pawn Other)`
    //_____________________________________________________________________________
`Weapon` | `WeaponChange(byte F)`
    //_____________________________________________________________________________
    // Change weapon to that specificed by F matching inventory weapon's Inventory Group.
`Weapon` | `WeaponSelect(byte F)`
    //_____________________________________________________________________________
    // ELR New function from WeaponChange to avoid potential bugs (this is to be used for SelectWeapon bind)

State PendingClientWeaponSet Function Summary
`void` | `PlayFiringSound(optional bool)`
`bool` | `PutDown()`

State ClientFiring Function Summary
`void` | `ClientWeaponSet()`
    /* PendingClientWeaponSet
    Weapon on network client side may be set here by the replicated
`void` | `AltFire(float Value)`
`void` | `Fire(float Value)`

State DownWeapon Function Summary
`bool` | `PutDown()`
`void` | `ServerAltFire()`
`void` | `ServerFire()`
`void` | `AltFire(float Value)`
`void` | `Fire(float Value)`

State Active Function Summary
`bool` | `PutDown()`
`void` | `ServerAltFire()`
`void` | `ServerFire()`
`void` | `AltFire(float Value)`
`void` | `Fire(float Value)`

State while Function Summary

State Reloading Function Summary
`bool` | `PutDown()`
`void` | `ServerAltFire()`
`void` | `ServerFire()`
`void` | `AltFire(float Value)`
`void` | `Fire(float Value)`
`void` | `ClientForceReload()`
`void` | `ServerForceReload()`

State Idle Function Summary
`bool` | `PutDown()`
`void` | `ServerForceReload()`

State NormalAltFire Function Summary
`void` | `EndState()`
`void` | `AnimEnd(int Channel)`
`void` | `AltFire(float F)`
`void` | `Fire(float F)`
`void` | `ServerAltFire()`
`void` | `ServerFire()`

State NormalFire Function Summary
`void` | `EndState()`
`void` | `AnimEnd(int Channel)`
`void` | `AltFire(float F)`
`void` | `Fire(float F)`
`void` | `ServerAltFire()`
`void` | `ServerFire()`

Source Code

    00001	//=============================================================================
    00002	// Parent class of all weapons.
    00003	//=============================================================================
    00004	class Weapon extends Inventory
    00005	  abstract
    00006	  native
    00007	  nativereplication;
    00008
    00009	#exec Texture Import File=Textures\Weapon.pcx Name=S_Weapon Mips=Off MASKED=1 COMPRESS=DXT1
    00010
    00011	//_____________________________________________________________________________
    00012	// Bools
    00013	var bool bChangeWeapon;             // Used in Active State
    00014	var bool bCanThrow;                 // if true, player can toss this weapon out
    00015	var bool bRapidFire;                // used by pawn animations in determining firing animation, and for net replication
    00016	var bool bForceReload;              // used to handle reload in Finish
    00017	var bool bMeleeWeapon;              // Weapon is only a melee weapon
    00018	var bool bForceFire, bForceAltFire; // Used to handle forcing fire in Finish
    00019	var bool bHaveAltFire;              // this weapon have a AltFire
    00020	var bool bEmptyShot;                // True if we tried to shoot a weapon without ammo
    00021	var bool bAllowEmptyShot;           // some weapons don't allow empty shot.
    00022	var bool bAllowShot;                // lock Shot for Semi-auto weapons if keeping fire pressed (must press fire again)
    00023	var bool bHaveScope;                // Do we have a zoom on this weapon (used by Altfire)
    00024	var bool bZoomed;                   // to use zoom
    00025	var bool bDrawCrosshairOutZoom;     // To be used for sniping weapons (no crosshair if not in zoom)
    00026	var bool bUnderWaterWork;           // true if the weapon works underwater.
    00027	var bool bUseSilencer;              // true if the weapon can use the silencer.
    00028	var bool bShouldGoThroughTraversable; // true if we want the shoots go through the XIIIMover with bTraversable=True
    00029	var bool bTraceBullets;             // Do we trace bullets
    00030	var bool bDrawZoomedCrosshair;      // if we need to draw the zoomed crosshair (because Interaction draw after HUD = bug of zoomed CH masking everything else)
    00031	var bool bAutoReload;               // Should we reload just after firing ?
    00032	var bool bAltEmptyShot;             // True if we tried to Altshoot a weapon without ammo
    00033	var bool bDrawAltMuzzleFlash;       // enable first-person muzzle flash for AltFire
    00034	var bool bHeavyWeapon;              // Used to slow pawn when holding this
    00035	var bool bHaveBoredSfx;             // To enable bored effect
    00036	var bool bCanHaveSlave;             // Can we have a slave ? (Dual weapons)
    00037	var bool bHaveSlave;                // do the weapon have a slave ? (Dual Weapons)
    00038	var bool bIsSlave;                  // is this weapon a slave ? (dual Weapons)
    00039	var bool bEnableSlave;              // to allow use of Altfire to switch between single/dual weapon
    00040	var bool bMuzzleFlash;              // if !=0 show first-person muzzle flash
    00041	var bool bSetFlashTime;             // reset FlashTime clock when false
    00042	var bool bDrawMuzzleFlash;          // enable first-person muzzle flash
    00043	var bool bRendered;                 // used to be unhidden only when rendering overlays
    00044
    00045	var enum eWeaponHand
    00046	{
    00047	    WHA_Fist,
    00048	    WHA_1HShot,
    00049	    WHA_2HShot,
    00050	    WHA_Throw,
    00051	    WHA_Deco,
    00052	} WHand;                            // Weapon type (hand using) meant for animsations & restrictions
    00053	var enum eWeaponMode
    00054	{
    00055	    WM_Auto,
    00056	    WM_SemiAuto,
    00057	    WM_Burst,
    00058	} WeaponMode;                       // Weapon Mode for Semi-auto guns.
    00059
    00060	//_____________________________________________________________________________
    00061	// Weapon/ammo information:
    00062	var class<ammunition> AmmoName;     // Type of ammo used.
    00063	var class<ammunition> AltAmmoName;  // Type of Alt ammo used.
    00064	var int PickupAmmoCount;            // Amount of ammo initially in pick-up item.
    00065	var int AltPickupAmmoCount;         // Amount of Alt ammo initially in pick-up item.
    00066	var travel ammunition AmmoType;     // Inventory Ammo being used.
    00067	var travel ammunition	AltAmmoType;  // Inventory Alt Ammo being used.
    00068	var travel byte ReloadCount;               // Amount of ammo depletion before reloading. 0 if no reloading is done.
    00069	var travel byte AltReloadCount;            // Amount of Alt ammo depletion before reloading. 0 if no reloading is done.
    00070	var string MeshName;                // to allow dynamic load of mesh (optimize memory)
    00071	var actor Silencer;                 // the silencer object to put on weapon.
    00072	var float StopFiringTime;           // repeater weapons use this
    00073	var vector FireOffset;              // Offset from first person eye position for projectile/trace start
    00074	var vector AltFireOffset;           // Offset from first person eye position for projectile/trace start
    00075	var texture CrossHair;              // Crosshair Texture
    00076	var float TraceAccuracy;            // Accuracy of the traces (in % of TraceDist)
    00077	var int iBurstCount;                // to handle burst mode
    00078	var float fVarAccuracy;             // variable accuracy (low for First shot, up to TraceAccuracy in 5 shots)
    00079	var float ScopeFOV;                 // FOV to use in zoom
    00080	var float ShotTime;                 // How long we wait after a shoot to go again // Used by IA controllers
    00081	var name FiringMode;                // firing mode to use, sent to the pawn to play right anim
    00082	var float FireNoise;                // Noise made by the weapon when firing
    00083	var float ReLoadNoise;              // Noise made by the weapon when ReLoading
    00084	var float AltFireNoise;             // Noise made by the weapon when firing
    00085	var float fTraceBulletCount;        // to decide if we should trace the bullet using bool bTraceBullets
    00086	var texture ZCrosshair;             // texture to use for Zoomed Crosshair
    00087	var texture ZCrosshairDot;          // texture to use for Zoomed Crosshair (the dot)
    00088	var texture StabilityTex;           // texture to use for Zoomed mode to show stability
    00089	var name LoadedFiringAnim;
    00090	var name EmptyFiringAnim;
    00091	var name LoadedAltFiringAnim;
    00092	var name EmptyAltFiringAnim;
    00093	var vector ViewFeedBack;            // to make view change when firing, X = horiz, Y = Vert,
    00094	var vector AltViewFeedBack;         // to make view change when altfiring, X = horiz, Y = Vert,
    00095	var int iAltZoomLevel;              // Number of zooming levels (for Alternative zooming system)
    00096	var float fAltZoomValue[3];         // Values of the Fov factors for each levels of Alt zooming system
    00097	                                    // Should be -(85/factor - 90)/88 defaults to x3, x8 & x12
    00098	var int iBoredCount;                // For special 'i'm bored' effect :)
    00099	var int RumbleFXNum;                // Rumble FX effect to use for this weapon.
    00100	var const localized string sWeaponModeAuto, sWeaponModeSemiAuto, sWeaponModeBurst;
    00101	                                    // to display Weapon mode
    00102	var InventoryAttachment FirstPersonMF;              // FirstPerson Muzzle Flash actor
    00103	var class<InventoryAttachment> FirstPersonMFClass;  // FirstPerson Muzzle Flash actor class
    00104	var() vector FPMFRelativeLoc;       // FirstPersonMuzzleFlash relative Location
    00105	var() Rotator FPMFRelativeRot;      // FirstPersonMuzzleFlash relative Rotation
    00106	var Emitter WRE;                    // WaterRingsEmmiter, to setup the HitSoundType on the emitter.
    00107	// dual Weapon / Slave handling
    00108	var Weapon MySlave;                 // the actor being the slave if bHaveSlave.
    00109	var Weapon SlaveOf;                 // the actor being the master if bIsSlave.
    00110	var name NextSlaveState;            // Used to handle Salve unsynchronized behaviour
    00111
    00112	//_____________________________________________________________________________
    00113	// SFXs Info
    00114	var float ShakeMag;                 // used for shakes on Fire
    00115	var float ShakeTime;                // used for shakes on Fire/
    00116	var vector ShakeVert;               // used for shakes on Fire
    00117	var vector ShakeSpeed;              // used for shakes on Fire
    00118	var float ShakeCycles;              // used for shakes on Fire
    00119	var float AltShakeMag;              // used for shakes on AltFire
    00120	var float AltShakeTime;             // used for shakes on AltFire
    00121	var vector AltShakeVert;            // used for shakes on AltFire
    00122	var vector AltShakeSpeed;           // used for shakes on AltFire
    00123	var float AltShakeCycles;           // used for shakes on AltFire
    00124
    00125	//_____________________________________________________________________________
    00126	// AI information
    00127	var float AIRating;
    00128	var float TraceDist;                // how far instant hit trace fires go (Units = Meters sorry for the non-metric system guys)
    00129	var float AltTraceDist;             // how far instant hit trace Altfires go (Units = Meters sorry for the non-metric system guys)
    00130	var Rotator AdjustedAim;
    00131
    00132	//-----------------------------------------------------------------------------
    00133	// Sound Assignments
    00134	var() sound hFireSound;             // Playing on Fire
    00135	var() sound hReloadSound;           // Playing on Reload
    00136	var() sound hNoAmmoSound;           // Playing on EmptyFire
    00137	var() sound hSelectWeaponSound;     // Playing on SelectWeapon
    00138	var() sound hZoomSound;             // Playing on Zooming (params for zoom/unzoom/stop)
    00139	//var() sound hShellsSound;           // Playing on spawning shells
    00140	var() sound hAltFireSound;          // Playing on AltFire
    00141	var() sound hActWaitSound;          // Playing on Active Waiting
    00142
    00143	// messages
    00144	var() Localized string MessageNoAmmo;
    00145
    00146	//_____________________________________________________________________________
    00147	// first person Muzzle Flash
    00148	// weapon is responsible for setting and clearing bMuzzleFlash whenever it wants the
    00149	// MFTexture drawn on the canvas (see RenderOverlays() )
    00150	var float FlashTime;                    // time when muzzleflash will be cleared (set in RenderOverlays())
    00151	var(MuzzleFlash) float MuzzleScale;     // scaling of muzzleflash
    00152	var(MuzzleFlash) float FlashOffsetY;    // flash center offset from centered Y (as pct. of Canvas Y size)
    00153	var(MuzzleFlash) float FlashOffsetX;    // flash center offset from centered X (as pct. of Canvas X size)
    00154	var(MuzzleFlash) float FlashLength;     // How long muzzle flash should be displayed in seconds
    00155	var(MuzzleFlash) float MuzzleFlashSize; // size of (square) texture
    00156	var texture MFTexture;                  // first-person muzzle flash sprite
    00157	var byte FlashCount;                    // when incremented, draw muzzle flash for current frame (on-line used)
    00158	var byte AltFlashCount;                 // when incremented, draw alt muzzle flash for current frame (on-line used)
    00159	var byte ReloadClientCount;             // when incremented, reload for clients
    00160
    00161	var bool DBDual;
    00162	var bool DBWeap;
    00163	CONST BOREDSFXTHRESHOLD=10;
    00164
    00165	//_____________________________________________________________________________
    00166	// Network replication !! NATIVEREPLICATION !!
    00167	replication
    00168	{
    00169	    // Things the server should send to the client.
    00170	    reliable if( bNetOwner && bNetDirty && (Role==ROLE_Authority) )
    00171	      AmmoType, ReloadCount, bAllowShot, AltAmmoType, AltReloadCount;
    00172
    00173	    // Functions called by server on client
    00174	    reliable if( Role==ROLE_Authority )
    00175	      ClientWeaponSet, ClientForceReload, ClientReload;
    00176
    00177	    // functions called by client on server
    00178	    reliable if( Role<ROLE_Authority )
    00179	      ServerForceReload, ServerFire, ServerAltFire, ServerRapidFire, ServerStopFiring, ServerReload;
    00180	}
    00181
    00182	//_____________________________________________________________________________
    00183	Static function StaticParseDynamicLoading(LevelInfo MyLI)
    00184	{
    00185	    Log("Weapon StaticParseDynamicLoading class="$default.class);
    00186	    Super.StaticParseDynamicLoading(MyLI);
    00187	    if ( default.AmmoName != none )
    00188	    {
    00189	      MyLI.ForcedClasses[MyLI.ForcedClasses.Length] = default.AmmoName;
    00190	      (default.AmmoName).Static.StaticParseDynamicLoading(MyLI);
    00191	    }
    00192	    if ( default.AltAmmoName != none )
    00193	    {
    00194	      MyLI.ForcedClasses[MyLI.ForcedClasses.Length] = default.AltAmmoName;
    00195	      (default.AltAmmoName).Static.StaticParseDynamicLoading(MyLI);
    00196	    }
    00197	    MyLI.ForcedMeshes[MyLI.ForcedMeshes.Length] =
    00198	      Mesh(DynamicLoadObject(default.MeshName, class'mesh'));
    00199	}
    00200
    00201	//_____________________________________________________________________________
    00202	simulated event PostBeginPlay()
    00203	{
    00204	    // Convert TraceDist from meters to Unreal Engine Units
    00205	    TraceDist = TraceDist * 200.0 / 2.54;
    00206	    AltTraceDist = AltTraceDist * 200.0 / 2.54;
    00207	//    Log("PostBeginPlay for"@self@"TraceDist="$TraceDist@"altTraceDist="$AltTraceDist);
    00208	    Super.PostBeginPlay();
    00209	    // Optimize using dynamicload (the real dynamicload should have happened in the mutator at the map init)
    00210	    if ( (Mesh == none) && (MeshName != "") )
    00211	    {
    00212	      Mesh = Skeletalmesh(dynamicloadobject(MeshName, class'mesh')); // ParseDynMade
    00213	      default.mesh = mesh;
    00214	    }
    00215	    if ( (AttachmentClass != none) && (AttachmentClass.default.StaticMeshName != "") )
    00216	      DynamicLoadObject(AttachmentClass.default.StaticMeshName, class'StaticMesh'); // ParseDynLoad Made
    00217	    iAltZoomLevel = 0; // Initialize because default is used for max zoom level
    00218	    bRendered = false;
    00219	    bHidden = true;
    00220	    Refreshdisplaying();
    00221	    if ( MySlave != none )
    00222	    {
    00223	      MySlave.bRendered = false;
    00224	      MySlave.bHidden = true;
    00225
MySlave.RefreshDisplaying(); 00226 } 00227 } 00228 00229 //_____________________________________________________________________________ 00230 simulated event PostNetBeginPlay() 00231 { 00232 if ( Role == ROLE_Authority ) 00233 return; 00234 if ( (Instigator == None) || (Instigator.Controller == None) ) 00235 SetHand(0); 00236 else 00237 SetHand(Instigator.Controller.Handedness); 00238 } 00239 00240 //_____________________________________________________________________________ 00241 simulated function string GetAmmoText(out int bDrawbulletIcon); 00242 00243 //_____________________________________________________________________________ 00244 // Used to handle unsynchronized behaviour of slaves. 00245 // not simulated because should not be used in multiplayer 00246 event Timer2() 00247 { 00248 switch (NextSlaveState) 00249 { 00250 Case 'BringUp': 00251 bRendered = true; 00252 // bHidden = false; 00253 // RefreshDisplaying(); 00254 BringUp(); 00255 break; 00256 Case 'Fire': 00257 Fire(0.0); 00258 break; 00259 } 00260 } 00261 00262 //_____________________________________________________________________________ 00263 //Tell WeaponAttachment to cause client side weapon firing effects 00264 simulated function IncrementReloadClientCount() 00265 { 00266 ReloadClientCount++; 00267 if ( WeaponAttachment(ThirdPersonActor) != None ) 00268 { 00269 WeaponAttachment(ThirdPersonActor).ReloadClientCount = ReloadClientCount; 00270 WeaponAttachment(ThirdPersonActor).ThirdPersonReload(); 00271 } 00272 } 00273 00274 //_____________________________________________________________________________ 00275 //Tell WeaponAttachment to cause client side weapon firing effects 00276 // 473 µs 00277 simulated function IncrementFlashCount() 00278 { 00279 FlashCount++; 00280 if ( WeaponAttachment(ThirdPersonActor) != None ) 00281 { 00282 WeaponAttachment(ThirdPersonActor).FlashCount = FlashCount; 00283 WeaponAttachment(ThirdPersonActor).ThirdPersonEffects(); // 420 µs 00284 } 00285 RumbleFX(); 00286 } 00287 00288 //_____________________________________________________________________________ 00289 //Tell WeaponAttachment to cause client side weapon firing effects 00290 simulated function IncrementAltFlashCount() 00291 { 00292 AltFlashCount++; 00293 if ( WeaponAttachment(ThirdPersonActor) != None ) 00294 { 00295 WeaponAttachment(ThirdPersonActor).AltFlashCount = AltFlashCount; 00296 WeaponAttachment(ThirdPersonActor).ThirdPersonAltEffects(); 00297 } 00298 RumbleFX(); 00299 } 00300 00301 //_____________________________________________________________________________ 00302 simulated function SetupMuzzleFlash(); 00303 00304 //_____________________________________________________________________________ 00305 // Prototype 00306 simulated function RumbleFX(); 00307 00308 /* Force reloading even though clip isn't empty. Called by player controller exec function, 00309 and implemented in idle state */ 00310 simulated function ForceReload(); 00311 00312 function ServerForceReload() 00313 { 00314 bForceReload = true; 00315 } 00316 00317 function ClientForceReload() 00318 { 00319 bForceReload = true; 00320 } 00321 00322 //_____________________________________________________________________________ 00323 // list important controller attributes on canvas 00324 simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos) 00325 { 00326 local string T; 00327 local name Anim; 00328 local float frame,rate; 00329 00330 // Super.DisplayDebug(Canvas, YL, YPos); 00331 00332 Canvas.SetDrawColor(0,255,0); 00333 Canvas.DrawText("WEAPON "$GetItemName(string(self))); 00334 YPos += YL; 00335 Canvas.SetPos(4,YPos); 00336 Canvas.DrawText(" STATE: "$GetStateName()$" Timer: "$TimerCounter@"bChangeWeapon: "$bChangeWeapon, false); 00337 YPos += YL; 00338 Canvas.SetPos(4,YPos); 00339 00340 if ( Default.ReloadCount > 0 ) 00341 { 00342 Canvas.DrawText("Reload Count: "$ReloadCount); 00343 YPos += YL; 00344 Canvas.SetPos(4,YPos); 00345 } 00346 00347 if ( DrawType == DT_StaticMesh ) 00348 Canvas.DrawText(" StaticMesh "$StaticMesh$" AmbientSound "$AmbientSound, false); 00349 else 00350 Canvas.DrawText(" Mesh "$Mesh$" AmbientSound "$AmbientSound, false); 00351 YPos += YL; 00352 Canvas.SetPos(4,YPos); 00353 if ( Mesh != None ) 00354 { 00355 // mesh animation 00356 GetAnimParams(0,Anim,frame,rate); 00357 T = " AnimSequence "$Anim$" Frame "$frame$" Rate "$rate; 00358 if ( bAnimByOwner ) 00359 T= T$" Anim by Owner"; 00360 Canvas.DrawText(T, false); 00361 YPos += YL; 00362 Canvas.SetPos(4,YPos); 00363 } 00364 00365 if ( AmmoType == None ) 00366 { 00367 Canvas.DrawText("ERROR - NO AMMUNITION"); 00368 YPos += YL; 00369 Canvas.SetPos(4,YPos); 00370 } 00371 else 00372 AmmoType.DisplayDebug(Canvas,YL,YPos); 00373 } 00374 00375 //_____________________________________________________________________________ 00376 // Inventory travelling across servers. 00377 event TravelPostAccept() 00378 { 00379 if ( Pawn(Owner) == None ) 00380 if ( Pawn(Owner).IsPlayerPawn() ) 00381 { 00382 DebugLog(self@"TravelPostAccept"); 00383 } 00384 Super.TravelPostAccept(); 00385 return; 00386 if ( AmmoType == none ) 00387 GiveAmmo(Pawn(Owner)); 00388 if ( self == Pawn(Owner).Weapon ) 00389 BringUp(); 00390 else 00391 GotoState(''); 00392 if ( Pawn(Owner).IsPlayerPawn() ) 00393 { 00394 DebugLog(" after TravelPostAccept AmmoAmount="$AmmoType.AmmoAmount); 00395 } 00396 } 00397 00398 //_____________________________________________________________________________ 00399 simulated event Destroyed() 00400 { 00401 Super.Destroyed(); 00402 if( (Pawn(Owner)!=None) && (Pawn(Owner).Weapon == self) ) 00403 Pawn(Owner).Weapon = None; 00404 else if( (Instigator!=None) && (Instigator.Weapon == self) ) 00405 Pawn(Owner).Weapon = None; 00406 00407 if ( bTossedOut ) 00408 return; // to avoid destroying our 'inventory' in a loop that would have memorized it (thus breaking the destruction loop) 00409 00410 if ( AmmoType != none ) 00411 AmmoType.Destroy(); 00412 if ( AltAmmoType != none ) 00413 AltAmmoType.Destroy(); 00414 if ( Silencer != None ) 00415 Silencer.Destroy(); 00416 } 00417 00418 //_____________________________________________________________________________ 00419 function SetUpDual(Weapon Dual, Pawn other); 00420 00421 //_____________________________________________________________________________ 00422 function GiveTo(Pawn Other) 00423 { 00424 Local Weapon Dual; 00425 00426 if ( Other.IsPlayerPawn() ) 00427 { 00428 DebugLog("GIVETO (weapon)"@self@"to"@Other@"InventorySetUp ? "$Level.Game.bInventorySetUp); 00429 } 00430 00431 // convert class if needed 00432 if ( (PlayerTransferClass == none) && (PlayerTransferClassName != "") ) 00433 PlayerTransferClass = class<Inventory>(DynamicLoadObject(PlayerTransferClassName, class'class')); 00434 00435 if ( (PlayerTransferClass != none) && Other.IsHumanControlled() && !Other.Controller.bIsBot ) 00436 { 00437 Dual = Weapon(Spawn(PlayerTransferClass,,,Other.Location)); 00438 Dual.GiveTo(Other); 00439 Destroy(); 00440 return; 00441 } 00442 // convert class if needed 00443 if ( (NonPlayerTransferClass == none) && (NonPlayerTransferClassName != "") ) 00444 NonPlayerTransferClass = class<Inventory>(DynamicLoadObject(NonPlayerTransferClassName, class'class')); 00445 00446 if ( (NonPlayerTransferClass != none) && (!Other.IsHumanControlled() || Other.Controller.bIsBot) ) 00447 { 00448 Dual = Weapon(Spawn(NonPlayerTransferClass,,,Other.Location)); 00449 Dual.GiveTo(Other); 00450 Destroy(); 00451 return; 00452 } 00453 00454 Dual = Weapon(Other.FindInventoryType(class)); 00455 if ( Dual == none ) 00456 { // currently not owning weapon of this class, Std giveTo 00457 NewWeaponNotify(Other); 00458 Super.GiveTo(Other); 00459 bTossedOut = false; 00460 GiveAmmo(Other); // include GiveAltAmmo(Other); 00461 if ( Default.ReloadCount > 0 ) 00462 { 00463 if ( !Other.IsPlayerPawn() || !Level.bLonePlayer || Level.Game.bInventorySetUp || bMeleeWeapon ) 00464 { 00465 if ( Other.IsPlayerPawn() ) 00466 { 00467 DebugLog(" after GiveAmmo, Ammo Addin ReloadCount "$ReloadCount@"for"@self); 00468 } 00469 AmmoType.AddAmmo(ReloadCount); 00470 } 00471 else // don't add anything as we just received inventory from save/last map 00472 if ( Other.IsPlayerPawn() ) 00473 { 00474 DebugLog(" don't add ammo as we just travelled"); 00475 } 00476 } 00477 else 00478 { 00479 if ( !Other.IsPlayerPawn() || !Level.bLonePlayer || Level.Game.bInventorySetUp || bMeleeWeapon ) 00480 { 00481 if ( Other.IsPlayerPawn() ) 00482 { 00483 DebugLog(" after GiveAmmo, Ammo Addin PickUpAmmoCount "$PickUpAmmoCount@"for"@self); 00484 } 00485 AmmoType.AddAmmo(PickUpAmmoCount); 00486 } 00487 else if ( Other.IsPlayerPawn() )// don't add anything as we just received inventory from save/last map 00488 { 00489 DebugLog(" don't add ammo as we just travelled"); 00490 } 00491 } 00492 ClientWeaponSet(true); 00493 bRendered = false; 00494 bHidden = true; 00495 RefreshDisplaying(); 00496 } 00497 else if (Dual == self) 00498 { // can happen when loading a game w/ two weapons in inventory 00499 if ( Other.IsPlayerPawn() ) 00500 { 00501 DebugLog("END GIVETO (weapon) Cancel because Dual == self"); 00502 } 00503 return; 00504 } 00505 else if ( Dual.bCanHaveSlave && !Dual.bHaveSlave && (Other.CanHoldDualWeapons() || !Level.Game.bInventorySetUp ) ) 00506 { 00507 if ( Other.IsPlayerPawn() ) 00508 { 00509 DebugLog(" Setting Up Dual for"@Dual@"&"@self); 00510 } 00511 SetUpDual(Dual, Other); 00512 } 00513 else if ( Dual == SlaveOf ) 00514 { // can happen when loading a game w/ two weapons in inventory 00515 if ( Other.IsPlayerPawn() ) 00516 { 00517 DebugLog("END GIVETO (weapon) Cancel because Dual == SlaveOf"); 00518 } 00519 return; 00520 } 00521 else 00522 { 00523 if ( Other.IsPlayerPawn() ) 00524 { 00525 DebugLog(" Already Owned"@dual@".bCanHaveSlave="$Dual.bCanHaveSlave@"., Take ammo then Destroy"); 00526 } 00527 if ( ReloadCount != 0 ) 00528 Dual.AmmoType.AddAmmo(ReloadCount); 00529 else 00530 Dual.AmmoType.AddAmmo(PickupAmmoCount); 00531 Destroy(); 00532 } 00533 if ( Other.IsPlayerPawn() ) 00534 { 00535 DebugLog("END GIVETO (Weapon)"@self@"(Owner="$Owner$") Ammo="@AmmoType@"(Owner="$AmmoType.Owner$")"); 00536 } 00537 } 00538 00539 //_____________________________________________________________________________ 00540 function Transfer(Pawn Other) 00541 { 00542 Local Weapon Dual; 00543 00544 if ( Other.IsPlayerPawn() ) 00545 { 00546 DebugLog("TRANSFER (weapon)"@self@"to"@Other); 00547 } 00548 00549 // detach from old owner 00550 if ( Instigator != none ) 00551 { 00552 DetachFromPawn(Instigator); 00553 Instigator.DeleteInventory(self); 00554 } 00555 00556 // Don't care about transfering ammo before weapon because GiveAmmo will reinsert them after weapon 00557 if ( AmmoType != none ) 00558 { 00559 if ( (AmmoType.AmmoAmount > 0) && (AmmoType.PickupClass != none) && (class<Ammo>(AmmoType.PickupClass) != none) ) // last test to avoid double message for ammos that have weapon as pickup (knives, grenads) 00560 { 00561 Other.PlaySound(AmmoType.PickupClass.default.PickupSound); 00562 Other.ReceiveLocalizedMessage( AmmoType.PickupClass.default.MessageClass, 0, None, None, AmmoType.PickupClass ); 00563 } 00564 if ( Other.IsHumanControlled() ) 00565 { 00566 if ( default.ReloadCount != 0 ) 00567 AmmoType.AmmoAmount = 0; // for weapons w/ reload count, don't transfer more than reload count 00568 // when transfering cap the amount of ammo pickable 00569 else if ( (AmmoType.PickupClass != none) && (class<Ammo>(AmmoType.PickupClass) != none) ) 00570 AmmoType.AmmoAmount = class<Ammo>(AmmoType.PickupClass).default.AmmoAmount; 00571 else 00572 AmmoType.AmmoAmount = PickupAmmoCount; 00573 } 00574 00575 AmmoType.Transfer(Other); 00576 AmmoType = none; 00577 } 00578 if ( AltAmmoType != none ) 00579 { 00580 /* not done w/ alt ammo 00581 // when transfering cap the amount of ammo pickable 00582 if ( AltAmmoType.PickupClass != none ) 00583 AltAmmoType.AmmoAmount = class<Ammo>(AltAmmoType.PickupClass).default.AmmoAmount; 00584 else 00585 AltAmmoType.AmmoAmount = AltPickupAmmoCount; 00586 */ 00587 if ( (AltAmmoType.AmmoAmount > 0) && (AltAmmoType.PickupClass != none) && (class<Ammo>(AltAmmoType.PickupClass) != none) ) // last test to avoid double message for ammos that have weapon as pickup (knives, grenads) 00588 { 00589 Other.PlaySound(AltAmmoType.PickupClass.default.PickupSound); 00590 Other.ReceiveLocalizedMessage( AltAmmoType.PickupClass.default.MessageClass, 0, None, None, AltAmmoType.PickupClass ); 00591 } 00592 AltAmmoType.Transfer(Other); 00593 AltAmmoType = none; 00594 } 00595 00596 // convert class if needed 00597 if ( (PlayerTransferClass == none) && (PlayerTransferClassName != "") ) 00598 PlayerTransferClass = class<Inventory>(DynamicLoadObject(PlayerTransferClassName, class'class')); 00599 00600 if ( (PlayerTransferClass != none) && Other.IsHumanControlled() ) 00601 { 00602 Dual = Weapon(Spawn(PlayerTransferClass,,,Other.Location)); 00603 if ( Default.ReloadCount != 0 ) 00604 Dual.ReloadCount = ReloadCount; 00605 Dual.Transfer(Other); 00606 Destroy(); 00607 return; 00608 } 00609 // convert class if needed 00610 if ( (NonPlayerTransferClass == none) && (NonPlayerTransferClassName != "") ) 00611 NonPlayerTransferClass = class<Inventory>(DynamicLoadObject(NonPlayerTransferClassName, class'class')); 00612 00613 if ( (NonPlayerTransferClass != none) && !Other.IsHumanControlled() ) 00614 { 00615 Dual = Weapon(Spawn(NonPlayerTransferClass,,,Other.Location)); 00616 if ( Default.ReloadCount != 0 ) 00617 Dual.ReloadCount = ReloadCount; 00618 Dual.Transfer(Other); 00619 Destroy(); 00620 return; 00621 } 00622 00623 Dual = Weapon(Other.FindInventoryType(class)); 00624 if ( Dual == none ) 00625 { // currently not owning weapon of this class 00626 NewWeaponNotify(Other); 00627 Other.PlaySound(PickupClass.default.PickupSound); 00628 Other.ReceiveLocalizedMessage( PickupClass.default.MessageClass, 0, None, None, PickupClass ); 00629 // GiveTo(Other); 00630 Super.GiveTo(Other); 00631 bTossedOut = false; 00632 GiveAmmo(Other); // include GiveAltAmmo(Other); 00633 ClientWeaponSet(true); 00634 bRendered = false; 00635 bHidden = true; 00636 RefreshDisplaying(); 00637 if ( Other.IsPlayerPawn() ) 00638 { 00639 DebugLog(" (weapon)"@self@"to"@Other@"GiveTo because not owned, AmmoAmount="$AmmoType.AmmoAmount); 00640 } 00641 if ( default.ReLoadCount != 0 ) 00642 AmmoType.AddAmmo(ReLoadCount); 00643 } 00644 else if ( Dual.bCanHaveSlave && !Dual.bHaveSlave && Other.CanHoldDualWeapons() ) 00645 { 00646 if ( Other.IsPlayerPawn() ) 00647 { 00648 DebugLog(" (weapon)"@self@"to"@Other@"GiveTo because Dual allowed"); 00649 } 00650 Other.PlaySound(PickupClass.default.PickupSound); 00651 Other.ReceiveLocalizedMessage( PickupClass.default.MessageClass, 0, None, None, PickupClass ); 00652 SetUpDual(Dual, Other); 00653 } 00654 else 00655 { 00656 if ( Other.IsPlayerPawn() ) 00657 { 00658 DebugLog(" (weapon)"@self@"to"@Other@" Add ReloadCount then Destroy because owned"); 00659 } 00660 if ( Default.ReloadCount > 0 ) 00661 Dual.AmmoType.AddAmmo(ReloadCount); 00662 if ( Default.AltReloadCount > 0 ) 00663 Dual.AmmoType.AddAmmo(ReloadCount); 00664 if ( class<Ammo>(Dual.AmmoType.PickupClass) == none ) 00665 { // Send message because picking weapon w/out ammo pickup 00666 Other.PlaySound(PickupClass.default.PickupSound); 00667 Other.ReceiveLocalizedMessage( PickupClass.default.MessageClass, 0, None, None, PickupClass ); 00668 } 00669 // else // else do nothing as ammo should have been transfered w/ the ammotype 00670 // Dual.AmmoType.AddAmmo(PickupAmmoCount); 00671 Destroy(); 00672 } 00673 } 00674 00675 //_____________________________________________________________________________ 00676 function NewWeaponNotify(Pawn Other); 00677 00678 /* 00679 //_____________________________________________________________________________ 00680 // Weapon rendering 00681 // Draw first person view of inventory 00682 simulated event RenderOverlays( canvas Canvas ) 00683 { 00684 local rotator NewRot; 00685 local bool bPlayerOwner; 00686 local int Hand; 00687 local PlayerController PlayerOwner; 00688 local float ScaledFlash; 00689 00690 if ( Instigator == None ) 00691 return; 00692 00693 PlayerOwner = PlayerController(Instigator.Controller); 00694 00695 if ( PlayerOwner != None ) 00696 { 00697 bPlayerOwner = true; 00698 Hand = PlayerOwner.Handedness; 00699 if ( Hand == 2 ) 00700 return; 00701 } 00702 00703 if ( bMuzzleFlash && bDrawMuzzleFlash && (MFTexture != None) ) 00704 { 00705 if ( !bSetFlashTime ) 00706 { 00707 bSetFlashTime = true; 00708 FlashTime = Level.TimeSeconds + FlashLength; 00709 } 00710 else if ( FlashTime < Level.TimeSeconds ) 00711 bMuzzleFlash = false; 00712 if ( bMuzzleFlash ) 00713 { 00714 ScaledFlash = 0.5 * MuzzleFlashSize * MuzzleScale * Canvas.ClipX/640.0; 00715 Canvas.SetPos(0.5*Canvas.ClipX - ScaledFlash + Canvas.ClipX * Hand * FlashOffsetX, 0.5*Canvas.ClipY - ScaledFlash + Canvas.ClipY * FlashOffsetY); 00716 // DrawMuzzleFlash(Canvas); 00717 } 00718 } 00719 else 00720 bSetFlashTime = false; 00721 00722 SetLocation( Instigator.Location + Instigator.CalcDrawOffset(self) ); 00723 NewRot = Instigator.GetViewRotation(); 00724 00725 if ( Hand == 0 ) 00726 newRot.Roll = 2 * Default.Rotation.Roll; 00727 else 00728 newRot.Roll = Default.Rotation.Roll * Hand; 00729 00730 setRotation(newRot); 00731 Canvas.DrawActor(self, false, false); 00732 } 00733 */ 00734 00735 //_____________________________________________________________________________ 00736 // If this is called then just setup pos & render because primary weapon is already rendered 00737 simulated function RenderSlaveOverlays( canvas Canvas ); 00738 00739 //_____________________________________________________________________________ 00740 simulated function bool ShouldDrawCrosshair(optional Canvas C) 00741 { 00742 return ( !bZoomed && (Pawn(Owner).IsPlayerPawn() && !PlayerController(Pawn(Owner).Controller).bZooming) ); 00743 } 00744 00745 //_____________________________________________________________________________ 00746 //return percent of full ammo (0 to 1 range) 00747 function float AmmoStatus() 00748 { 00749 return float(AmmoType.AmmoAmount)/AmmoType.MaxAmmo; 00750 } 00751 00752 //_____________________________________________________________________________ 00753 native function bool HasAmmo(); 00754 /* 00755 simulated function bool HasAmmo() 00756 { 00757 // should be useless 00758 if ( AmmoType == none ) 00759 AmmoType = Ammunition(Pawn(Owner).FindInventoryType(AmmoName)); 00760 00761 if ( MySlave != none ) 00762 return ( (AmmoType.AmmoAmount - MySlave.ReloadCount) > 0); 00763 else if ( SlaveOf != none ) 00764 return ( (AmmoType.AmmoAmount - SlaveOf.ReloadCount) > 0); 00765 else 00766 return AmmoType.HasAmmo(); 00767 } 00768 */ 00769 00770 //_____________________________________________________________________________ 00771 simulated function bool HasAltAmmo() 00772 { 00773 if ( AltAmmoType == none ) 00774 return false; 00775 return AltAmmoType.HasAmmo(); 00776 } 00777 00778 //_____________________________________________________________________________ 00779 simulated function bool HasSilencer(); 00780 00781 //_____________________________________________________________________________ 00782 // sets appropriate weapon configuration, and returns rating based on that configuration 00783 function float RateSelf() 00784 { 00785 if ( !HasAmmo() ) 00786 return -2; 00787 return (AIRating + FRand() * 0.05); 00788 } 00789 00790 //_____________________________________________________________________________ 00791 // If picking up another weapon of the same class, add its ammo. 00792 // If ammo count was at zero, check if should auto-switch to this weapon. 00793 function bool HandlePickupQuery( Pickup Item ) 00794 { 00795 local int OldAmmo, NewAmmo; 00796 local Pawn P; 00797 00798 // if ( DBDual ) 00799 if ( Pawn(Owner).IsPlayerPawn() ) 00800 { 00801 DebugLog(">> HandlePickupQuery for "$self); 00802 } 00803 if (Item.InventoryType == Class) 00804 { 00805 if ( Level.bLonePlayer && bCanHaveSlave && !bHaveSlave ) 00806 { 00807 if ( DBDual ) Log(" > we are accepting picking up a weapon to be used for dual wielding"); 00808 return false; 00809 } 00810 } 00811 if (Item.InventoryType == Class) 00812 { 00813 if ( (WeaponPickup(item) != none) && WeaponPickup(item).bWeaponStay && ((item.inventory == None) || item.inventory.bTossedOut) ) 00814 return true; 00815 P = Pawn(Owner); 00816 if ( AmmoType != None ) 00817 { 00818 OldAmmo = AmmoType.AmmoAmount; 00819 if ( Item.Inventory != None ) 00820 NewAmmo = Weapon(Item.Inventory).PickupAmmoCount; 00821 else 00822 NewAmmo = class<Weapon>(Item.InventoryType).Default.PickupAmmoCount; 00823 if ( AmmoType.AddAmmo(NewAmmo) && (OldAmmo == 0) 00824 && (P.Weapon.class != item.InventoryType) ) 00825 ClientWeaponSet(true); 00826 } 00827 Item.AnnouncePickup(Pawn(Owner)); 00828 return true; 00829 } 00830 if ( Inventory == None ) 00831 return false; 00832 return Inventory.HandlePickupQuery(Item); 00833 } 00834 00835 //_____________________________________________________________________________ 00836 // set which hand is holding weapon 00837 simulated function SetHand(float Hand) 00838 { 00839 Hand = 1; 00840 /* 00841 if ( Hand == 2 ) 00842 { 00843 PlayerViewOffset.Y = 0; 00844 FireOffset.Y = 0; 00845 return; 00846 } 00847 00848 Mesh = Default.Mesh; 00849 if ( Hand == 0 ) 00850 { 00851 PlayerViewOffset.X = Default.PlayerViewOffset.X * 0.88; 00852 PlayerViewOffset.Y = -0.2 * Default.PlayerViewOffset.Y; 00853 PlayerViewOffset.Z = Default.PlayerViewOffset.Z * 1.12; 00854 } 00855 else 00856 { 00857 PlayerViewOffset.X = Default.PlayerViewOffset.X; 00858 PlayerViewOffset.Y = Default.PlayerViewOffset.Y * Hand; 00859 PlayerViewOffset.Z = Default.PlayerViewOffset.Z; 00860 } 00861 FireOffset.Y = Default.FireOffset.Y * Hand; 00862 */ 00863 } 00864 00865 //_____________________________________________________________________________ 00866 // Change weapon to that specificed by F matching inventory weapon's Inventory Group. 00867 simulated function Weapon WeaponChange( byte F ) 00868 { 00869 local Weapon newWeapon; 00870 00871 if ( InventoryGroup == F ) 00872 { 00873 if ( !HasAmmo() ) 00874 { 00875 if ( Inventory == None ) 00876 newWeapon = None; 00877 else 00878 newWeapon = Inventory.WeaponChange(F); 00879 return newWeapon; 00880 } 00881 else 00882 return self; 00883 } 00884 else if ( Inventory == None ) 00885 return None; 00886 else 00887 return Inventory.WeaponChange(F); 00888 } 00889 00890 //_____________________________________________________________________________ 00891 // ELR New function from WeaponChange to avoid potential bugs (this is to be used for SelectWeapon bind) 00892 simulated function Weapon WeaponSelect( byte F ) 00893 { 00894 local Weapon newWeapon; 00895 00896 if ( InventoryGroup == F ) 00897 { 00898 if (!( (HasAmmo() || (bHaveAltFire && HasAltAmmo()) || (bHaveSlave && (MySlave.ReloadCount > 0))) 00899 && !bIsSlave && !(Pawn(Owner).bHaveOnlyOneHandFree && (WHand == WHA_2HShot)) )) 00900 { 00901 if ( Inventory == None ) 00902 newWeapon = None; 00903 else 00904 newWeapon = Inventory.WeaponSelect(F); 00905 return newWeapon; 00906 } 00907 else 00908 return self; 00909 } 00910 else if ( Inventory == None ) 00911 return None; 00912 else 00913 return Inventory.WeaponSelect(F); 00914 } 00915 00916 //_____________________________________________________________________________ 00917 // Find the previous weapon (using the Inventory group) 00918 simulated function Weapon PrevWeapon(Weapon CurrentChoice, Weapon CurrentWeapon) 00919 { 00920 // if ( AmmoType.HasAmmo() ) 00921 if ( (HasAmmo() || (bHaveAltFire && HasAltAmmo()) || (bHaveSlave && (MySlave.ReloadCount > 0))) 00922 && !bIsSlave && !(Pawn(Owner).bHaveOnlyOneHandFree && (WHand == WHA_2HShot)) ) 00923 { 00924 if ( (CurrentChoice == None) ) 00925 { 00926 if ( CurrentWeapon != self ) 00927 CurrentChoice = self; 00928 } 00929 else if ( InventoryGroup == CurrentChoice.InventoryGroup ) 00930 { 00931 if ( InventoryGroup == CurrentWeapon.InventoryGroup ) 00932 { 00933 if ( (GroupOffset < CurrentWeapon.GroupOffset) 00934 && (GroupOffset > CurrentChoice.GroupOffset) ) 00935 CurrentChoice = self; 00936 } 00937 else if ( GroupOffset > CurrentChoice.GroupOffset ) 00938 CurrentChoice = self; 00939 } 00940 else if ( InventoryGroup > CurrentChoice.InventoryGroup ) 00941 { 00942 if ( (InventoryGroup < CurrentWeapon.InventoryGroup) 00943 || (CurrentChoice.InventoryGroup > CurrentWeapon.InventoryGroup) ) 00944 CurrentChoice = self; 00945 } 00946 else if ( (CurrentChoice.InventoryGroup > CurrentWeapon.InventoryGroup) 00947 && (InventoryGroup < CurrentWeapon.InventoryGroup) ) 00948 CurrentChoice = self; 00949 } 00950 if ( Inventory == None ) 00951 return CurrentChoice; 00952 else 00953 return Inventory.PrevWeapon(CurrentChoice,CurrentWeapon); 00954 } 00955 00956 //_____________________________________________________________________________ 00957 simulated function Weapon NextWeapon(Weapon CurrentChoice, Weapon CurrentWeapon) 00958 { 00959 // if ( AmmoType.HasAmmo() ) 00960 if ( (HasAmmo() || (bHaveAltFire && HasAltAmmo()) || (bHaveSlave && (MySlave.ReloadCount > 0)) ) 00961 && !bIsSlave && !(Pawn(Owner).bHaveOnlyOneHandFree && (WHand == WHA_2HShot)) ) 00962 { 00963 if ( (CurrentChoice == None) ) 00964 { 00965 if ( CurrentWeapon != self ) 00966 CurrentChoice = self; 00967 } 00968 else if ( InventoryGroup == CurrentChoice.InventoryGroup ) 00969 { 00970 if ( InventoryGroup == CurrentWeapon.InventoryGroup ) 00971 { 00972 if ( (GroupOffset > CurrentWeapon.GroupOffset) 00973 && (GroupOffset < CurrentChoice.GroupOffset) ) 00974 CurrentChoice = self; 00975 } 00976 else if ( GroupOffset < CurrentChoice.GroupOffset ) 00977 CurrentChoice = self; 00978 } 00979 else if ( InventoryGroup < CurrentChoice.InventoryGroup ) 00980 { 00981 if ( (InventoryGroup > CurrentWeapon.InventoryGroup) 00982 || (CurrentChoice.InventoryGroup < CurrentWeapon.InventoryGroup) ) 00983 CurrentChoice = self; 00984 } 00985 else if ( (CurrentChoice.InventoryGroup < CurrentWeapon.InventoryGroup) 00986 && (InventoryGroup > CurrentWeapon.InventoryGroup) ) 00987 CurrentChoice = self; 00988 } 00989 if ( Inventory == None ) 00990 return CurrentChoice; 00991 else 00992 return Inventory.NextWeapon(CurrentChoice,CurrentWeapon); 00993 } 00994 00995 simulated function AnimEnd(int Channel) 00996 { 00997 if ( Level.NetMode == NM_Client ) 00998 PlayIdleAnim(); 00999 } 01000 01001 //_____________________________________________________________________________ 01002 function GiveAmmo( Pawn Other ) 01003 { 01004 if ( AmmoName == None ) 01005 return; 01006 01007 if ( Default.ReloadCount != 0 ) 01008 ReLoadCount = min(ReLoadCount, PickUpAmmoCount); 01009 else 01010 ReLoadCount = PickUpAmmoCount; 01011 01012 AmmoType = Ammunition(Other.FindInventoryType(AmmoName)); 01013 if ( AmmoType == none ) 01014 { 01015 if ( Other.IsPlayerPawn() ) 01016 { 01017 DebugLog("GiveAmmo to"@other@", Ammo NOT Already owned, reseting to AmmoAmount = 0"); 01018 } 01019 AmmoType = Spawn(AmmoName); // Create ammo type required 01020 Other.AddInventory(AmmoType); // and add to player's inventory 01021 AmmoType.AmmoAmount = 0; 01022 } 01023 else 01024 { // AmmoType must be after self in inventory, can happen when grabing some ammo before weapon 01025 if ( Other.IsPlayerPawn() ) 01026 { 01027 DebugLog("GiveAmmo to"@other@", Ammo Already owned, not adding any ammo"); 01028 } 01029 01030 if ( Level.NetMode == NM_StandAlone ) 01031 Other.InsertInventory(AmmoType, self); 01032 /* 01033 if ( Default.ReloadCount > 0 ) 01034 { 01035 Log("GiveAmmo to"@other@", Ammo Already owned, Addin ReloadCount "$ReloadCount); 01036 AmmoType.AddAmmo(ReloadCount); 01037 } 01038 else 01039 { 01040 Log("GiveAmmo to"@other@", Ammo Already owned, Addin PickUpAmmoCount "$PickUpAmmoCount); 01041 AmmoType.AddAmmo(PickUpAmmoCount); 01042 } 01043 */ 01044 } 01045 if ( bHaveAltFire ) 01046 GiveAltAmmo(other); 01047 } 01048 01049 //_____________________________________________________________________________ 01050 // ELR ADD Possibility that PickUpAmmoCount < ReLoadCount (else Bug) 01051 simulated function GiveAltAmmo( Pawn Other ) 01052 { 01053 if ( AltAmmoName == None ) 01054 return; 01055 AltAmmoType = Ammunition(Other.FindInventoryType(AltAmmoName)); 01056 if ( AltAmmoType == none ) 01057 { 01058 AltAmmoType = Spawn(AltAmmoName); // Create ammo type required 01059 Other.AddInventory(AltAmmoType); // and add to player's inventory 01060 AltAmmoType.AmmoAmount = AltPickUpAmmoCount; 01061 if ( default.AltReloadCount != 0 ) 01062 AltReLoadCount = min(AltReLoadCount, AltPickUpAmmoCount); 01063 else 01064 AltReLoadCount = AltPickUpAmmoCount; 01065 } 01066 else 01067 { // AmmoType must be after self in inventory, can happen when grabing some ammo before weapon 01068 if ( Level.NetMode == NM_StandAlone ) 01069 Other.InsertInventory(AltAmmoType, self); 01070 AltAmmoType.AddAmmo(AltPickUpAmmoCount); 01071 } 01072 } 01073 01074 // Return the switch priority of the weapon (normally AutoSwitchPriority, but may be 01075 // modified by environment (or by other factors for bots) 01076 simulated function float SwitchPriority() 01077 { 01078 local float temp; 01079 01080 if ( !Instigator.IsHumanControlled() ) 01081 return RateSelf(); 01082 else if ( !AmmoType.HasAmmo() ) 01083 { 01084 if ( Pawn(Owner).Weapon == self ) 01085 return -0.5; 01086 else 01087 return -1; 01088 } 01089 else 01090 return 1; 01091 } 01092 01093 //_____________________________________________________________________________ 01094 // Compare self to current weapon. If better than current weapon, then switch 01095 simulated function ClientWeaponSet(bool bOptionalSet) 01096 { 01097 local weapon W; 01098 01099 Instigator = Pawn(Owner); //weapon's instigator isn't replicated to client 01100 if ( Instigator == None ) 01101 { 01102 GotoState('PendingClientWeaponSet'); 01103 return; 01104 } 01105 else if ( IsInState('PendingClientWeaponSet') ) 01106 GotoState(''); 01107 if ( Instigator.Weapon == self ) 01108 return; 01109 01110 if ( Instigator.Weapon == None ) 01111 { 01112 Instigator.PendingWeapon = self; 01113 Instigator.ChangedWeapon(); 01114 return; 01115 } 01116 01117 if ( bOptionalSet && Instigator.IsHumanControlled() ) 01118 return; 01119 /* ELR XIIIUNUSED no auto switch 01120 if ( Instigator.Weapon.SwitchPriority() < SwitchPriority() ) 01121 { 01122 W = Instigator.PendingWeapon; 01123 Instigator.PendingWeapon = self; 01124 GotoState(''); 01125 01126 if ( !Instigator.Weapon.PutDown() ) 01127 Instigator.PendingWeapon = W; 01128 return; 01129 } 01130 */ 01131 GotoState(''); 01132 } 01133 01134 simulated function Weapon RecommendWeapon( out float rating ) 01135 { 01136 local Weapon Recommended; 01137 local float oldRating, oldFiring; 01138 local int oldMode; 01139 01140 if (Instigator.bisdead || Instigator.Controller.bIsBot || Instigator.Controller.Enemy == None) //fouille sur cadavre, bot ou basesoldier sans enemmi 01141 { 01142 if( HasAmmo() ) 01143 rating = AIRating; 01144 else 01145 rating=-1; 01146 } 01147 else if ( Instigator.IsHumanControlled() ) //XIII 01148 rating = SwitchPriority(); 01149 else //basesoldier avec ennemi 01150 { 01151 rating = RateSelf(); 01152 if (self == Instigator.Weapon && AmmoType.HasAmmo()) 01153 rating += 0.05; // tend to stick with same weapon 01154 //rating += Instigator.Controller.WeaponPreference(self); 01155 } 01156 if ( inventory != None ) 01157 { 01158 Recommended = inventory.RecommendWeapon(oldRating); 01159 if ( (Recommended != None) && (oldRating > rating) ) 01160 { 01161 rating = oldRating; 01162 return Recommended; 01163 } 01164 } 01165 return self; 01166 } 01167 01168 //_____________________________________________________________________________ 01169 // Toss this weapon out 01170 function DropFrom(vector StartLocation) 01171 { 01172 AIRating = Default.AIRating; 01173 bMuzzleFlash = false; 01174 if ( AmmoType != None ) 01175 { 01176 PickupAmmoCount = AmmoType.AmmoAmount; 01177 AmmoType.AmmoAmount = 0; 01178 } 01179 else if ( default.ReloadCount != 0 ) 01180 { 01181 PickupAmmoCount = reloadCount; 01182 } 01183 GotoState(''); 01184 Super.DropFrom(StartLocation); 01185 } 01186 01187 //_____________________________________________________________________________ 01188 simulated function BringUp() 01189 { 01190 if ( DBWeap ) 01191 Log(self@"BringUp"); 01192 if ( Instigator.IsHumanControlled() ) 01193 { 01194 if( ! Instigator.Controller.bIsBot ) 01195 { 01196 SetHand(PlayerController(Instigator.Controller).Handedness); 01197 PlayerController(Instigator.Controller).EndZoom(); 01198 } 01199 } 01200 PlaySelect(); 01201 bRendered = true; 01202 // bHidden = false; 01203 // RefreshDisplaying(); 01204 GotoState('Active'); 01205 if ( (MySlave != none) && bEnableSlave ) 01206 MySlave.SlaveBringUp(); 01207 } 01208 01209 //_____________________________________________________________________________ 01210 simulated function BringUpNoSlave() 01211 { 01212 // Log("BringUp Call for"@self); 01213 01214 if ( Instigator.IsHumanControlled() ) 01215 { 01216 SetHand(PlayerController(Instigator.Controller).Handedness); 01217 PlayerController(Instigator.Controller).EndZoom(); 01218 } 01219 PlaySelect(); 01220 GotoState('Active'); 01221 } 01222 01223 //_____________________________________________________________________________ 01224 simulated function SlaveBringUp() 01225 { 01226 NextSlaveState = 'BringUp'; 01227 SetTimer2(0.2 + fRand()*0.2, false); 01228 } 01229 01230 //_____________________________________________________________________________ 01231 // Need this to force the server to reload. 01232 function ServerReLoad() 01233 { 01234 // Log(" ServerReLoad called"); 01235 GotoState('ReLoading'); 01236 } 01237 01238 //_____________________________________________________________________________ 01239 // Need this to force the server to reload. 01240 function ClientReLoad() 01241 { 01242 // Log(" ClientReLoad called"); 01243 GotoState('ReLoading'); 01244 } 01245 01246 //************************************************************************************** 01247 // 01248 // Firing functions and states 01249 // 01250 simulated function bool RepeatFire() 01251 { 01252 return bRapidFire; 01253 } 01254 01255 function ServerStopFiring() 01256 { 01257 StopFiringTime = Level.TimeSeconds; 01258 } 01259 01260 function ServerRapidFire() 01261 { 01262 ServerFire(); 01263 if ( IsInState('NormalFire') ) 01264 StopFiringTime = Level.TimeSeconds + 0.6; 01265 } 01266 01267 function ServerFire() 01268 { 01269 if ( AmmoType == None ) 01270 { 01271 // ammocheck 01272 log("WARNING "$self$" HAS NO AMMO!!!"); 01273 GiveAmmo(Pawn(Owner)); 01274 } 01275 if ( AmmoType.HasAmmo() ) 01276 { 01277 GotoState('NormalFire'); 01278 if ( default.ReloadCount > 0 ) 01279 ReloadCount--; 01280 LocalFire(); 01281 if ( AmmoType.bInstantHit ) 01282 TraceFire(TraceAccuracy,0,0); 01283 else 01284 ProjectileFire(); 01285 } 01286 } 01287 01288 simulated function Fire( float Value ) 01289 { 01290 if ( !AmmoType.HasAmmo() ) 01291 return; 01292 01293 if ( !RepeatFire() ) 01294 ServerFire(); 01295 else if ( StopFiringTime < Level.TimeSeconds + 0.3 ) 01296 { 01297 StopFiringTime = Level.TimeSeconds + 0.6; 01298 ServerRapidFire(); 01299 } 01300 if ( Role < ROLE_Authority ) 01301 { 01302 if ( default.ReloadCount > 0 ) 01303 ReloadCount--; 01304 LocalFire(); 01305 GotoState('ClientFiring'); 01306 } 01307 } 01308 01309 //_____________________________________________________________________________ 01310 simulated function SlaveFire() 01311 { 01312 NextSlaveState = 'Fire'; 01313 SetTimer2(0.1+fRand()*0.10, false); 01314 } 01315 01316 simulated function LocalFire() 01317 { 01318 local PlayerController P; 01319 01320 // bPointing = true; 01321 01322 if ( (Instigator != None) && Instigator.IsLocallyControlled() ) 01323 { 01324 P = PlayerController(Instigator.Controller); 01325 if (P!=None) 01326 { 01327 // if ( InstFlash != 0.0 ) 01328 // P.ClientInstantFlash( InstFlash, InstFog); 01329 01330 P.ShakeView(ShakeTime, ShakeMag, ShakeVert, 120000, ShakeSpeed, 1); 01331 } 01332 } 01333 // if ( Affector != None ) 01334 // Affector.FireEffect(); 01335 PlayFiring(); 01336 } 01337 01338 function ServerAltFire() 01339 { 01340 if ( !IsInState('Idle') ) 01341 GotoState('Idle'); 01342 } 01343 01344 /* AltFire() 01345 Weapon mode change. 01346 */ 01347 simulated function AltFire( float Value ) 01348 { 01349 if ( !IsInState('Idle') ) 01350 GotoState('Idle'); 01351 ServerAltFire(); 01352 } 01353 01354 /* 01355 simulated function vector GetFireStart(vector X, vector Y, vector Z) 01356 { 01357 return (Instigator.Location + Instigator.EyePosition() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z); 01358 } 01359 */ 01360 native function vector GetFireStart(vector X, vector Y, vector Z); 01361 /* 01362 //_____________________________________________________________________________ 01363 simulated function vector GetFireStart(vector X, vector Y, vector Z) 01364 { 01365 if ( bZoomed ) 01366 return (Instigator.Location + Instigator.EyePosition() + FireOffset.X * X); 01367 else 01368 return (Instigator.Location + Instigator.EyePosition() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z); 01369 } 01370 */ 01371 01372 function ProjectileFire() 01373 { 01374 local Vector Start, X,Y,Z; 01375 01376 Owner.MakeNoise(1.0); 01377 GetAxes(Instigator.GetViewRotation(),X,Y,Z); 01378 Start = GetFireStart(X,Y,Z); 01379 AdjustedAim = Instigator.AdjustAim(AmmoType, Start, 0); 01380 AmmoType.SpawnProjectile(Start,AdjustedAim); 01381 } 01382 01383 function TraceFire( float Accuracy, float YOffset, float ZOffset ) 01384 { 01385 local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z; 01386 local actor Other; 01387 01388 Owner.MakeNoise(1.0); 01389 GetAxes(Instigator.GetViewRotation(),X,Y,Z); 01390 StartTrace = GetFireStart(X,Y,Z); 01391 AdjustedAim = Instigator.AdjustAim(AmmoType, StartTrace, 0); 01392 EndTrace = StartTrace + (YOffset + Accuracy * (FRand() - 0.5 ) ) * Y * 1000 01393 + (ZOffset + Accuracy * (FRand() - 0.5 )) * Z * 1000; 01394 X = vector(AdjustedAim); 01395 EndTrace += (TraceDist * X); 01396 Other = Trace(HitLocation,HitNormal,EndTrace,StartTrace,True); 01397 AmmoType.ProcessTraceHit(self, Other, HitLocation, HitNormal, X,Y,Z); 01398 } 01399 01400 simulated function bool NeedsToReload() 01401 { 01402 return ( bForceReload || (Default.ReloadCount > 0) && (ReloadCount == 0) ); 01403 } 01404 01405 // Finish a sequence 01406 function Finish() 01407 { 01408 local bool bForce, bForceAlt; 01409 01410 if ( NeedsToReload() && AmmoType.HasAmmo() ) 01411 { 01412 GotoState('Reloading'); 01413 return; 01414 } 01415 01416 bForce = bForceFire; 01417 bForceAlt = bForceAltFire; 01418 bForceFire = false; 01419 bForceAltFire = false; 01420 01421 if ( bChangeWeapon ) 01422 { 01423 GotoState('DownWeapon'); 01424 return; 01425 } 01426 01427 if ( (Instigator == None) || (Instigator.Controller == None) ) 01428 { 01429 GotoState(''); 01430 return; 01431 } 01432 01433 if ( !Instigator.IsHumanControlled() ) 01434 { 01435 if ( !AmmoType.HasAmmo() ) 01436 { 01437 Instigator.Controller.SwitchToBestWeapon(); 01438 if ( bChangeWeapon ) 01439 GotoState('DownWeapon'); 01440 else 01441 GotoState('Idle'); 01442 } 01443 if ( Instigator.PressingFire() ) 01444 Global.ServerFire(); 01445 else if ( Instigator.PressingAltFire() ) 01446 CauseAltFire(); 01447 else 01448 { 01449 Instigator.Controller.StopFiring(); 01450 GotoState('Idle'); 01451 } 01452 return; 01453 } 01454 if ( !AmmoType.HasAmmo() && Instigator.IsLocallyControlled() ) 01455 { 01456 // if local player, switch weapon 01457 Instigator.Controller.SwitchToBestWeapon(); 01458 if ( bChangeWeapon ) 01459 { 01460 GotoState('DownWeapon'); 01461 return; 01462 } 01463 else 01464 GotoState('Idle'); 01465 } 01466 if ( Instigator.Weapon != self ) 01467 GotoState('Idle'); 01468 else if ( (StopFiringTime > Level.TimeSeconds) || bForce || Instigator.PressingFire() ) 01469 Global.ServerFire(); 01470 else if ( bForceAlt || Instigator.PressingAltFire() ) 01471 CauseAltFire(); 01472 else 01473 GotoState('Idle'); 01474 } 01475 01476 function CauseAltFire() 01477 { 01478 Global.ServerAltFire(); 01479 } 01480 01481 simulated function ClientFinish() 01482 { 01483 if ( (Instigator == None) || (Instigator.Controller == None) ) 01484 { 01485 GotoState(''); 01486 return; 01487 } 01488 if ( NeedsToReload() && AmmoType.HasAmmo() ) 01489 { 01490 GotoState('Reloading'); 01491 return; 01492 } 01493 if ( !AmmoType.HasAmmo() ) 01494 { 01495 Instigator.Controller.SwitchToBestWeapon(); 01496 if ( !bChangeWeapon ) 01497 { 01498 PlayIdleAnim(); 01499 GotoState('Idle'); 01500 return; 01501 } 01502 } 01503 if ( bChangeWeapon ) 01504 GotoState('DownWeapon'); 01505 else if ( Instigator.PressingFire() ) 01506 Global.Fire(0); 01507 else 01508 { 01509 if ( Instigator.PressingAltFire() ) 01510 Global.AltFire(0); 01511 else 01512 { 01513 PlayIdleAnim(); 01514 GotoState('Idle'); 01515 } 01516 } 01517 } 01518 01519 //_____________________________________________________________________________ 01520 state NormalFire 01521 { 01522 function ServerFire() 01523 { 01524 bForceFire = true; 01525 } 01526 01527 function ServerAltFire() 01528 { 01529 bForceAltFire = true; 01530 } 01531 01532 function Fire(float F) {} 01533 function AltFire(float F) {} 01534 01535 function AnimEnd(int Channel) 01536 { 01537 Finish(); 01538 } 01539 01540 function EndState() 01541 { 01542 StopFiringTime = Level.TimeSeconds; 01543 } 01544 Begin: 01545 Sleep(0.0); 01546 } 01547 01548 //_____________________________________________________________________________ 01549 state NormalAltFire 01550 { 01551 function ServerFire() 01552 { 01553 bForceFire = true; 01554 } 01555 01556 function ServerAltFire() 01557 { 01558 bForceAltFire = true; 01559 } 01560 01561 function Fire(float F) {} 01562 function AltFire(float F) {} 01563 01564 function AnimEnd(int Channel) 01565 { 01566 Finish(); 01567 } 01568 01569 function EndState() 01570 { 01571 StopFiringTime = Level.TimeSeconds; 01572 } 01573 Begin: 01574 Sleep(0.0); 01575 } 01576 01577 /* 01578 Weapon is up and ready to fire, but not firing. 01579 */ 01580 state Idle 01581 { 01582 simulated function ForceReload() 01583 { 01584 ServerForceReload(); 01585 } 01586 01587 function ServerForceReload() 01588 { 01589 if ( AmmoType.HasAmmo() ) 01590 GotoState('Reloading'); 01591 } 01592 01593 simulated function AnimEnd(int Channel) 01594 { 01595 PlayIdleAnim(); 01596 } 01597 01598 simulated function bool PutDown() 01599 { 01600 GotoState('DownWeapon'); 01601 return True; 01602 } 01603 01604 Begin: 01605 // bPointing=False; 01606 if ( NeedsToReload() && AmmoType.HasAmmo() ) 01607 GotoState('Reloading'); 01608 if ( !AmmoType.HasAmmo() ) 01609 Instigator.Controller.SwitchToBestWeapon(); //Goto Weapon that has Ammo 01610 if ( Instigator.PressingFire() ) Fire(0.0); 01611 if ( Instigator.PressingAltFire() ) AltFire(0.0); 01612 PlayIdleAnim(); 01613 } 01614 01615 state Reloading 01616 { 01617 function ServerForceReload() {} 01618 function ClientForceReload() {} 01619 function Fire( float Value ) {} 01620 function AltFire( float Value ) {} 01621 01622 function ServerFire() 01623 { 01624 bForceFire = true; 01625 } 01626 01627 function ServerAltFire() 01628 { 01629 bForceAltFire = true; 01630 } 01631 01632 simulated function bool PutDown() 01633 { 01634 bChangeWeapon = true; 01635 return True; 01636 } 01637 01638 simulated function BeginState() 01639 { 01640 if ( !bForceReload ) 01641 { 01642 if ( Role < ROLE_Authority ) 01643 ServerForceReload(); 01644 else 01645 ClientForceReload(); 01646 } 01647 bForceReload = false; 01648 PlayReloading(); 01649 } 01650 01651 simulated function AnimEnd(int Channel) 01652 { 01653 ReloadCount = Default.ReloadCount; 01654 if ( Role < ROLE_Authority ) 01655 ClientFinish(); 01656 else 01657 Finish(); 01658 } 01659 } 01660 01661 01662 /* Active 01663 Bring newly active weapon up. 01664 The weapon will remain in this state while its selection animation is being played (as well as any postselect animation). 01665 While in this state, the weapon cannot be fired. 01666 */ 01667 state Active 01668 { 01669 simulated function BringUp() { bRendered = true; } 01670 function Fire( float Value ) {} 01671 function AltFire( float Value ) {} 01672 01673 function ServerFire() 01674 { 01675 bForceFire = true; 01676 } 01677 01678 function ServerAltFire() 01679 { 01680 bForceAltFire = true; 01681 } 01682 01683 simulated function bool PutDown() 01684 { 01685 local name anim; 01686 local float frame,rate; 01687 GetAnimParams(0,anim,frame,rate); 01688 bChangeWeapon = true; 01689 return True; 01690 } 01691 01692 simulated function BeginState() 01693 { 01694 Instigator = Pawn(Owner); 01695 bForceFire = false; 01696 bForceAltFire = false; 01697 bChangeWeapon = false; 01698 } 01699 01700 simulated function EndState() 01701 { 01702 bForceFire = false; 01703 bForceAltFire = false; 01704 } 01705 01706 simulated function AnimEnd(int Channel) 01707 { 01708 if ( bChangeWeapon ) 01709 GotoState('DownWeapon'); 01710 if ( Owner == None ) 01711 { 01712 log(self$" no owner"); 01713 Global.AnimEnd(0); 01714 GotoState(''); 01715 } 01716 else 01717 { 01718 if ( Role == ROLE_Authority ) 01719 Finish(); 01720 else 01721 ClientFinish(); 01722 } 01723 } 01724 } 01725 01726 /* DownWeapon 01727 Putting down weapon in favor of a new one. No firing in this state 01728 */ 01729 State DownWeapon 01730 { 01731 function Fire( float Value ) {} 01732 function AltFire( float Value ) {} 01733 01734 function ServerFire() {} 01735 function ServerAltFire() {} 01736 01737 simulated function bool PutDown() 01738 { 01739 return true; //just keep putting it down 01740 } 01741 01742 simulated function AnimEnd(int Channel) 01743 { 01744 Pawn(Owner).ChangedWeapon(); 01745 } 01746 01747 simulated function BeginState() 01748 { 01749 bChangeWeapon = false; 01750 bMuzzleFlash = false; 01751 TweenDown(); 01752 } 01753 } 01754 01755 //_____________________________________________________________________________ 01756 //Fire on the client side. This state is only entered on the network client of the player that is firing this weapon. 01757 state ClientFiring 01758 { 01759 function Fire( float Value ) {} 01760 function AltFire( float Value ) {} 01761 01762 simulated function AnimEnd(int Channel) 01763 { 01764 ClientFinish(); 01765 } 01766 01767 simulated function EndState() 01768 { 01769 AmbientSound = None; 01770 if ( RepeatFire() && !bPendingDelete ) 01771 ServerStopFiring(); 01772 } 01773 } 01774 01775 /* PendingClientWeaponSet 01776 Weapon on network client side may be set here by the replicated function ClientWeaponSet(), to wait, 01777 if needed properties have not yet been replicated. ClientWeaponSet() is called by the server to 01778 tell the client about potential weapon changes after the player runs over a weapon (the client 01779 decides whether to actually switch weapons or not. 01780 */ 01781 State PendingClientWeaponSet 01782 { 01783 simulated function Timer() 01784 { 01785 if ( Pawn(Owner) != None ) 01786 ClientWeaponSet(false); 01787 } 01788 01789 simulated function BeginState() 01790 { 01791 SetTimer(0.05, true); 01792 } 01793 01794 simulated function EndState() 01795 { 01796 SetTimer(0.0, false); 01797 } 01798 } 01799 01800 simulated function bool PutDown() 01801 { 01802 bChangeWeapon = true; 01803 return true; 01804 } 01805 01806 simulated function zoom(); 01807 01808 //_____________________________________________________________________________ 01809 simulated function PlayIdleAnim() 01810 { 01811 if ( bHaveBoredSfx && (Instigator != none) && Instigator.IsPlayerPawn() && (iBoredCount > BOREDSFXTHRESHOLD) ) 01812 { 01813 iBoredCount = 0; 01814 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01815 Instigator.PlayRolloffSound(hActWaitSound, self, 0, int(Instigator.IsPlayerPawn()), 0 ); 01816 PlayAnim('WaitAct', 1.0, 0.3); 01817 } 01818 else 01819 PlayAnim('Wait', 1.0, 0.3); 01820 } 01821 01822 //_____________________________________________________________________________ 01823 // 738 µs 01824 simulated function PlayFiring() 01825 { 01826 // Log("PlayFiring call for"@self@"w/FiringMode="$FiringMode); 01827 if ( HasAmmo() ) 01828 PlayAnim(LoadedFiringAnim, 1.0); 01829 else 01830 PlayAnim(EmptyFiringAnim, 1.0); 01831 01832 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01833 PlayFiringSound(HasSilencer()); // 184µs 01834 01835 if ( !HasAmmo() ) 01836 return; 01837 01838 IncrementFlashCount(); // 473 µs 01839 if ( bDrawMuzzleflash ) 01840 SetUpMuzzleFlash(); 01841 } 01842 01843 //_____________________________________________________________________________ 01844 simulated function PlayAltFiring() 01845 { 01846 // Log("PlayAltFiring call for"@self@"w/FiringMode="$FiringMode); 01847 if ( HasAltAmmo() ) 01848 PlayAnim(LoadedAltFiringAnim, 1.0); 01849 else 01850 PlayAnim(EmptyAltFiringAnim, 1.0); 01851 01852 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01853 PlayAltFiringSound(); 01854 01855 if ( !HasAltAmmo() ) 01856 return; 01857 01858 IncrementAltFlashCount(); 01859 if ( bDrawAltMuzzleflash ) 01860 SetUpMuzzleFlash(); 01861 } 01862 01863 native function PlayFiringSound(optional bool bHasSilencer); 01864 /* 01865 //_____________________________________________________________________________ 01866 simulated function PlayFiringSound() 01867 { 01868 if ( bEmptyShot ) 01869 Instigator.PlayRolloffSound(hNoAmmoSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01870 else 01871 { 01872 if ( HasSilencer() ) 01873 Instigator.PlayRolloffSound(hFireSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01874 else 01875 Instigator.PlayRolloffSound(hFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01876 } 01877 } 01878 */ 01879 01880 //_____________________________________________________________________________ 01881 simulated function PlayAltFiringSound() 01882 { 01883 if ( bAltEmptyShot ) 01884 Instigator.PlayRolloffSound(hNoAmmoSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01885 else 01886 { 01887 if ( HasSilencer() ) 01888 Instigator.PlayRolloffSound(hAltFireSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01889 else 01890 Instigator.PlayRolloffSound(hAltFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01891 } 01892 } 01893 01894 //_____________________________________________________________________________ 01895 simulated function TweenDown() 01896 { 01897 // log("TweenDown call for"@self); 01898 PlayAnim('Down', 1.0); 01899 } 01900 01901 //_____________________________________________________________________________ 01902 simulated function PlaySelect() 01903 { 01904 if ( DBWeap ) 01905 log("PlaySelect call for"@self@"w/ mesh="$Mesh); 01906 bForceFire = false; 01907 bForceAltFire = false; 01908 PlayAnim('Select',1.0); 01909 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01910 Instigator.PlayRolloffSound(hSelectWeaponSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01911 } 01912 01913 //_____________________________________________________________________________ 01914 simulated function PlayReloading() 01915 { 01916 PlayAnim('ReLoad',1.0); 01917 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01918 Instigator.PlayRolloffSound(hReloadSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 0 ); 01919 MakeNoise(ReLoadNoise); 01920 } 01921 01922 //_____________________________________________________________________________ 01923 // Reload Notifies 01924 simulated function FPSRelNote1() 01925 { 01926 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01927 Instigator.PlayRolloffSound(hReloadSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 1 ); 01928 } 01929 simulated function FPSRelNote2() 01930 { 01931 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01932 Instigator.PlayRolloffSound(hReloadSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 2 ); 01933 } 01934 simulated function FPSRelNote3() 01935 { 01936 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01937 Instigator.PlayRolloffSound(hReloadSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 3 ); 01938 } 01939 01940 //_____________________________________________________________________________ 01941 // Select Notifies 01942 simulated function FPSSelWPNote1() 01943 { 01944 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01945 Instigator.PlayRolloffSound(hSelectWeaponSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 1 ); 01946 } 01947 simulated function FPSSelWPNote2() 01948 { 01949 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01950 Instigator.PlayRolloffSound(hSelectWeaponSound, self, 2, int(Pawn(Owner).IsPlayerPawn()), 2 ); 01951 } 01952 simulated function FPSSelWPNote3() 01953 { 01954 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01955 Instigator.PlayRolloffSound(hSelectWeaponSound, self, 3, int(Pawn(Owner).IsPlayerPawn()), 3 ); 01956 } 01957 01958 //_____________________________________________________________________________ 01959 // Dry Notifies 01960 simulated function FPSDryNote1() 01961 { 01962 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01963 Instigator.PlayRolloffSound(hNoAmmoSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 1 ); 01964 } 01965 simulated function FPSDryNote2() 01966 { 01967 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01968 Instigator.PlayRolloffSound(hNoAmmoSound, self, 2, int(Pawn(Owner).IsPlayerPawn()), 2 ); 01969 } 01970 simulated function FPSDryNote3() 01971 { 01972 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01973 Instigator.PlayRolloffSound(hNoAmmoSound, self, 3, int(Pawn(Owner).IsPlayerPawn()), 3 ); 01974 } 01975 01976 //_____________________________________________________________________________ 01977 // Firing Notifies 01978 simulated function FPSFireNote1() 01979 { 01980 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01981 { 01982 if ( HasSilencer() ) 01983 Instigator.PlayRolloffSound(hFireSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 1 ); 01984 else 01985 Instigator.PlayRolloffSound(hFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 1 ); 01986 } 01987 } 01988 simulated function FPSFireNote2() 01989 { 01990 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 01991 { 01992 if ( HasSilencer() ) 01993 Instigator.PlayRolloffSound(hFireSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 2 ); 01994 else 01995 Instigator.PlayRolloffSound(hFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 2 ); 01996 } 01997 } 01998 simulated function FPSFireNote3() 01999 { 02000 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 02001 { 02002 if ( HasSilencer() ) 02003 Instigator.PlayRolloffSound(hFireSound, self, 1, int(Pawn(Owner).IsPlayerPawn()), 3 ); 02004 else 02005 Instigator.PlayRolloffSound(hFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 3 ); 02006 } 02007 } 02008 02009 //_____________________________________________________________________________ 02010 // AltFiring Notifies 02011 simulated function FPSFireAltNote1() 02012 { 02013 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 02014 Instigator.PlayRolloffSound(hAltFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 1 ); 02015 } 02016 simulated function FPSFireAltNote2() 02017 { 02018 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 02019 Instigator.PlayRolloffSound(hAltFireSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 2 ); 02020 } 02021 02022 //_____________________________________________________________________________ 02023 // Active waiting Notifies 02024 simulated function FPSFireWaitActNote1() 02025 { 02026 if ( Instigator.IsLocallyControlled() || (Level.NetMode == NM_StandAlone) ) 02027 Instigator.PlayRolloffSound(hActWaitSound, self, 0, int(Pawn(Owner).IsPlayerPawn()), 1 ); 02028 } 02029 02030 defaultproperties 02031 { 02032 bCanThrow=True 02033 LoadedFiringAnim="Fire" 02034 EmptyFiringAnim="Firevide" 02035 LoadedAltFiringAnim="Fire" 02036 EmptyAltFiringAnim="Firevide" 02037 iAltZoomLevel=2 02038 fAltZoomValue(0)=0.700800 02039 fAltZoomValue(1)=0.884800 02040 fAltZoomValue(2)=0.942300 02041 sWeaponModeAuto="Auto" 02042 sWeaponModeSemiAuto="Single" 02043 sWeaponModeBurst="Burst" 02044 ShakeMag=300.000000 02045 shaketime=5.000000 02046 ShakeVert=(Z=5.000000) 02047 ShakeSpeed=(X=300.000000,Y=300.000000,Z=300.000000) 02048 ShakeCycles=1.000000 02049 AIRating=0.500000 02050 TraceDist=1.270000 02051 AltTraceDist=1.270000 02052 MessageNoAmmo=" has no ammo." 02053 MuzzleScale=1.000000 02054 FlashLength=0.100000 02055 InventoryGroup=1 02056 PlayerViewOffset=(X=30.000000,Z=-5.000000) 02057 AttachmentClass=Class'Engine.WeaponAttachment' 02058 Icon=Texture'Engine.S_Weapon' 02059 ItemName="Weapon" 02060 bReplicateInstigator=True 02061 bIgnoreDynLight=False 02062 DrawType=DT_Mesh 02063 SaturationDistance=800.000000 02064 StabilisationDistance=3000.000000 02065 StabilisationVolume=-10.000000 02066 }

End Source Code