From what I noticed, it seems to match the timing of the ut2k4 shots, but in the ut99 it seems to be able to do closer combos. For less delay
Code: Select all
class UT2341ShockRifleProjectile extends ShockProjectile;
var FX_ShockRifleProjectile ASMDBallEffect;
var class<DamageType> ComboInstigatingDamageType;
simulated function PostBeginPlay()
{
Super(Projectile).PostBeginPlay();
if ( Level.NetMode != NM_DedicatedServer )
{
ASMDBallEffect = Spawn(class'FX_ShockRifleProjectile', self);
ASMDBallEffect.SetBase(self);
}
Velocity = Speed * Vector(Rotation); // starts off slower so combo can be done closer
SetTimer(0.4, false);
tempStartLoc = Location;
}
function Timer()
{
SetCollisionSize(20, 20);
}
simulated function Destroyed()
{
if (ASMDBallEffect != None)
{
ASMDBallEffect.Destroy();
}
Super(Projectile).Destroyed();
}
simulated function DestroyTrails()
{
if (ASMDBallEffect != None)
{
ASMDBallEffect.Destroy();
}
}
// @! override explosion
simulated function Explode(vector HitLocation,vector HitNormal)
{
if ( Role == ROLE_Authority )
{
HurtRadius(Damage, DamageRadius, MyDamageType, MomentumTransfer, HitLocation );
}
PlaySound(ImpactSound, SLOT_Misc);
if ( EffectIsRelevant(Location,false) )
Spawn(class'FX_ShockRifleImpact',,, Location, Rotator(HitNormal));
SetCollisionSize(0.0, 0.0);
Destroy();
}
// @! override Combo
function SuperExplosion()
{
local actor HitActor;
local vector HitLocation, HitNormal;
HurtRadius(ComboDamage, ComboRadius, ComboDamageType, ComboMomentumTransfer, Location );
Spawn(class'UT2341ShockRifleCombo',self,,,Rotator(Location - Instigator.Location));
if ( (Level.NetMode != NM_DedicatedServer) && EffectIsRelevant(Location,false) )
{
HitActor = Trace(HitLocation, HitNormal,Location - Vect(0,0,120), Location,false);
if ( HitActor != None )
Spawn(class'ComboDecal',self,,HitLocation, rotator(vect(0,0,-1)));
}
PlaySound(ComboSound, SLOT_None,1.0,,800);
DestroyTrails();
Destroy();
}
event TakeDamage( int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType)
{
if (DamageType == ComboInstigatingDamageType)
{
Instigator = EventInstigator;
SuperExplosion();
if( EventInstigator.Weapon != None )
{
EventInstigator.Weapon.ConsumeAmmo(0, ComboAmmoCost, true);
Instigator = EventInstigator;
}
}
}
ñ p( bW ? } § b €? bק ›§ E zu bÁ x9P×99 zÔÔüÃôY b xG B1/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRiflePickup extends ShockRiflePickup;
static function StaticPrecache(LevelInfo L)
{
/*
L.AddPrecacheMaterial(Material'XEffects.ShockHeatDecal');
L.AddPrecacheMaterial(Material'XEffectMat.shock_flash');
L.AddPrecacheMaterial(Material'XEffectMat.shock_flare_a');
L.AddPrecacheMaterial(Material'XEffectMat.shock_core');
L.AddPrecacheMaterial(Material'XEffectMat.purple_line');
L.AddPrecacheMaterial(Material'XEffectMat.shock_sparkle');
L.AddPrecacheMaterial(Material'XEffectMat.shock_core_low');
L.AddPrecacheMaterial(Material'XEffectMat.shock_Energy_green_faded');
L.AddPrecacheMaterial(Material'XEffectMat.Shock_Elec_a');
L.AddPrecacheMaterial(Material'XEffectMat.shock_gradient_b');
L.AddPrecacheMaterial(Material'XEffectMat.Shock_ring_a');
L.AddPrecacheMaterial(Material'XEffectMat.ShockComboFlash');
L.AddPrecacheMaterial(Material'XGameShaders.shock_muzflash_1st');
L.AddPrecacheMaterial(Material'XGameShaders.WeaponShaders.shock_muzflash_3rd');
L.AddPrecacheMaterial(Material'XWeapons_rc.ShockBeamTex');
L.AddPrecacheMaterial(Material'XEffects.SaDScorcht');
L.AddPrecacheMaterial(Material'DeployableTex.C_T_Electricity_SG');
L.AddPrecacheMaterial(Material'UT2004Weapons.ShockRipple');
*/
L.AddPrecacheStaticMesh(StaticMesh'Editor.TexPropSphere');
L.AddPrecacheStaticMesh(StaticMesh'UT2341Weapons_SM.UTASMD');
}
simulated function UpdatePrecacheMaterials()
{
/*
Level.AddPrecacheMaterial(Material'XEffects.ShockHeatDecal');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_flash');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_flare_a');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_core');
Level.AddPrecacheMaterial(Material'XEffectMat.purple_line');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_sparkle');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_core_low');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_Energy_green_faded');
Level.AddPrecacheMaterial(Material'XEffectMat.Shock_Elec_a');
Level.AddPrecacheMaterial(Material'XEffectMat.shock_gradient_b');
Level.AddPrecacheMaterial(Material'XEffectMat.Shock_ring_a');
Level.AddPrecacheMaterial(Material'XEffectMat.ShockComboFlash');
Level.AddPrecacheMaterial(Material'XGameShaders.shock_muzflash_1st');
Level.AddPrecacheMaterial(Material'XGameShaders.WeaponShaders.shock_muzflash_3rd');
Level.AddPrecacheMaterial(Material'XWeapons_rc.ShockBeamTex');
Level.AddPrecacheMaterial(Material'DeployableTex.C_T_Electricity_SG');
Level.AddPrecacheMaterial(Material'XEffects.SaDScorcht');
Level.AddPrecacheMaterial(Material'UT2004Weapons.ShockRipple');
*/
Super(Weapon).UpdatePrecacheMaterials();
}
simulated function UpdatePrecacheStaticMeshes()
{
//Level.AddPrecacheStaticMesh(StaticMesh'Editor.TexPropSphere');
Super.UpdatePrecacheStaticMeshes();
}
X/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRifleCombo extends Actor;
//#exec OBJ LOAD FILE=XEffectMat.utx
var ShockComboFlare Flare;
var Rotator NetRot;
replication
{
//Rotation isn't replicated under these conditions
reliable if (Role == ROLE_Authority)
NetRot;
}
simulated function PreBeginPlay()
{
Super.PreBeginPlay();
if (Role == ROLE_Authority)
NetRot = Rotation;
}
simulated event PostNetBeginPlay()
{
Super.PostNetBeginPlay();
if (Level.NetMode != NM_DedicatedServer)
Spawn(class'FX_ShockRifleComboVortex',self,,,NetRot);
}
auto simulated state Combo
{
Begin:
Sleep(0.9);
LightType = LT_None;
}
E/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRifleBeamFire extends ShockBeamFire;
var class<Emitter> BeamImpactEffectClass;
//var() class<ShockBeamEffect> BeamEffectClass;
//#exec OBJ LOAD FILE=..\Sounds\WeaponSounds.uax
// Leaving this in here because ShockProjFire.ProjSpawnOffset is probably wrong
/*
function DoFireEffect()
{
local Vector StartTrace,X,Y,Z;
local Rotator R, Aim;
Instigator.MakeNoise(1.0);
StartTrace = Instigator.Location + Instigator.EyePosition();
if ( PlayerController(Instigator.Controller) != None )
{
// for combos
Weapon.GetViewAxes(X,Y,Z);
StartTrace = StartTrace + X*class'ShockProjFire'.Default.ProjSpawnOffset.X;
if ( !Weapon.WeaponCentered() )
StartTrace = StartTrace + Weapon.Hand * Y*class'ShockProjFire'.Default.ProjSpawnOffset.Y + Z*class'ShockProjFire'.Default.ProjSpawnOffset.Z;
}
Aim = AdjustAim(StartTrace, AimError);
R = rotator(vector(Aim) + VRand()*FRand()*Spread);
DoTrace(StartTrace, R);
}
*/
/*
function InitEffects()
{
if ( Level.DetailMode == DM_Low )
FlashEmitterClass = None;
Super.InitEffects();
if ( FlashEmitter != None )
Weapon.AttachToBone(FlashEmitter, 'tip');
}
*/
/*
function SpawnBeamEffect(Vector Start, Rotator Dir, Vector HitLocation, Vector HitNormal, int ReflectNum)
{
local xEmitter Beam;
if (Weapon != None)
{
Beam = Weapon.Spawn(BeamEffectClass,,, Start, Dir);
if (ReflectNum != 0)
{
Beam.Instigator = None; // prevents client side repositioning of beam start
}
FX_ShockRifleBeamEffect(Beam).AimAt(HitLocation, HitNormal);
}
}
*/
ïr( K J 0 1 wR*R a. wÛ*Û aG ÿv( \Y _
¤ q ` N L `99 f
c
× \Õú ` ¤ a A j c
\'ß ‚w§ Î Ù*$ š§ Î Ù Ý&¤# a&[§ ¶ \ f
¤# a%[§ ¶ \ f
Ì‚w *
w §° -ä~w.ˆ * V
›¸6Ì V
6ÌØ A › N `Ý NáØ V
AÝ NÛâØ V
AâØ A \ß N A K Ñ N ` T!y AAÿ K!y K Ñ N ` T!y Azw.¹ * L.¹ M A ` €?Âw L* L1 D9D«9?Èܧ AÕõ `Þ {7‚w.ˆ *$ .ˆ Q A ` €? 1 D9D«9?Èܧ AÕõ `Þ {L‚w.ˆ * a à Ý B¯6Ì N6Ì ›6Ì N6Ì › cáØ N ›° c« Üš™?õ„„„a à ø a à ÷ a à ú a à ù 1 D9D«9?Èܧ AÕõ `Þ ò‚˜.ˆ ø%+ ±®9?.ˆ ø«9?ÈÜ9?%§ k ê
%§ Î**¾± B« ÒÍÌL? 1 D9D«9?Èܧ AÕõ `Þ »‚˜.ˆ ø%+ ±®9?.ˆ ø«9?ÈÜ9?%§ k ê
%§ Î**± B« ÒÍÌ̾ & Dȧ AÕõ `ØI 1 D9D«9?Èb§ AÕõ `Ø{ & Dȧ AÕõ `Ø & Dȧ AÕõ `ØÉ A× AÕ @ jë A c
jâØ \ c
a‚Ú j# r.ô * Q¤ a a A9PÕ9?ÿÿÿÿ jaw Q* Q ø \N \ f
A j%G I/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRifleAttachment extends ShockAttachment;
//var class<xEmitter> MuzFlashClass;
//var xEmitter MuzFlash;
simulated function PostNetBeginPlay()
{
Super(xWeaponAttachment).PostNetBeginPlay();
/*
if ( (Instigator != None) && (Instigator.PlayerReplicationInfo != None)&& (Instigator.PlayerReplicationInfo.Team != None) )
{
if ( Instigator.PlayerReplicationInfo.Team.TeamIndex == 0 )
Skins[1] = Material'UT2004Weapons.RedShockFinal';
else if ( Instigator.PlayerReplicationInfo.Team.TeamIndex == 1 )
Skins[1] = Material'UT2004Weapons.BlueShockFinal';
}
*/
}
simulated event ThirdPersonEffects()
{
local rotator r;
if ( Level.NetMode != NM_DedicatedServer && FlashCount > 0 )
{
if ( FiringMode == 0 )
WeaponLight();
else
{
if (MuzFlash == None)
{
MuzFlash = Spawn(MuzFlashClass);
AttachToBone(MuzFlash, 'tip');
}
if (MuzFlash != None)
{
MuzFlash.mStartParticles++;
r.Roll = Rand(65536);
SetBoneRotation('Flash_Bone', r, 0, 1.f);
}
}
}
Super(xWeaponAttachment).ThirdPersonEffects();
}
M/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRifleAmmoPickup extends ShockAmmoPickup;
function RespawnEffect()
{
spawn(class'FX_PickupRespawn');
}
}/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRifleAmmo extends ShockAmmo;
R>/*************************************************************
*
*
*
*************************************************************/
class UT2341ShockRifle extends Weapon;
#exec OBJ LOAD FILE=UT2341Weapons_Tex.utx
#exec OBJ LOAD FILE=UT2341Weapons_Anims.ukx
#exec OBJ LOAD FILE=UT2341Weapons_SM.usx
var ShockProjectile ComboTarget; // used by AI
var bool bRegisterTarget;
var bool bWaitForCombo;
var vector ComboStart;
var color EffectColor;
simulated function vector GetEffectStart()
{
local Coords C;
if ( Instigator.IsFirstPerson() )
{
if ( WeaponCentered() )
return CenteredEffectStart();
C = GetBoneCoords('tip');
return C.Origin - 15 * C.XAxis;
}
return Super.GetEffectStart();
}
simulated function bool WeaponCentered()
{
return ( bSpectated || (Hand > 1) );
}
// AI Interface
function float GetAIRating()
{
local Bot B;
B = Bot(Instigator.Controller);
if ( B == None )
return AIRating;
if ( B.Enemy == None )
{
if ( (B.Target != None) && VSize(B.Target.Location - B.Pawn.Location) > 8000 )
return 0.9;
return AIRating;
}
if ( bWaitForCombo )
return 1.5;
if ( !B.ProficientWithWeapon() )
return AIRating;
if ( B.Stopped() )
{
if ( !B.EnemyVisible() && (VSize(B.Enemy.Location - Instigator.Location) < 5000) )
return (AIRating + 0.5);
return (AIRating + 0.3);
}
else if ( VSize(B.Enemy.Location - Instigator.Location) > 1600 )
return (AIRating + 0.1);
else if ( B.Enemy.Location.Z > B.Location.Z + 200 )
return (AIRating + 0.15);
return AIRating;
}
function SetComboTarget(ShockProjectile S)
{
if ( !bRegisterTarget || (bot(Instigator.Controller) == None) || (Instigator.Controller.Enemy == None) )
return;
bRegisterTarget = false;
ComboStart = Instigator.Location;
ComboTarget = S;
ComboTarget.Monitor(Bot(Instigator.Controller).Enemy);
}
function float RangedAttackTime()
{
local bot B;
B = Bot(Instigator.Controller);
if ( (B == None) || (B.Enemy == None) )
return 0;
if ( B.CanComboMoving() )
return 0;
return FMin(2,0.3 + VSize(B.Enemy.Location - Instigator.Location)/class'ShockProjectile'.default.Speed);
}
function float SuggestAttackStyle()
{
return -0.4;
}
simulated function bool StartFire(int mode)
{
if ( bWaitForCombo && (Bot(Instigator.Controller) != None) )
{
if ( (ComboTarget == None) || ComboTarget.bDeleteMe )
bWaitForCombo = false;
else
return false;
}
return Super.StartFire(mode);
}
function DoCombo()
{
if ( bWaitForCombo )
{
bWaitForCombo = false;
if ( (Instigator != None) && (Instigator.Weapon == self) )
StartFire(0);
}
}
/* BestMode()
choose between regular or alt-fire
*/
function byte BestMode()
{
local float EnemyDist, MaxDist;
local bot B;
bWaitForCombo = false;
B = Bot(Instigator.Controller);
if ( (B == None) || (B.Enemy == None) )
return 0;
if (B.IsShootingObjective())
return 0;
if ( !B.EnemyVisible() )
{
if ( (ComboTarget != None) && !ComboTarget.bDeleteMe && B.CanCombo() )
{
bWaitForCombo = true;
return 0;
}
ComboTarget = None;
if ( B.CanCombo() && B.ProficientWithWeapon() )
{
bRegisterTarget = true;
return 1;
}
return 0;
}
EnemyDist = VSize(B.Enemy.Location - Instigator.Location);
if ( B.Skill > 5 )
MaxDist = 4 * class'ShockProjectile'.default.Speed;
else
MaxDist = 3 * class'ShockProjectile'.default.Speed;
if ( (EnemyDist > MaxDist) || (EnemyDist < 150) )
{
ComboTarget = None;
return 0;
}
if ( (ComboTarget != None) && !ComboTarget.bDeleteMe && B.CanCombo() )
{
bWaitForCombo = true;
return 0;
}
ComboTarget = None;
if ( (EnemyDist > 2500) && (FRand() < 0.5) )
return 0;
if ( B.CanCombo() && B.ProficientWithWeapon() )
{
bRegisterTarget = true;
return 1;
}
if ( FRand() < 0.7 )
return 0;
return 1;
}
// end AI Interface
Cclass UT2341SeekingRocketProj extends UT2341RocketProj;
var Actor Seeking;
var vector InitialDir;
replication
{
reliable if( bNetInitial && (Role==ROLE_Authority) )
Seeking, InitialDir;
}
simulated function Timer()
{
local vector ForceDir;
local float VelMag;
if ( InitialDir == vect(0,0,0) )
InitialDir = Normal(Velocity);
Acceleration = vect(0,0,0);
Super.Timer();
if ( (Seeking != None) && (Seeking != Instigator) )
{
// Do normal guidance to target.
ForceDir = Normal(Seeking.Location - Location);
if( (ForceDir Dot InitialDir) > 0 )
{
VelMag = VSize(Velocity);
// track vehicles better
if ( Seeking.Physics == PHYS_Karma )
ForceDir = Normal(ForceDir * 0.8 * VelMag + Velocity);
else
ForceDir = Normal(ForceDir * 0.5 * VelMag + Velocity);
Velocity = VelMag * ForceDir;
Acceleration += 5 * ForceDir;
}
// Update rocket so it faces in the direction its going.
SetRotation(rotator(Velocity));
}
}
simulated function PostBeginPlay()
{
Super.PostBeginPlay();
SetTimer(0.1, true);