## XIII
Class XIIIProjectile

source: C:\XIII\XIII\Classes\XIIIProjectile.uc

    Core.Object
       |
       +--Engine.Actor
          |
          +--Engine.Projectile
             |
             +--XIII.XIIIProjectile

Direct Known Subclasses:USA02HelicoMissile, AshTrayFlying, BazookRocket, Bolt, BottleFlying, BrikFlying, BulletTraces, DartFlying, GrenadFlying, HarponFlying, HookProjectile, M16GrenadFlying, PhoneFlying, ShardFlying, TKnifeFlying, WBallFlying, FlashBangFlying, MPBombFlying

class XIIIProjectile
extends Engine.Projectile

    //-----------------------------------------------------------
    //
    //-----------------------------------------------------------

Variables
`class` | `ExplosionEmitterClass` Memorize water entry to (maybe) spawn water surface explosion
`int` | `HitSoundType` Type of sound vs type of impact
`class` | `ImpactEmitterMem` Should be spawned & init() in child classes (because spec inits needed).
`float` | `ImpactNoise` Noise made by the Projectile when hitting something
`class` | `InHeadClass` Type of sound vs type of impact
`Trail` | `MyTrail` Should be spawned & init() in child classes (because spec inits needed).
`class` | `MyTrailClass` Type of sound vs type of impact
`vector` | `OrgFrom` used for shakes on blowup
`float` | `ShakeCycles` used for shakes on blowup
`float` | `ShakeMag` used for shakes on blowup
`vector` | `ShakeSpeed` used for shakes on blowup
`float` | `ShakeTime` used for shakes on blowup
`vector` | `ShakeVert` used for shakes on blowup
`float` | `SoftImpactNoise` Noise made by the Projectile when hitting someone
`string` | `StaticMeshName` to dynamicload it
`class` | `aVisualImpact` Type of sound vs type of impact
`bool` | `bHaveBlownUp` if true spawn ExplosionDecal else spawn VisualImpact
`bool` | `bSpawnDecal` if true spawn ExplosionDecal else spawn VisualImpact
`bool` | `bSplashed` if true spawn ExplosionDecal else spawn VisualImpact
`sound` | `hExploSound` Type of sound vs type of impact
`int` | `iStunning` projectile stun if HeadShot, no damage else (not bool because bool don't work as function params on GC)
`vector` | `vWaterEntry` Memorize water entry to (maybe) spawn water surface explosion

Function Summary
`simulated` | `BlowUp(vector HitLocation)`
    //_____________________________________________________________________________
`bool` | `CanSplash()`
    //_____________________________________________________________________________
`DamageLocations` | `GetPotentialDamageLocation(XIIIPawn P, vector HitLoc, vector HitDir)`
    //_____________________________________________________________________________
    // ELR CheckDamageLocation, used by projectiles
`simulated` | `HitWall(vector HitNormal, Actor Wall)`
    //_____________________________________________________________________________
`simulated` | `PlayImpactSound(vector Normal, Actor Wall)`
    //_____________________________________________________________________________
`simulated` | `ProcessTouch(Actor Other, Vector HitLocation)`
    //_____________________________________________________________________________
    // Override ProcessTouch
`void` | `SetImpactNoise(float IN1, float IN2)`
    //_____________________________________________________________________________
`simulated` | `SetUpImpactEmitter(Sound S)`
    //_____________________________________________________________________________
`simulated` | `SpawnWaterExplo(vector HitLocation)`
    //_____________________________________________________________________________
    // Generic water surface explosion SFX
`void` | `StaticParseDynamicLoading(LevelInfo MyLI)`
    //_____________________________________________________________________________
`void` | `Touch(Actor Other)`
    //_____________________________________________________________________________
    // Touching

Source Code

    00001	//-----------------------------------------------------------
    00002	//
    00003	//-----------------------------------------------------------
    00004	class XIIIProjectile extends Projectile;
    00005
    00006	var bool bSpawnDecal;         // if true spawn ExplosionDecal else spawn VisualImpact
    00007	var bool bHaveBlownUp;
    00008	var bool bSplashed;
    00009
    00010	enum DamageLocations
    00011	{
    00012	    LOC_Head,
    00013	    LOC_Body,
    00014	    LOC_HeadSide,
    00015	};
    00016
    00017	var float ImpactNoise;        // Noise made by the Projectile when hitting something
    00018	var float SoftImpactNoise;    // Noise made by the Projectile when hitting someone
    00019	var int HitSoundType;         // Type of sound vs type of impact
    00020	// 0 = bullet
    00021	// 1 = Fists
    00022	// 2 = CommandoKnife UNUSED
    00023	// 3 = Bolt/Harpon
    00024	// 4 = Grenade bounce
    00025	// 5 = TKnife
    00026	var class<Effects> aVisualImpact;
    00027	var sound hExploSound;
    00028	var class<ProjectileInHead> InHeadClass;
    00029	var class<Trail> MyTrailClass;
    00030	var Trail MyTrail;            // Should be spawned & init() in child classes (because spec inits needed).
    00031	var class<ImpactEmitter> ImpactEmitterMem;
    00032	var string StaticMeshName;    // to dynamicload it
    00033
    00034	var float ShakeMag;           // used for shakes on blowup
    00035	var float ShakeTime;
    00036	var vector ShakeVert;
    00037	var vector ShakeSpeed;
    00038	var float ShakeCycles;
    00039	var vector OrgFrom;
    00040	var vector vWaterEntry;       // Memorize water entry to (maybe) spawn water surface explosion
    00041
    00042	var config class<Emitter> ExplosionEmitterClass;
    00043
    00044	var int iStunning;            // projectile stun if HeadShot, no damage else (not bool because bool don't work as function params on GC)
    00045
    00046	CONST DBProj=false;
    00047
    00048	//_____________________________________________________________________________
    00049	Static function StaticParseDynamicLoading(LevelInfo MyLI)
    00050	{
    00051	    Log("XIIIProjectile StaticParseDynamicLoading class="$default.class);
    00052	    if ( default.StaticMeshName != "" )
    00053	      MyLI.ForcedStaticMeshes[MyLI.ForcedStaticMeshes.Length] =
    00054	        StaticMesh(DynamicLoadObject(default.StaticMeshName, class'StaticMesh'));
    00055	}
    00056
    00057	//_____________________________________________________________________________
    00058	simulated event PostBeginPlay()
    00059	{
    00060	    Super.PostBeginPlay();
    00061	    if ( (StaticMesh == none) && (StaticMeshName != "") )
    00062	    {
    00063	      StaticMesh = StaticMesh(dynamicloadobject(StaticMeshName, class'StaticMesh'));
    00064	      default.StaticMesh = StaticMesh;
    00065	      SetDrawType(DT_StaticMesh);
    00066	//      Log("PostBeginPlay DYNAMICLOAD StaticMesh "$StaticMeshName@"result "$StaticMesh);
    00067	    }
    00068	    vWaterEntry = Location;
    00069	    OrgFrom = Location;
    00070	    if ( (Instigator != none) && (Instigator.Base != none) && (Instigator.Base.Velocity != vect(0,0,0)) )
    00071	      SetBase(Instigator.Base);
    00072	}
    00073
    00074	//_____________________________________________________________________________
    00075	event Timer2()
    00076	{ // FIXME cheat to make complex staticmesh movers (like elevators) work
    00077	    Touching.Length = 0;
    00078	}
    00079
    00080	//_____________________________________________________________________________
    00081	// Touching
    00082	simulated singular function Touch(Actor Other)
    00083	{
    00084	    local actor HitActor;
    00085	    local vector HitLocation, HitNormal, VelDir;
    00086	    local bool bBeyondOther;
    00087	    local float BackDist, DirZ;
    00088	    local material HitMat;
    00089	    local staticMeshActor SMA;
    00090	    local VehicleDeco VHD;
    00091	    local Mover Mov;
    00092	    local int i;
    00093
    00094	    if ( Other == Instigator )
    00095	      return;
    00096	    if ( DBProj ) Log("PROJ"@self@"Touched "$Other);
    00097	    if ( Velocity == vect(0,0,0) )
    00098	    {
    00099	      if ( DBProj ) Log("  Touched cancelled because null velocity");
    00100	      return;
    00101	    }
    00102
    00103	    if ( StaticMeshActor(Other) != none )
    00104	    { // touching a staticmeshactor that is not bWorldGeometry, Get exact hit location
    00105	      if ( DBProj ) Log("  Is StaticMeshActor");
    00106	      SetTimer2(0.02, false); // to clean touching list later;
    00107	      foreach TraceActors(class'StaticMeshActor', SMA, HitLocation, HitNormal, Location + Velocity*0.1, Location - Velocity*0.1, vect(0,0,0), TRACETYPE_DiscardIfCanShootThroughWithProjectileWeapon)
    00108	      {
    00109	        if (SMA == Other)
    00110	        {
    00111	          SetLocation(HitLocation);
    00112	//          Log("--> proj Other="$other$" HitActor="$SMA$" Location="$Location@"hitLocation="$HitLocation);
    00113	          HitWall(HitNormal, Other);
    00114	          return;
    00115	        }
    00116	      }
    00117	      HitWall(-vector(rotation), other);
    00118	      // Remove other from touching list ::TODO:: Hum Hum check if this is not too dirty & may cause crash for a reason or another
    00119	      return;
    00120	    }
    00121	    else if ( VehicleDeco(Other) != none )
    00122	    { // touching a staticmeshactor that is not bWorldGeometry, Get exact hit location
    00123	      if ( DBProj ) Log("  Is VehicleDeco");
    00124	      SetTimer2(0.02, false); // to clean touching list later;
    00125	      foreach TraceActors(class'VehicleDeco', VHD, HitLocation, HitNormal, Location + Velocity*0.1, Location - Velocity*0.1, vect(0,0,0), TRACETYPE_DiscardIfCanShootThroughWithProjectileWeapon)
    00126	      {
    00127	        if (VHD == Other)
    00128	        {
    00129	          SetLocation(HitLocation);
    00130	//          Log("--> proj Other="$other$" HitActor="$VHD$" Location="$Location@"hitLocation="$HitLocation@"Normal="@HitNormal);
    00131	          HitWall(HitNormal, Other);
    00132	          return;
    00133	        }
    00134	      }
    00135	      HitWall(-vector(rotation), other);
    00136	      // Remove other from touching list ::TODO:: Hum Hum check if this is not too dirty & may cause crash for a reason or another
    00137	      return;
    00138	    }
    00139	    else if ( Mover(Other) != none )
    00140	    {
    00141	      if ( DBProj ) Log("  Is Mover");
    00142	      SetTimer2(0.02, false); // to clean touching list later;
    00143	      foreach TraceActors(class'Mover', Mov, HitLocation, HitNormal, Location + Velocity*0.1, Location - Velocity*0.1, vect(0,0,0), TRACETYPE_DiscardIfCanShootThroughWithProjectileWeapon)
    00144	      {
    00145	        if ( (Mov == Other) && (HitNormal dot Velocity < 0.0) )
    00146	        {
    00147	//          Log("--> proj Other="$other$" HitActor="$SMA$" Location="$Location@"hitLocation="$HitLocation);
    00148	          SetLocation(HitLocation + HitNormal*2.0);
    00149	          HitWall(HitNormal, Other);
    00150	          return;
    00151	        }
    00152	      }
    00153	      HitWall(-vector(rotation), other);
    00154	      // Remove other from touching list ::TODO:: Hum Hum check if this is not too dirty & may cause crash for a reason or another
    00155	      return;
    00156	    }
    00157
    00158	    if ( Other.bProjTarget || (Other.bBlockActors && Other.bBlockPlayers) )
    00159	    {
    00160	      if ( Velocity == vect(0,0,0) )
    00161	      {
    00162	        ProcessTouch(Other,Location);
    00163	        return;
    00164	      }
    00165
    00166	      //get exact hitlocation - trace back along velocity vector
    00167	      bBeyondOther = ( (Velocity dot (Location - Other.Location)) > 0 );
    00168	//      Log("--> proj bBeyondOther="$bBeyondOther);
    00169	      VelDir = Normal(Velocity);
    00170	      DirZ = sqrt(abs(VelDir.Z));
    00171	//      Log("-->  Other="$other@"ColRad="$Other.CollisionRadius@"ColHei="$Other.CollisionHeight@"VelDir="$VelDir@"DirZ="$DirZ);
    00172	      BackDist = Other.CollisionRadius * (1 - DirZ) + Other.CollisionHeight * DirZ;
    00173	//      Log("-->  1rst BackDist="$BackDist);
    00174
    00175
    00176	      if ( bBeyondOther )
    00177	        BackDist += VSize(Location - Other.Location);
    00178	      else
    00179	        BackDist -= VSize(Location - Other.Location);
    00180	//      Log("-->  2nd BackDist="$BackDist);
    00181
    00182	      HitActor = Trace(HitLocation, HitNormal, Location, Location - 1.1 * BackDist * VelDir, true, vect(0,0,0), HitMat, TRACETYPE_DiscardIfCanShootThroughWithProjectileWeapon);
    00183	//      Log("--> proj HitActor="$HitActor$" Location="$Location@"hitLocation="$HitLocation@"BackDist="$BackDist);
    00184	      if (HitActor == Other)
    00185	        ProcessTouch(Other, HitLocation);
    00186	      else if ( bBeyondOther )
    00187	// ELR It seem like this code mess up the hitLocation if bBeyondOther=true (as we do have localized damages)
    00188	//        ProcessTouch(Other, Other.Location - Other.CollisionRadius * VelDir);
    00189	        ProcessTouch(Other, Location - 2.0 * Other.CollisionRadius * VelDir);
    00190	      else
    00191	        ProcessTouch(Other, Location);
    00192	    }
    00193	}
    00194
    00195	//_____________________________________________________________________________
    00196	// Override ProcessTouch
    00197	simulated function ProcessTouch(Actor Other, Vector HitLocation)
    00198	{
    00199	    local int Loc;
    00200	    Local bool bSpawnHeadProj;
    00201	    local ProjectileInHead PIH;
    00202
    00203	    if ( DBProj ) Log("PROJ"@self@"ProcessTouch"@other@"iStunning="$iStunning);
    00204	    if ( Other != Instigator )
    00205	    {
    00206	      if ( XIIIPawn(Other) != none )
    00207	      {
    00208	        if ( Velocity != vect(0,0,0) )
    00209	          Loc = GetPotentialDamageLocation( XIIIPawn(Other), HitLocation, Velocity);
    00210	        else
    00211	          Loc = GetPotentialDamageLocation( XIIIPawn(Other), HitLocation, vector(rotation) );
    00212	      }
    00213	//      Log("  >"@self@"ProcessTouch LOC="@Loc);
    00214	      if ( iStunning > 0 )
    00215	      {
    00216	        if ( Loc == 1 )
    00217	        {
    00218	//          Log("  >"@self@" No damages, Body hit");
    00219	          Explode(HitLocation,Normal(HitLocation-Other.Location));
    00220	          if ( Pawn(Other) != none )
    00221	            MakeNoise(SoftImpactNoise);
    00222	          else
    00223	            MakeNoise(ImpactNoise);
    00224	          return;
    00225	        }
    00226	//        else
    00227	//          Log("  >"@self@" Damages, Head hit");
    00228	      }
    00229	      if ( DBProj ) Log("  > "$self$" ProcessTouch other="$other$" Loc="$Loc$" HitLocation="$HitLocation);
    00230	      if ( Loc <= 1 )
    00231	      {
    00232	        if ( (Pawn(Other) != none) &&  !Pawn(Other).bIsDead )
    00233	          bSpawnHeadProj = true; // Only spawn once & at first time
    00234	        Other.TakeDamage(Damage, Instigator, HitLocation, -MomentumTransfer * normal(velocity), MyDamageType);
    00235	        Explode(HitLocation,Normal(HitLocation-Other.Location));
    00236	        if ( (Pawn(Other) != none) && (Level.Game != none) && (Level.Game.GoreLevel == 0) )
    00237	        {
    00238	          if ( (Loc == 0) && bSpawnHeadProj && Pawn(Other).bIsDead && (InHeadClass != none) )
    00239	          {
    00240	            PIH = Spawn(InHeadClass,Other,,HitLocation, Rotation);
    00241	            PIH.StaticMesh = StaticMesh;
    00242	          }
    00243	          Spawn(class'XIIIDamageType'.default.BloodShotEmitterClass,,, HitLocation, Rotator(normal(HitLocation-Other.Location)));
    00244	        }
    00245
if ( Pawn(Other) != none ) 00246 MakeNoise(SoftImpactNoise); 00247 else 00248 MakeNoise(ImpactNoise); 00249 } 00250 // else do nothing, keep the projectile going 00251 } 00252 } 00253 00254 //_____________________________________________________________________________ 00255 // ELR CheckDamageLocation, used by projectiles 00256 function DamageLocations GetPotentialDamageLocation( XIIIPawn P, vector HitLoc , vector HitDir) 00257 { 00258 // Inspired from DX (Thanx to the scripter that gave the offset formula to a newB:) 00259 local Vector offset, HitLoc2, HitNorm2, StartTrace, EndTrace; 00260 local float headOffsetZ; 00261 local Actor A; 00262 local material HitMat; 00263 00264 if ( P.bIsDead ) return LOC_Body; 00265 P.LastBoneHit=''; 00266 00267 // Use the hitlocation to determine where the pawn is hit 00268 // Transform the worldspace hitlocation into objectspace 00269 // In objectspace, X is front to back Y is side to side, and Z is top to bottom 00270 offset = (HitLoc - P.Location) << P.Rotation; 00271 headOffsetZ = P.CollisionHeight * 0.65; 00272 00273 if ( (iStunning > 0) || (P.IsPlayerPawn() && Level.bLonePlayer) ) 00274 { // ELR Cheat to optimize (no call to foreach trace) when several enemies 00275 // are shooting the player in solo game 00276 // Log("GetPotentialDamageLocation Offset="$Offset.z / P.CollisionHeight); 00277 if ( Offset.Z > P.CollisionHeight * 0.7 ) 00278 return LOC_Head; 00279 else 00280 return LOC_Body; 00281 } 00282 00283 StartTrace = HitLoc - normal(HitDir)*P.CollisionRadius*2.0; 00284 EndTrace = HitLoc + normal(HitDir)*P.CollisionRadius*2.0; 00285 // Log("P.Location="$P.Location@"HitLoc="$HitLoc@"HitDir="$HitDir@"StartTRace="$StartTrace@"EndTrace="$EndTrace); 00286 foreach TraceActors(class'Actor', A, HitLoc2, HitNorm2, EndTrace, StartTrace, vect(0,0,0), TRACETYPE_RequestBones) 00287 { 00288 // Log(P@"testing actor "$A); 00289 if ( A == P ) 00290 { 00291 /* 00292 StartTrace = HitLoc - normal(HitDir)*P.CollisionRadius*2.0; 00293 EndTrace = HitLoc + normal(HitDir)*P.CollisionRadius*2.0; 00294 A = Trace(HitLoc2, HitNorm2, HitLoc2 - HitNorm2*P.CollisionRadius*2, HitLoc2 + HitNorm2, True, vect(0,0,0), HitMat, TRACETYPE_RequestBones); 00295 */ 00296 P.LastBoneHit = GetLastTraceBone(); 00297 // Log(">>> Potential Bone ="$P.LastBoneHit); 00298 if ( P.LastBoneHit == 'X Head' ) 00299 return LOC_Head; 00300 } 00301 } 00302 00303 if ( Offset.Z > HeadOffsetZ ) 00304 return LOC_HeadSide; 00305 else 00306 return LOC_Body; 00307 } 00308 00309 //_____________________________________________________________________________ 00310 function SetImpactNoise(float IN1, float IN2) 00311 { 00312 SoftImpactNoise = IN1; 00313 ImpactNoise = IN2; 00314 } 00315 00316 //_____________________________________________________________________________ 00317 simulated function BlowUp(vector HitLocation) 00318 { 00319 local XIIIPlayerPawn Victims; 00320 local vector HitLoc; 00321 00322 if ( bHaveBlownUp ) 00323 return; 00324 00325 bHaveBlownUp=true; 00326 // Log(self$" blowing up w/ MomentumTransfer="$MomentumTransfer); 00327 00328 if ( Instigator == none ) 00329 Instigator = Pawn(Owner); 00330 00331 HurtRadius(Damage,DamageRadius, MyDamageType, MomentumTransfer, HitLocation ); 00332 if ( ShakeTime != 0 ) 00333 { 00334 foreach RadiusActors( class 'XIIIPlayerPawn', Victims, DamageRadius*0.5, HitLoc ) 00335 { 00336 PlayerController(Victims.Controller).ShakeView(ShakeTime, ShakeMag, ShakeVert, 120000, ShakeSpeed, ShakeCycles); 00337 } 00338 } 00339 00340 if ( Role == ROLE_Authority ) 00341 MakeNoise(ImpactNoise); 00342 PlaySound(hExploSound,0,1,2); 00343 } 00344 00345 //_____________________________________________________________________________ 00346 simulated function HitWall(vector HitNormal, actor Wall) 00347 { 00348 if ( DBProj ) Log("PROJ"@self@"HitWall"@Wall@"Normal="$HitNormal); 00349 00350 if ( Role == ROLE_Authority ) 00351 { 00352 if ( Mover(Wall) != None ) 00353 Wall.TakeDamage( Damage, instigator, Location, MomentumTransfer * Normal(Velocity), MyDamageType); 00354 MakeNoise(ImpactNoise); 00355 } 00356 // PlayImpactSound(HitNormal, Wall); 00357 PlayImpactSound(-vector(rotation), Wall); 00358 00359 Explode(Location + ExploWallOut * HitNormal, HitNormal); 00360 00361 if ( (Mover(Wall) == None) && !Wall.bMovable ) 00362 { 00363 if ( bSpawnDecal && (ExplosionDecal != None) && (Level.NetMode != NM_DedicatedServer) ) 00364 Spawn(ExplosionDecal,self,,Location, rotator(-HitNormal)); 00365 else if ( !bSpawnDecal && (aVisualImpact != None) && (Level.NetMode != NM_DedicatedServer) ) 00366 Spawn(aVisualImpact,self,,Location+0.1*HitNormal, rotator( (vector(rotation)*2.0-HitNormal)/3.0 )); 00367 } 00368 } 00369 00370 //_____________________________________________________________________________ 00371 simulated function PlayImpactSound(vector Normal, actor Wall) 00372 { 00373 local Material M; 00374 local actor A; 00375 local vector HitLoc, HitNorm; 00376 local ImpactEmitter B; 00377 00378 if ( Level.NetMode == NM_DedicatedServer ) 00379 return; 00380 00381 A = Trace(HitLoc, HitNorm, Location - Normal*10, Location + Normal*10, true, vect(0,0,0), M); 00382 00383 if ( DBProj ) Log("PlayImpactSound A="$A@"M="$M); 00384 if ( Wall.bWorldGeometry || (Mover(Wall) != none) || (StaticMeshActor(Wall) != none) || (VehicleDeco(Wall) != none)) 00385 { 00386 if ( (M != none) && (M.HitSound != none) ) 00387 SetUpImpactEmitter(M.HitSound); 00388 if ( ImpactEmitterMem != none ) 00389 { 00390 B = Spawn(ImpactEmitterMem,,, HitLoc+HitNorm, Rotator(HitNorm)); 00391 if ( (B != none) && (HitSoundType >= 0) ) 00392 { 00393 if ( (M != none) && (M.HitSound != none) ) 00394 B.PlaySound(M.HitSound, HitSoundType); 00395 } 00396 } 00397 } 00398 } 00399 00400 //_____________________________________________________________________________ 00401 simulated function SetUpImpactEmitter(Sound S) 00402 { 00403 local string Str; 00404 local int i; 00405 00406 // First get rid of the beginning of the sound name just to keep whet is needed 00407 Str = string(S); 00408 i = InStr(S, 'hPlay'); 00409 Str = Right(Str, Len(Str) - i - 5); 00410 // Log("--'"$Str$"'--"); 00411 00412 // Then switch/case the result to setup the SFX class 00413 switch (Str) 00414 { 00415 case "ImpBtE": 00416 case "ImpBtI": 00417 case "ImpCar": 00418 case "ImpMar": 00419 case "ImpTil": 00420 case "ImpPie": 00421 // Concrete type 00422 ImpactEmitterMem = class'BulletDustEmitter'; 00423 break; 00424 case "ImpGra": 00425 // Gravel type 00426 ImpactEmitterMem = class'GravelDustEmitter'; 00427 break; 00428 case "ImpBoiC": 00429 case "ImpBoiP": 00430 case "ImpPar": 00431 case "ImpFeu": 00432 // Wood type 00433 ImpactEmitterMem = class'WoodDustEmitter'; 00434 break; 00435 case "ImpEau": 00436 // Water type (should not happen but maybe....) 00437 ImpactEmitterMem = class'BulletDustEmitter'; 00438 break; 00439 case "ImpGla": 00440 case "ImpVer": 00441 // Glass type 00442 ImpactEmitterMem = class'GlassImpactEmitter'; 00443 break; 00444 case "ImpGri": 00445 case "ImpMet": 00446 case "ImpTol": 00447 // Metal type 00448 ImpactEmitterMem = class'BulletMetalEmitter'; 00449 break; 00450 case "ImpHrb": 00451 // Grass Type 00452 ImpactEmitterMem = class'GrassDustEmitter'; 00453 break; 00454 case "ImpTer": 00455 // Earth type 00456 ImpactEmitterMem = class'EarthDustEmitter'; 00457 break; 00458 case "ImpNei": 00459 // Snow Type 00460 ImpactEmitterMem = class'SnowDustEmitter'; 00461 break; 00462 case "ImpMol": 00463 case "ImpMoq": 00464 // Soft Types 00465 ImpactEmitterMem = class'MoqDustEmitter'; 00466 break; 00467 case "ImpCdvr": 00468 ImpactEmitterMem = class'BloodShotEmitter'; 00469 break; 00470 case "ImpLin": 00471 default: 00472 // other types, not spawn any SFX 00473 ImpactEmitterMem = class'BulletDustEmitter'; 00474 break; 00475 } 00476 /* 00477 handler hPlayImpBtE (int iWhichAmmo) Béton exterieur 00478 handler hPlayImpBtI (int iWhichAmmo) Béton interieur 00479 handler hPlayImpBoiC (int iWhichAmmo) Bois Creux 00480 handler hPlayImpBoiP (int iWhichAmmo) Bois plein 00481 handler hPlayImpCar (int iWhichAmmo) Carrelage 00482 handler hPlayImpEau (int iWhichAmmo) Eau 00483 handler hPlayImpFeu (int iWhichAmmo) Feuilles 00484 handler hPlayImpFlesh (int iWhichAmmo) Chair 00485 handler hPlayImpGla (int iWhichAmmo) Glace 00486 handler hPlayImpGra (int iWhichAmmo) Gravier 00487 handler hPlayImpGri (int iWhichAmmo) Grille 00488 handler hPlayImpHrb (int iWhichAmmo) Herbe 00489 handler hPlayImpLin (int iWhichAmmo) Lino 00490 handler hPlayImpMar (int iWhichAmmo) Marbre 00491 handler hPlayImpMet (int iWhichAmmo) Métal 00492 handler hPlayImpMol (int iWhichAmmo) diverses textures molles: matelas; fauteuille; liège. 00493 handler hPlayImpMoq (int iWhichAmmo) Moquette 00494 handler hPlayImpNei (int iWhichAmmo) Neige 00495 handler hPlayImpPar (int iWhichAmmo) Parquet 00496 handler hPlayImpPie (int iWhichAmmo) Pierre 00497 handler hPlayImpTer (int iWhichAmmo) Terre 00498 handler hPlayImpTol (int iWhichAmmo) Tôle 00499 handler hPlayImpTil (int iWhichAmmo) Tuile 00500 handler hPlayImpVer (int iWhichAmmo) Verre*/ 00501 } 00502 00503 //_____________________________________________________________________________ 00504 simulated event Destroyed() 00505 { 00506 if ( DBProj ) Log("PROJ"@self@"Destroyed "); 00507 if ( MyTrail != none ) 00508 MyTrail.Destroy(); 00509 Super.Destroyed(); 00510 } 00511 00512 //_____________________________________________________________________________ 00513 function bool CanSplash() 00514 { 00515 if ( !bSplashed ) 00516 { 00517 bSplashed = true; 00518 return true; 00519 } 00520 } 00521 00522 //_____________________________________________________________________________ 00523 event PhysicsVolumeChange( PhysicsVolume NewVolume ) 00524 { 00525 // Log("PhysicsVolumeChange"); 00526 // no super so don't call 00527 if ( NewVolume.bWaterVolume ) 00528 vWaterEntry = Location; 00529 } 00530 00531 //_____________________________________________________________________________ 00532 // Generic water surface explosion SFX 00533 simulated function SpawnWaterExplo(vector HitLocation) 00534 { 00535 local vector HitLoc, HitNorm; 00536 local vector StartTrace; 00537 local actor other; 00538 Local Material HitMat; 00539 00540 StartTrace = (HitLocation + vWaterEntry)/2.0; 00541 StartTrace.z = vWaterEntry.z + 10; 00542 Other = Trace(HitLoc, HitNorm, (HitLocation + vWaterEntry)/2.0, StartTrace, false, vect(0,0,0), HitMat, 0x008); 00543 if ( Other.IsA('Watervolume') ) 00544 PhysicsVolume(Other).BeingHitByProjectile(HitLoc); 00545 } 00546 00547 00548 00549 defaultproperties 00550 { 00551 bSpawnDecal=True 00552 HitSoundType=-1 00553 hExploSound=Sound'XIIIsound.Explo__ExploGren.ExploGren__hExploGren' 00554 bUnlit=False 00555 SaturationDistance=100.000000 00556 StabilisationDistance=794.000000 00557 }

End Source Code