Re: Auto-Guiding Rockets -- [WIP]
Posted: Sun Mar 19, 2017 9:54 pm
any update on this?
Code: Select all
//=============================================================================
// AutoRocket.
//=============================================================================
class AutoRocket expands UT_SeekingRocket;
var() float SeekAcceleration, SeekSpeed, TargetAcquiringRadius, WallAvoidSpeed, WallPredictionFactor, WallAvoidSlowdown, ShootDensity, ShootDistance, ShootDistanceFactor, MinHomePathDistance, MinWallAvoidNormal, TargetFindDensity, MaxPathDistance, FlockRadius, RotateRate, MinSeekAccel;
var() bool bShootAtTarget, bIgnoreIgnorers, bFlock, bLayBreadcrumbs;
var() class<Actor> ProjectileClass;
var Pawn User;
var Actor HomeTarget;
var BreadcrumbPath NavigationPath, TempCrumb;
var bool bFoundUser;
var WingedCrumb B, MyCrumb, TargetWC, TargetW;
var int Slew;
var enum GusNavType
{
NAV_None,
NAV_Default,
NAV_Crumbs
}
Navigation;
replication
{
reliable if ( Role == ROLE_Authority )
User,
bFoundUser;
}
simulated function float MinHomeNormal()
{
if ( Seeking != None && !Seeking.IsInState('Dying') )
return 0.5 * MinWallAvoidNormal;
else
return 0.1 * MinWallAvoidNormal;
}
simulated event bool PercentChance(float Percentage)
{
return FRand() * 100 < Percentage;
}
simulated event Vector EstimateLocation(Actor Other)
{
if ( Other == None )
return Location;
return Other.Location + (Other.Velocity / VSize(Velocity)) * 0.5;
}
simulated event HomeAt(Actor Other, optional bool bRotateOnly)
{
local Vector Est;
Est = EstimateLocation(Other);
if ( bRotateOnly )
{
Velocity += Vector(Rotation) + (Est - Location) * RotateRate;
}
else
{
Acceleration += ((Est - Location) * SeekSpeed);
Velocity *= (SeekAcceleration / (Velocity dot (Est - Location))) + MinSeekAccel;
}
}
simulated event Actor WillHitWall(optional out Vector Location, optional out Vector OutNormal)
{
return Trace(Location, OutNormal, Self.Location + Velocity * WallPredictionFactor);
}
simulated event bool MonsterFriendly(ScriptedPawn Other)
{
return Other != None && Other.AttitudeTo(User) == ATTITUDE_Friendly;
}
simulated event bool CheckSeekable(Pawn Other, Pawn FireAgent)
{
return (
Other != None
&&
(
FireAgent == None
^^
(
FastTrace(Other.Location)
&& Other != FireAgent
&& !Other.IsInState('Dying')
&&
(
!MonsterFriendly(ScriptedPawn(Other))
||
(
!Level.Game.bTeamGame
|| Other.PlayerReplicationInfo == None
|| FireAgent.PlayerReplicationInfo == None
|| Other.PlayerReplicationInfo.Team != FireAgent.PlayerReplicationInfo.Team
)
)
)
)
);
}
function BeginPlay()
{
if ( Owner == None )
return;
if ( Pawn(Owner) != None )
User = Pawn(Owner);
else
User = Pawn(Owner.Owner);
}
simulated function SetTarget(Pawn Other)
{
Seeking = Other;
}
simulated function WingedCrumb PathLocation()
{
if ( !bLayBreadcrumbs )
return None;
foreach RadiusActors(class'WingedCrumb', B, MaxPathDistance)
if ( FastTrace(Location, B.Location) )
return B;
return Spawn(class'WingedCrumb', self);
}
simulated function FindNavigationTarget()
{
while ( True )
{
if ( NavigationPath != None )
while ( VSize(Location - NavigationPath.Owner.Location) < 300 )
{
if ( WingedCrumb(NavigationPath.Next.Destination) == None )
break;
MyCrumb = WingedCrumb(NavigationPath.Next.Destination);
TempCrumb = NavigationPath;
NavigationPath = NavigationPath.Next;
TempCrumb.Destroy();
}
foreach RadiusActors(class'WingedCrumb', TargetWC, 768, Target.Location)
{
if ( TargetW == None || VSize(TargetWC.Location - TargetW.Location) < 256 )
TargetW = TargetWC;
}
if ( TargetW == None )
break;
NavigationPath = MyCrumb.FindPathToBreadcrumb(TargetW);
HomeTarget = NavigationPath.Next;
break;
}
}
simulated event Timer()
{
local Pawn P, Target;
local ut_spriteSmokePuff B;
local Actor A;
local AutoRocket AR;
local Vector WallNorm, WallLoc;
SetRotation(Rotator(Velocity));
A = WillHitWall(WallLoc, WallNorm);
if ( A != None && ( LevelInfo(A) != None || !CheckSeekable(Pawn(A), User) ) && ((VSize(WallLoc - Location) / VSize(Velocity * 0.1)) / 256) * MinHomeNormal() > (WallNorm dot Velocity) )
{
Velocity /= WallAvoidSlowdown;
Acceleration -= WallAvoidSpeed * 2 * (WallNorm dot Velocity) * WallNorm;
}
else if ( bFlock && Seeking == None )
{
foreach RadiusActors(class'AutoRocket', AR, FlockRadius)
{
HomeAt(AR, true);
}
}
if ( User != None )
bFoundUser = True;
MyCrumb = PathLocation();
if ( Seeking != None && !Seeking.IsInState('Dying') && CheckSeekable(Pawn(Seeking), User) )
{
HomeTarget = None;
if ( Navigation == NAV_Crumbs && ( FastTrace(Seeking.Location) && ( HomeTarget == None || !FastTrace(HomeTarget.Location) ) ) || ( HomeTarget != None && VSize(HomeTarget.Location - Location) < MinHomePathDistance && HomeTarget != Seeking ) )
FindNavigationTarget();
else if ( Navigation == NAV_Default && MyCrumb != None && ( !FastTrace(Seeking.Location) && ( HomeTarget == None || !FastTrace(HomeTarget.Location) ) ) || ( HomeTarget != None && VSize(HomeTarget.Location - Location) < MinHomePathDistance && HomeTarget != Seeking ) )
{
HomeTarget = Spawn(class'NavigationHelper');
NavigationHelper(HomeTarget).LoadPathToward(Seeking);
HomeTarget = NavigationHelper(HomeTarget).Helped(true);
}
else if ( FastTrace(Seeking.Location) )
HomeTarget = Seeking;
if ( HomeTarget != None )
{
HomeAt(HomeTarget);
if ( bShootAtTarget && PercentChance(ShootDensity) && ProjectileClass != None )
Spawn(ProjectileClass, Owner, '', Location + Vector(Rotation) * (CollisionRadius + ShootDistance + ProjectileClass.default.CollisionRadius) * ShootDistanceFactor);
}
}
else if ( PercentChance(TargetFindDensity) )
{
HomeTarget = None;
foreach RadiusActors(class'Pawn', P, TargetAcquiringRadius)
{
if ( Target == None || VSize(P.Location - Location) < VSize(Target.Location - Location) )
{
Target = P;
if ( CheckSeekable(Target, User) )
SetTarget(Target);
}
}
}
}
Code: Select all
//=============================================================================
// AutoRocket.
//=============================================================================
class AutoRocket expands UT_SeekingRocket;
var() float SeekAcceleration, SeekSpeed, TargetAcquiringRadius, WallAvoidSpeed, WallPredictionFactor, WallAvoidSlowdown, ShootDensity, ShootDistance, ShootDistanceFactor, MinHomePathDistance, MinWallAvoidNormal, TargetFindDensity, MaxPathDistance, FlockRadius, RotateRate, MinSeekAccel, SpaceFollowRadius;
var() bool bShootAtTarget, bIgnoreIgnorers, bFlock, bLayBreadcrumbs;
var() class<Actor> ProjectileClass;
var Pawn User;
var Actor HomeTarget;
var BreadcrumbPath NavigationPath, TempCrumb;
var bool bFoundUser;
var WingedCrumb B, MyCrumb, TargetWC, TargetW;
var int Slew;
var enum GusNavType
{
NAV_None,
NAV_Default,
NAV_Crumbs
}
Navigation;
replication
{
reliable if ( Role == ROLE_Authority )
User,
bFoundUser;
}
simulated function float DistanceTo(Vector Other)
{
return VSize(Other - Location);
}
simulated function Vector SpaceNormal()
{
local float x, y, z;
local Vector v, cv, norm;
for ( x = -1; x <= 1; x += 0.5 )
for ( y = -1; y <= 1; y += 0.5 )
for ( z = -1; z <= 1; z += 0.5 )
{
v.x = x;
v.y = y;
v.z = z;
Trace(v, norm, v * SpaceFollowRadius);
cv += v;
}
cv = Normal(cv);
Log("Traced"@cv@as spaciest normal!);
return cv;
}
simulated function float MinHomeNormal()
{
return 0.1 * MinWallAvoidNormal;
}
simulated event bool PercentChance(float Percentage)
{
return FRand() * 100 < Percentage;
}
simulated event Vector EstimateLocation(Actor Other)
{
if ( Other == None )
return Location;
return Other.Location + (Other.Velocity / VSize(Velocity)) * 0.5;
}
simulated event HomeAt(Actor Other, optional bool bRotateOnly)
{
local Vector Est;
Est = EstimateLocation(Other);
if ( bRotateOnly )
{
Velocity += Vector(Rotation) + (Est - Location) * RotateRate;
}
else
{
Acceleration += ((Est - Location) * SeekSpeed);
Velocity *= (SeekAcceleration / (Velocity dot (Est - Location))) + MinSeekAccel;
}
}
simulated event HomeToward(Vector HomeNormal, float Intensity, float Speeding)
{
Velocity += Vector(Rotation) + Normal(HomeNormal) * RotateRate * Intensity;
Acceleration += Normal(HomeNormal) * Speeding;
}
simulated event Actor WillHitWall(optional out Vector Location, optional out Vector OutNormal)
{
if ( Seeking != None && FastTrace(Seeking.Location) )
return none;
return Trace(Location, OutNormal, Self.Location + Velocity * WallPredictionFactor);
}
simulated event bool MonsterFriendly(ScriptedPawn Other)
{
return Other != None && Other.AttitudeTo(User) == ATTITUDE_Friendly;
}
simulated event bool CheckSeekable(Pawn Other, Pawn FireAgent)
{
return (
Other != None
&&
(
FireAgent == None
^^
(
FastTrace(Other.Location)
&& Other != FireAgent
&& !Other.IsInState('Dying')
&&
(
!MonsterFriendly(ScriptedPawn(Other))
||
(
!Level.Game.bTeamGame
|| Other.PlayerReplicationInfo == None
|| FireAgent.PlayerReplicationInfo == None
|| Other.PlayerReplicationInfo.Team != FireAgent.PlayerReplicationInfo.Team
)
)
)
)
);
}
function BeginPlay()
{
if ( Owner == None )
return;
if ( Pawn(Owner) != None )
User = Pawn(Owner);
else
User = Pawn(Owner.Owner);
}
simulated function SetTarget(Pawn Other)
{
Seeking = Other;
}
simulated function WingedCrumb PathLocation()
{
if ( !bLayBreadcrumbs )
return None;
foreach RadiusActors(class'WingedCrumb', B, MaxPathDistance)
if ( FastTrace(Location, B.Location) )
return B;
return Spawn(class'WingedCrumb', self);
}
simulated function FindNavigationTarget()
{
while ( True )
{
if ( NavigationPath != None )
while ( VSize(Location - NavigationPath.Owner.Location) < 300 )
{
if ( WingedCrumb(NavigationPath.Next.Destination) == None )
break;
MyCrumb = WingedCrumb(NavigationPath.Next.Destination);
TempCrumb = NavigationPath;
NavigationPath = NavigationPath.Next;
TempCrumb.Destroy();
}
foreach RadiusActors(class'WingedCrumb', TargetWC, 768, Target.Location)
{
if ( TargetW == None || VSize(TargetWC.Location - TargetW.Location) < 256 )
TargetW = TargetWC;
}
if ( TargetW == None )
break;
NavigationPath = MyCrumb.FindPathToBreadcrumb(TargetW);
HomeTarget = NavigationPath.Next;
break;
}
}
simulated event Timer()
{
local Pawn P, Target;
local ut_spriteSmokePuff B;
local Actor A;
local AutoRocket AR;
local Vector WallNorm, WallLoc;
HomeToward(SpaceNormal(), 0.5, 0);
SetRotation(Rotator(Velocity));
A = WillHitWall(WallLoc, WallNorm);
if ( A != None && ( LevelInfo(A) != None || !CheckSeekable(Pawn(A), User) ) && ((VSize(WallLoc - Location) / VSize(Velocity * 0.1)) / 256) * MinHomeNormal() > (WallNorm dot Velocity) )
{
Velocity /= WallAvoidSlowdown;
Acceleration -= WallAvoidSpeed * 2 * (WallNorm dot Velocity) * WallNorm;
}
else if ( bFlock && Seeking == None )
{
foreach RadiusActors(class'AutoRocket', AR, FlockRadius)
{
HomeAt(AR, true);
}
}
if ( User != None )
bFoundUser = True;
MyCrumb = PathLocation();
if ( Seeking != None && !Seeking.IsInState('Dying') && CheckSeekable(Pawn(Seeking), User) )
{
HomeTarget = None;
if ( Navigation == NAV_Crumbs && ( FastTrace(Seeking.Location) && ( HomeTarget == None || !FastTrace(HomeTarget.Location) ) ) || ( HomeTarget != None && VSize(HomeTarget.Location - Location) < MinHomePathDistance && HomeTarget != Seeking ) )
FindNavigationTarget();
else if ( Navigation == NAV_Default && MyCrumb != None && ( !FastTrace(Seeking.Location) && ( HomeTarget == None || !FastTrace(HomeTarget.Location) ) ) || ( HomeTarget != None && VSize(HomeTarget.Location - Location) < MinHomePathDistance && HomeTarget != Seeking ) )
{
HomeTarget = Spawn(class'NavigationHelper');
NavigationHelper(HomeTarget).LoadPathToward(Seeking);
HomeTarget = NavigationHelper(HomeTarget).Helped(true);
}
else if ( FastTrace(Seeking.Location) )
HomeTarget = Seeking;
if ( HomeTarget != None )
{
HomeAt(HomeTarget);
if ( bShootAtTarget && PercentChance(ShootDensity) && ProjectileClass != None )
Spawn(ProjectileClass, Owner, '', Location + Vector(Rotation) * (CollisionRadius + ShootDistance + ProjectileClass.default.CollisionRadius) * ShootDistanceFactor);
}
}
else if ( PercentChance(TargetFindDensity) )
{
HomeTarget = None;
foreach RadiusActors(class'Pawn', P, TargetAcquiringRadius)
{
if ( Target == None || VSize(P.Location - Location) < VSize(Target.Location - Location) )
{
Target = P;
if ( CheckSeekable(Target, User) )
SetTarget(Target);
}
}
}
}
Without understanding of complete intention of code I guess that self.Instigator would be a better choice than self.Owner.Gustavo6046 wrote:Code: Select all
class AutoRocket expands UT_SeekingRocket; ... function BeginPlay() { if ( Owner == None ) return; if ( Pawn(Owner) != None ) User = Pawn(Owner); else User = Pawn(Owner.Owner); }
From the context user is used I guess that Gustavo wants to know who has emitted the projectile. AFAIK Projectiles have no owner, but Instigator is inherited automatically on spawning a Projectile.sektor2111 wrote:preventing Instigator