Add aim assist

This commit is contained in:
Sara Montecino 2022-11-14 22:28:08 -08:00
parent 27edeb0f0c
commit f551802cef
14 changed files with 138 additions and 17 deletions

View File

@ -51,6 +51,7 @@ bUseSplitscreen=False
+Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ")
+Profiles=(Name="Pickup",CollisionEnabled=QueryAndPhysics,bCanModify=True,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap),(Channel="Character",Response=ECR_Overlap)),HelpMessage="Item to pickup")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Character")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Enemy")
-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall")
-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn")
-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -4,9 +4,12 @@
#include "BasePawn.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/FloatingPawnMovement.h"
#include "DrawDebugHelpers.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Util.h"
#define LogInfo(Msg) Util::log_info(TEXT("ABasePawn"), Msg)
#define LogError(Msg) Util::log_error(TEXT("ABasePawn"), Msg)
// Sets default values
ABasePawn::ABasePawn(const FObjectInitializer &object_initializer):
@ -147,12 +150,30 @@ void ABasePawn::shoot()
{
if (current_ammo > 0)
{
FVector player_location = player_mesh->GetComponentLocation();
const float y = yaw.calculate_yaw();
const FRotator rotator(0, y, 0);
FVector forward = FRotationMatrix(rotator).GetUnitAxis(EAxis::X) * 100;
const FVector player_location = get_location();
FRotator rotator(0, yaw.calculate_yaw(), 0);
if (use_aim_assist)
{
LogInfo(FString::Printf(TEXT("Yaw %f"), rotator.Yaw));
const float y_offset = aim_assist(player_location, rotator);
if (y_offset != 0)
{
rotator.Yaw = y_offset;
}
LogInfo(FString::Printf(TEXT("Offset %f"), y_offset));
FVector line_end = FVector(5000, 0, 0);
FVector aim_line_end = rotator.RotateVector(line_end);
// DrawDebugLine(
// GetWorld(),
// player_location,
// aim_line_end + player_location,
// FColor::Red,
// true
// );
}
FVector spawn_location = player_location + forward;
FVector forward = FRotationMatrix(rotator).GetUnitAxis(EAxis::X);
FVector spawn_location = player_location + (forward * 100);
FActorSpawnParameters spawnParameters;
spawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
spawnParameters.Owner = this;
@ -169,6 +190,81 @@ void ABasePawn::shoot()
}
}
/**
* Calculate the yaw angle needed to hit the nearest enemy target.
*
* @return Yaw angle offset.
*/
float ABasePawn::aim_assist(const FVector start, const FRotator rotator)
{
/*
* Create trace end based on start location and given rotator.
*/
FVector trace = start + FVector(10000, 0, 0);
trace = rotator.RotateVector(trace);
/*
* Run box trace for enemy targets.
*/
FHitResult out_hit;
const bool succeeded = UKismetSystemLibrary::SphereTraceSingle(
GetWorld(),
start,
trace,
aim_assist_distance,
ETraceTypeQuery::TraceTypeQuery3, // "Enemy" trace channel
false,
TArray<AActor*>(),
EDrawDebugTrace::Type::None,
out_hit,
true,
FLinearColor::Green,
FLinearColor::Green,
0
);
/*
* No enemies were within range.
*/
if (!succeeded)
{
return 0;
}
ABasePawn* enemy_pawn = Cast<ABasePawn>(out_hit.Actor);
/*
* Bad setup. We should only be hitting pawns.
*/
if (!enemy_pawn)
{
LogError("Aim assist trace hit non-pawn");
return 0;
}
const FVector enemy_vector = enemy_pawn->get_location() - start;
const FRotator new_rotator = enemy_vector.Rotation();
//FVector target_vector = FVector(enemy_vector.X, enemy_vector.Y, 0);
//target_vector.Normalize();
//FVector actual_vector = FVector(trace.X, trace.Y, 0) - start;
//actual_vector.Normalize();
//const float angle_between = UKismetMathLibrary::DegAcos(FVector::DotProduct(actual_vector, target_vector));
//const FVector cross = FVector::CrossProduct(actual_vector, target_vector);
//if (cross.Z > 0)
//{
// return angle_between;
//}
//else if (cross.Z < 0)
//{
// return angle_between * -1;
//}
//return 0;
return new_rotator.Yaw;
}
void ABasePawn::handle_death()
{
/*

View File

@ -112,11 +112,20 @@ protected:
float fire_rate_s;
/**
* Max ammor.
* Max ammo.
*/
UPROPERTY(EditAnywhere, Category = "Attack")
int32 max_ammo;
/**
*
*/
UPROPERTY(EditAnywhere, Category = "Attack")
float aim_assist_distance;
UPROPERTY(EditAnywhere, Category = "Attack")
bool use_aim_assist;
/**
* Shooting enabled;
*/
@ -146,4 +155,7 @@ protected:
* Spawned death effect actor.
*/
AActor* death_effect;
private:
float aim_assist(const FVector start, const FRotator rotator);
};

View File

@ -38,14 +38,24 @@ void AEnemyAIController::Tick(float delta_time)
else
{
FVector target_location = president->get_location();
FVector current_location = Cast<ABasePawn>(GetPawn())->get_location();
FVector between = target_location - current_location;
between = FVector(between.X, between.Y, 0);
between.Normalize();
FVector extended = (between * overshoot_multiplier) + target_location;
const ABasePawn* local_pawn = Cast<ABasePawn>(GetPawn());
if (local_pawn)
{
FVector current_location = local_pawn->get_location();
FVector between = target_location - current_location;
between = FVector(between.X, between.Y, 0);
between.Normalize();
FVector extended = (between * overshoot_multiplier) + target_location;
MoveToLocation(extended);
current_state = state_t::moving;
}
else
{
// This will be cleaned up shortly.
current_state = state_t::dead;
}
MoveToLocation(extended);
current_state = state_t::moving;
}
break;
case state_t::moving:
@ -95,7 +105,7 @@ ABasePawn* AEnemyAIController::get_president() const
if (!found)
{
LogError("No president found!");
// LogError("No president found!");
}
return found;

View File

@ -43,6 +43,7 @@ private:
wait,
target,
moving,
dead
};
ABasePawn* get_president() const;

View File

@ -14,6 +14,10 @@ xShoot from any direction
xShoot at continuous rate when holding shoot button
xAdd player damage
xAdd player ammo
xAdd auto aim
Add art
- Car models
- Street shader
Add win condition
- Time based. Keep president alive until he reaches destination.
Add HUD UI
@ -21,9 +25,6 @@ Add menu
Add local multiplayer
x Blueprint
- C++
Add art
- Car models
- Street shader
Add sounds
Add juice
Add muzzle on shoot