Excellent , it works, except SpawnFlightEffects(); needs to go into PostBeginPlay();
Once you have that you don’t need the mesh info. ProjExplosionTemplate=ParticleSystem’yourParticleSystem’ will work.
I’ve been trying to work out where the problem is exactly. I guess it’s the UTProj_Grenade code. I did try the mesh alone (as per your code) not using the emitter because I thought the problem could be the FlightEffects emitter. But as I have the code below using the emitter it collides fine - and my mollys which now extend my grenade work fine too.
(perhaps a couple of reasonable comparison problem examples, or not: maybe the UTProj_Grenade code isn’t at fault… I had a problem with a weapon not picking up ammo -solved after I extended the weapon from the weapon, and the latter extended only had basic defaultproperties and that was about it. But after that it picked up ammo. Another time a weapon wouldn’t reload, and again I extended, and again problem solved. No code changes, nothing, just extended and they worked. Maybe the UT nade doesn’t like being extended from?? When I have some patience I’ll take a look at the nade code.)
Anyway, this works:
class GrenadeKFZproj extends Projectile;
//problem, extended from UTProj_Grenade but they don't collide with Landscape hills
//https: forums.unrealengine.com/showthread.php?124817-grenades-work-on-terrain-but-not-landscape
//solved, but otherwise die landscape die
var float BounceDamping;
var float TossZ;
var float AccelRate;
var float MaxExplosionLightDistance;
var float CustomGravityScaling;
var float CheckRadius;
var float DecalWidth, DecalHeight;
var float DurationOfDecal;
var ParticleSystem ProjFlightTemplate;
var ParticleSystem ProjExplosionTemplate;
var ParticleSystemComponent ProjEffects;
var class<UDKExplosionLight> ExplosionLightClass;
var class<PointLightComponent> ProjectileLightClass;
var SoundCue ExplosionSound;
var PointLightComponent ProjectileLight;
var MaterialInterface ExplosionDecal;
var name DecalDissolveParamName;
var bool bWaitForEffects;
var bool bShuttingDown;
var bool bAdvanceExplosionEffect;
var bool bSuppressExplosionFX;
function LowerTheMFGun()
{
local WeaponKFZ KFZWeap;
KFZWeap = WeaponKFZ(Owner);
if (KFZWeap != None)
{
KFZWeap.WeaponAside4Grenade();
}
}
function RaiseTheMFGun()
{
local WeaponKFZ KFZWeap;
KFZWeap = WeaponKFZ(Owner);
if (KFZWeap != None)
{
KFZWeap.WeaponAside4Grenade();
KFZPawn(Instigator).MakeNoise(21.0, 'GunFire');
}
}
simulated function PostBeginPlay()
{
super.PostBeginPlay();
SpawnFlightEffects();
SetTimer(2.5+FRand()*0.5,false);
RandSpin(100000);
}
function Init(vector Direction)
{
SetRotation(Rotator(Direction));
Velocity = Speed * Direction;
// TossZ = TossZ + (FRand() * TossZ / 4.0) - (TossZ / 5.0);
Velocity.Z += TossZ;
Acceleration = AccelRate * Normal(Velocity);
}
simulated function Timer()
{
Explode(Location, vect(0,0,1));
}
simulated event HitWall(vector HitNormal, Actor Wall, PrimitiveComponent WallComp)
{
bBlockedByInstigator = true;
if ( WorldInfo.NetMode != NM_DedicatedServer )
{
PlaySound(ImpactSound, true);
}
// check to make sure we didn't hit a pawn
if ( Pawn(Wall) == none )
{
Velocity = 0.75*(( Velocity dot HitNormal ) * HitNormal * -2.0 + Velocity);
Speed = VSize(Velocity);
if (Velocity.Z > 400)
{
Velocity.Z = 0.5 * (400 + Velocity.Z);
}
// If we hit a pawn or we are moving too slowly, explod
if ( Speed < 20 || Pawn(Wall) != none )
{
ImpactedActor = Wall;
SetPhysics(PHYS_None);
}
}
else if ( Wall != Instigator ) // Hit a different pawn, just explode
{
Explode(Location, HitNormal);
}
}
simulated event Landed(Vector HitNormal, Actor FloorActor)
{
HitWall(HitNormal, FloorActor, None);
}
simulated function PhysicsVolumeChange( PhysicsVolume NewVolume )
{
if ( WaterVolume(NewVolume) != none )
{
Velocity *= 0.25;
}
Super.PhysicsVolumeChange(NewVolume);
}
simulated function SpawnFlightEffects()
{
if (WorldInfo.NetMode != NM_DedicatedServer && ProjFlightTemplate != None)
{
ProjEffects = WorldInfo.MyEmitterPool.SpawnEmitterCustomLifetime(ProjFlightTemplate);
ProjEffects.SetAbsolute(false, false, false);
ProjEffects.SetLODLevel(WorldInfo.bDropDetail ? 1 : 0);
ProjEffects.OnSystemFinished = MyOnParticleSystemFinished;
ProjEffects.bUpdateComponentInTick = true;
AttachComponent(ProjEffects);
}
}
simulated function MyOnParticleSystemFinished(ParticleSystemComponent PSC)
{
if (PSC == ProjEffects)
{
if (bWaitForEffects)
{
if (bShuttingDown)
{
// it is not safe to destroy the actor here because other threads are doing stuff, so do it next tick
LifeSpan = 0.01;
}
else
{
bWaitForEffects = false;
}
}
// clear component and return to pool
DetachComponent(ProjEffects);
WorldInfo.MyEmitterPool.OnParticleSystemFinished(ProjEffects);
ProjEffects = None;
}
}
simulated function SpawnExplosionEffects(vector HitLocation, vector HitNormal)
{
local vector LightLoc, LightHitLocation, LightHitNormal;
local vector Direction;
local ParticleSystemComponent ProjExplosion;
local Actor EffectAttachActor;
local MaterialInstanceTimeVarying MITV_Decal;
if (WorldInfo.NetMode != NM_DedicatedServer)
{
if (ProjectileLight != None)
{
DetachComponent(ProjectileLight);
ProjectileLight = None;
}
if (ProjExplosionTemplate != None)
{
// Disabling for the demo to prevent explosions from attaching to the pawn...
// EffectAttachActor = (bAttachExplosionToVehicles || (UTVehicle(ImpactedActor) == None)) ? ImpactedActor : None;
EffectAttachActor = None;
if (!bAdvanceExplosionEffect)
{
ProjExplosion = WorldInfo.MyEmitterPool.SpawnEmitter(ProjExplosionTemplate, HitLocation, rotator(HitNormal), EffectAttachActor);
}
else
{
Direction = normal(Velocity - 2.0 * HitNormal * (Velocity dot HitNormal)) * Vect(1,1,0);
ProjExplosion = WorldInfo.MyEmitterPool.SpawnEmitter(ProjExplosionTemplate, HitLocation, rotator(Direction), EffectAttachActor);
ProjExplosion.SetVectorParameter('Velocity',Direction);
ProjExplosion.SetVectorParameter('HitNormal',HitNormal);
}
SetExplosionEffectParameters(ProjExplosion);
if ( !WorldInfo.bDropDetail && ((ExplosionLightClass != None) || (ExplosionDecal != none)) && ShouldSpawnExplosionLight(HitLocation, HitNormal) )
{
if ( ExplosionLightClass != None )
{
if (Trace(LightHitLocation, LightHitNormal, HitLocation + (0.25 * ExplosionLightClass.default.TimeShift[0].Radius * HitNormal), HitLocation, false) == None)
{
LightLoc = HitLocation + (0.25 * ExplosionLightClass.default.TimeShift[0].Radius * (vect(1,0,0) >> ProjExplosion.Rotation));
}
else
{
LightLoc = HitLocation + (0.5 * VSize(HitLocation - LightHitLocation) * (vect(1,0,0) >> ProjExplosion.Rotation));
}
UDKEmitterPool(WorldInfo.MyEmitterPool).SpawnExplosionLight(ExplosionLightClass, LightLoc, EffectAttachActor);
}
// this code is mostly duplicated in: UTGib, UTProjectile, UTVehicle, UTWeaponAttachment be aware when updating
if (ExplosionDecal != None && Pawn(ImpactedActor) == None )
{
if( MaterialInstanceTimeVarying(ExplosionDecal) != none )
{
// hack, since they don't show up on terrain anyway
if ( Terrain(ImpactedActor) == None )
{
MITV_Decal = new(self) class'MaterialInstanceTimeVarying';
MITV_Decal.SetParent( ExplosionDecal );
WorldInfo.MyDecalManager.SpawnDecal(MITV_Decal, HitLocation, rotator(-HitNormal), DecalWidth, DecalHeight, 10.0, FALSE );
//here we need to see if we are an MITV and then set the burn out times to occur
MITV_Decal.SetScalarStartTime( DecalDissolveParamName, DurationOfDecal );
}
}
else
{
WorldInfo.MyDecalManager.SpawnDecal( ExplosionDecal, HitLocation, rotator(-HitNormal), DecalWidth, DecalHeight, 10.0, true );
}
}
}
}
if (ExplosionSound != None)
{
PlaySound(ExplosionSound, true);
}
bSuppressExplosionFX = true; // so we don't get called again
}
}
simulated function bool ShouldSpawnExplosionLight(vector HitLocation, vector HitNormal)
{
local PlayerController P;
local float Dist;
// decide whether to spawn explosion light
ForEach LocalPlayerControllers(class'PlayerController', P)
{
Dist = VSize(P.ViewTarget.Location - Location);
if ( (P.Pawn == Instigator) || (Dist < ExplosionLightClass.Default.Radius) || ((Dist < MaxExplosionLightDistance) && ((vector(P.Rotation) dot (Location - P.ViewTarget.Location)) > 0)) )
{
return true;
}
}
return false;
}
simulated function Explode(vector HitLocation, vector HitNormal)
{
if (Damage>0 && DamageRadius>0)
{
if ( Role == ROLE_Authority )
MakeNoise(1.0);
if ( !bShuttingDown )
{
ProjectileHurtRadius(HitLocation, HitNormal );
}
}
SpawnExplosionEffects(HitLocation, HitNormal);
ShutDown();
}
simulated function SetExplosionEffectParameters(ParticleSystemComponent ProjExplosion);
defaultproperties
{
ProjFlightTemplate=ParticleSystem'KFTex6_effects.mesheffectstuff.GrenadeDM51'
//ProjExplosionTemplate=ParticleSystem'KFTex6_effects.muzzleflashes.UDKsBeautifulGeneralExplosion_mod'
ProjExplosionTemplate=ParticleSystem'KFTex6_effects.muzzleflashes.GrenExplosion'
ExplosionLightClass=class'KFZ.GrenadeLight'
ImpactSound=SoundCue'KFTex4.TheCues.GrenadeRoll'//SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_GrenadeFloor_Cue'
ExplosionSound=SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_Impact_Cue'
ExplosionDecal=MaterialInstanceTimeVarying'WP_RocketLauncher.Decals.MITV_WP_RocketLauncher_Impact_Decal01'
Begin Object Name=CollisionCylinder
CollisionRadius=+24//014.000000
CollisionHeight=+24//014.000000
End Object
CylinderComponent=CollisionCylinder
MaxExplosionLightDistance=+4000.0
speed=1000
MaxSpeed=1200.0
Damage=280.0
DamageRadius=200
MomentumTransfer=80000
MyDamageType=class'KFZ.DamageRocket'
LifeSpan=0.0
DecalWidth=512.0
DecalHeight=512.0
bCollideWorld=true
bBounce=true
TossZ=+245.0
Physics=PHYS_Falling
CheckRadius=36.0
bNetTemporary=False
bWaitForEffects=false
CustomGravityScaling=1. //0.500
}