Page 5 of 5

Re: Auto-Guiding Rockets -- [WIP]

Posted: Sun Mar 19, 2017 9:54 pm
by Terraniux
any update on this?

Re: Auto-Guiding Rockets -- [WIP]

Posted: Mon Mar 20, 2017 7:34 am
by sektor2111
Is in the same stage as Air Smashing mutator, Tag Games, weapon Jump Node, etc. more exactly a work in progress...

Re: Auto-Guiding Rockets -- [WIP]

Posted: Tue Mar 21, 2017 8:24 pm
by Gustavo6046
Nope, this is actually a finished project. The auto-rocket is good enough. I forgot to post the last verion 'w'

Code:

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);
			}
		}
	}
}
Fixing topic name.

EDIT: After another topic skim, maybe it's time to release a definitive last release, without dodging walls whenever target is there (as Nelsona said -- I probably didn't understand at the time lol), and adding small spacious normal calculation.

EDIT 2: My flawed try:

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);
			}
		}
	}
}

Re: Auto-Guiding Rockets -- [WIP]

Posted: Tue Mar 21, 2017 10:58 pm
by Barbie
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);
}
Without understanding of complete intention of code I guess that self.Instigator would be a better choice than self.Owner.

Re: [Auto-Guiding Rockets] -- Beta 1

Posted: Tue Mar 21, 2017 11:35 pm
by sektor2111
You should look at PeaceRocket and use that thing as priority but preventing Instigator. If None Pawn is found do roam around.

Your old mod was based on a single concern, rocket avoiding walls and ignoring pawns being busy to track walls and nothing more.

Re: [Auto-Guiding Rockets] -- Beta 1

Posted: Wed Mar 22, 2017 3:30 am
by Barbie
sektor2111 wrote:preventing Instigator
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.

Re: [Auto-Guiding Rockets] -- Beta 1

Posted: Wed Mar 22, 2017 7:16 am
by sektor2111
If he will quit blabbering with brain ideas about being programmer, and just using simple way, coding like a low level coder (it's not a shame - it's learning), probably will Never Fail. What is about ? USING STUPID LOW LEVEL LOGS, when you are using log("Owner ="@Owner) and log("Instigator ="@Instigator) might be helpful in figuring if that section is being ever executed and what content runs there. Else I see some "scientific" functions which I think have useless content just because they weren't checked if have been ever called. EPIC used LOGS - even forgetting to remove some of them. Logs are not painful, they do help a lot in clarifications about certain stuff if it's running or not - else the guess work is not the right way. There are a lot of simulated functions which I don't think are necessary like that. Client needs to know where is going rocket and not processing values from it. It needs information about spawning, direction changed, speed, and exploding. By checking a default good projectile eg. UT_SeekingRocket you'll see that not everything has to be a "simulated function". Again, LOGS are real tutorials if are not ignored.

I used Logs in 90% of things which I wrote and that's why they do work, because I've CHECKED them. To not forget for such a toy, if rocket has a job started function should not continue other dumb executions. If you have a target, go get it and forget stupid walls around.