C++ UAnimInstance Examples
C++ UAnimInstance Examples
UAnimInstance::Montage_Play Examples
These are the top rated real world C++ (Cpp) examples of UAnimInstance::Montage_Play extracted from open source projects. You can rate examples to help us
improve the quality of examples.
Link: https://cpp.hotexamples.com/examples/-/UAnimInstance/Montage_Play/cpp-uaniminstance-montage_play-method-examples.html
EXAMPLE #1
#include "MobileOpenCV.h"
#include "MobileOpenCVCharacter.h"
#include "MobileOpenCVProjectile.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/InputSettings.h"
//////////////////////////////////////////////////////////////////////////
// AMobileOpenCVCharacter
AMobileOpenCVCharacter::AMobileOpenCVCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
//////////////////////////////////////////////////////////////////////////
// Input
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AMobileOpenCVCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AMobileOpenCVCharacter::LookUpAtRate);
}
void AMobileOpenCVCharacter::OnFire()
{
// try and fire a projectile
if (ProjectileClass != NULL)
{
const FRotator SpawnRotation = GetControlRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle pos ition
const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
if (ScaledDelta.X != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.X * BaseTurnRate;
AddControllerYawInput(Value);
}
if (ScaledDelta.Y != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.Y* BaseTurnRate;
AddControllerPitchInput(Value);
}
TouchItem.Location = Location;
}
TouchItem.Location = Location;
}
}
}
}
#include "MurphysLaw.h"
#include "MurphysLawCharacter.h"
#include "../Network/MurphysLawPlayerState.h"
#include "../Weapon/MurphysLawBaseWeapon.h"
#include "../HUD/MurphysLawHUDWidget.h"
#include "../Components/MurphysLawInventoryComponent.h"
#include "../Menu/MurphysLawInGameMenu.h"
#include "../Network/MurphysLawPlayerController.h"
#include "../AI/MurphysLawAIController.h"
#include "WidgetComponent.h"
#include "Blueprint/UserWidget.h"
#include "Animation/AnimInstance.h"
#include "UnrealNetwork.h"
#include "../DamageZone/MurphysLawDamageZone.h"
#include "../Environnement/ExplosiveBarrel/MurphysLawExplosiveBarrel.h"
#include "MurphysLawNameplateWidget.h"
#include "Kismet/KismetMathLibrary.h"
#include "../Network/MurphysLawGameMode.h"
#include "../Network/MurphysLawGameState.h"
#include <MurphysLaw/Interface/MurphysLawIController.h>
#include <MurphysLaw/Utils/MurphysLawUtils.h>
//////////////////////////////////////////////////////////////////////////
// AMurphysLawCharacter
AMurphysLawCharacter::AMurphysLawCharacter()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a SceneComponent
SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
SceneComponent->AttachParent = GetCapsuleComponent();
SceneComponent->RelativeLocation = FVector(-20, 0, 120);
// Create a CharacterNameplate
CharacterNameplate = CreateDefaultSubobject<UWidgetComponent>(TEXT("CharacterNameplate"));
CharacterNameplate->AttachParent = SceneComponent;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
GetMesh()->SetCollisionObjectType(ECC_PhysicsBody);
GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Ignore);
GetMesh()->SetCollisionResponseToAllChannels(ECR_Block);
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
// Movement related
IsCrouched = false;
GetCharacterMovement()->GetNavAgentPropertiesRef().bCanCrouch = true;
ConfigureMovement(false); // Configure as human to see human related values in editor
// Spawning settings
SpawnCollisionHandlingMethod = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
// Indicates to the server what properties of the object to replicate on the clients
void AMurphysLawCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty> &OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMurphysLawCharacter, CurrentWeaponIndex);
DOREPLIFETIME(AMurphysLawCharacter, CurrentHealth);
DOREPLIFETIME(AMurphysLawCharacter, Dead);
DOREPLIFETIME(AMurphysLawCharacter, TeamBodyMeshColor);
DOREPLIFETIME(AMurphysLawCharacter, TeamMaskMeshColor);
}
void AMurphysLawCharacter::BeginPlay()
{
Super::BeginPlay();
// AI settings ressources
if (AIControllerClass == nullptr) ShowWarning("No AIController class assigned to MurphysLawCharacter");
EquipFirstWeapon();
// Set the current health of the character here in case the value has been overriden in a subclass
CurrentHealth = MaxHealth;
if (NewController != nullptr)
{
// Update settings of movement component to allow "natural" movement for bots
const bool ConfigureAsBot = NewController->IsA<AAIController>();
ConfigureMovement(ConfigureAsBot);
}
}
if (FirstPersonCameraComponent != nullptr)
{
// Gets the camera angle for the mini-map (to rotate it as the player rotates the player)
Bearing = FirstPersonCameraComponent->GetComponentRotation().Yaw;
}
// If the character is not moving, we deactivate his running so he doesn't lose stamina
if (!IsMoving)
{
SetIsRunning(false);
}
if (Role == ROLE_Authority)
{
TakeDamage(Damage, CollisionDamageEvent, GetController(), this);
}
}
if (Role == ROLE_Authority)
{
TakeDamage(Damage, CollisionDamageEvent, GetController(), this);
}
}
HighestZ = 0;
SetIsInAir(false);
}
/** [PS] DO NOT REMOVE - Trying to make it work */
// UKismetMathLibrary::BreakRotator(PlayerRot, X, Y, Z);
// FRotator Result = UKismetMathLibrary::MakeRotator(0.f, 0.f, Z);
// //UKismetMathLibrary::BreakRotIntoAxes(PlayerRot, X, Y, Z);
//
// SceneComponent->SetWorldLocationAndRotation(sceneLocation, Result);
// /*SceneComponent->SetWorldRotation(FRotationMatrix::MakeFromXY(X, Y).ToQuat());*/
//}
}
//////////////////////////////////////////////////////////////////////////
// Input
void AMurphysLawCharacter::Aim()
{
if (HasWeaponEquipped())
{
FirstPersonCameraComponent->FieldOfView = GetEquippedWeapon()->AimFactor;
IsCharacterAiming = true;
}
}
void AMurphysLawCharacter::StopAiming()
{
if (HasWeaponEquipped())
{
FirstPersonCameraComponent->FieldOfView = DefaultAimFactor;
IsCharacterAiming = false;
}
}
void AMurphysLawCharacter::Run()
{
SetIsRunning(true);
}
void AMurphysLawCharacter::StopRunning()
{
SetIsRunning(false);
}
///////////////////////////////////////////////////////////////////////////
#pragma endregion
// Refills ammos for the collected weapon or collects it if character didn't have it yet
void AMurphysLawCharacter::CollectWeapon(class AMurphysLawBaseWeapon* Weapon)
{
Inventory->CollectWeapon(Weapon);
// If the equipped weapon is empty when picking up the weapon and it's the same, it auto-reloads
if (HasWeaponEquipped()
&& GetEquippedWeapon()->IsOfSameType(Weapon)
&& ShouldReload())
{
Reload();
}
}
bool AMurphysLawCharacter::CanPlayerMove()
{
bool CanMove = true;
AMurphysLawBaseWeapon* CurrentWeapon = GetEquippedWeapon();
if (CurrentWeapon)
CanMove = !(IsCrouched && CurrentWeapon->IsReloading);
return CanMove;
}
// Show HUD
auto PlayerController = Cast<AMurphysLawPlayerController>(GetController());
if(PlayerController != nullptr)
PlayerController->ChangeHUDVisibility(ESlateVisibility::Visible);
}
}
void AMurphysLawCharacter::EquipFirstWeapon()
{
CurrentWeaponIndex = NO_WEAPON_VALUE;
// Determines the current weapon of the character
for (int32 i = 0; i < Inventory->NumberOfWeaponInInventory && CurrentWeaponIndex == NO_WEAPON_VALUE; ++i)
{
AMurphysLawBaseWeapon* Weapon = Inventory->GetWeapon(i);
if (Weapon != nullptr)
{
// The first available weapon in the inventory become the current weapon
CurrentWeaponIndex = i;
Weapon->SetActorHiddenInGame(false);
Inventory->GetFullMeshWeapon(i)->SetActorHiddenInGame(false);
}
}
}
void AMurphysLawCharacter::Fire()
{
// check if we have a weapon equipped
if (HasWeaponEquipped())
{
// if the weapon has been able to fire
if (GetEquippedWeapon()->Fire(this))
{
// Stop the character from running
SetIsRunning(false);
// We reload the weapon if it is empty and we have bullets left in our inventory
if (ShouldReload())
{
Reload();
}
}
}
// Remove self from query potential results since we are the first to collide with the ray
FCollisionQueryParams RayQueryParams;
RayQueryParams.AddIgnoredActor(this);
FHitResult CollisionResult;
bool HasHit = GetWorld()->LineTraceSingleByObjectType(CollisionResult, CollisionRayStart, CollisionRayEnd, CollisionObjectQueryParams, RayQueryParams);
if (HasHit)
{
// Simple damage amount considering the distance to the target depending on the bone hit
float DeliveredDamage = GetDeliveredDamage(CollisionResult);
// If the actor we hit is a hittable actor and an enemy, we have at least one hit so we'll show the Hit Marker
if (IsHittableActor(CollisionResult.GetActor()) && !MurphysLawUtils::IsInSameTeam(CollisionResult.GetActor(), this))
{
AtLeastOneHit = true;
}
if (Role == ROLE_Authority)
{
CollisionResult.GetActor()->TakeDamage(DeliveredDamage, CollisionDamageEvent, GetController(), this);
}
else
{
Server_TransferDamage(CollisionResult.GetActor(), DeliveredDamage, CollisionDamageEvent, GetController(), this);
}
}
}
if (BoneName == SOCKET_HEAD)
DeliveredDamage *= FACTOR_HEADSHOT;
else if (BoneName == SOCKET_SPINE)
DeliveredDamage *= FACTOR_CHESTSHOT;
return DeliveredDamage;
}
bool AMurphysLawCharacter::Server_TransferDamage_Validate(class AActor * DamagedActor, const float DamageAmount, struct FDamageEvent const & DamageEvent, class AController *
EventInstigator, class AActor * DamageCauser) { return true; }
void AMurphysLawCharacter::Server_TransferDamage_Implementation(class AActor * DamagedActor, const float DamageAmount, struct FDamageEvent const & DamageEvent, class AController *
EventInstigator, class AActor * DamageCauser)
{
DamagedActor->TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}
float AMurphysLawCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const & DamageEvent, class AController * EventInstigator, AActor * DamageCauser)
{
float ActualDamage = 0.f;
return ActualDamage;
}
void AMurphysLawCharacter::OnReceiveAnyDamage(float Damage, const UDamageType* DamageType, AController* InstigatedBy, AActor* DamageCauser)
{
// If it was friendly fire, we do not damage our teammate, except if it is from an explosive
if (IsFriendlyFire(InstigatedBy) && !DamageCausedByExplosive(DamageCauser))
{
return;
}
bool AMurphysLawCharacter::Server_TakeDamage_Validate(float DamageAmount, struct FDamageEvent const & DamageEvent, class AController * EventInstigator, AActor * DamageCauser) { return
true; }
void AMurphysLawCharacter::Server_TakeDamage_Implementation(float DamageAmount, struct FDamageEvent const & DamageEvent, class AController * EventInstigator, AActor * DamageCauser)
{
TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}
if (GameState)
GameState->PlayerKilledTeammate(GetPlayerState()->GetTeam() == AMurphysLawGameMode::TEAM_A);
}
else
{
// If the player was killed by somebody else
if (InstigatedBy)
{
DeathMessage = FString::Printf(TEXT("%s was killed by %s"), *GetHumanReadableName(), *InstigatedBy->GetHumanReadableName());
if (GameState)
{
if (GetPlayerState())
{
GameState->PlayerWasKilled(OtherPlayerState->GetTeam() == AMurphysLawGameMode::TEAM_A);
}
else
ShowError("PlayerState is null");
}
else
ShowError("GameState is null");
}
}
// Returns true if the controller inflicting the damage is in the same team, false otherwise
bool AMurphysLawCharacter::IsFriendlyFire(class AController* OtherController) const
{
// If the controller of the actor that hit me is a player controller
auto OtherPlayerController = Cast<AMurphysLawPlayerController>(OtherController);
if (OtherPlayerController && OtherPlayerController != GetController())
{
// And if we both have a player state
auto OtherPlayerState = Cast<AMurphysLawPlayerState>(OtherPlayerController->PlayerState);
if (OtherPlayerState && GetPlayerState())
{
// We check if we are on the same team
return OtherPlayerState->GetTeam() == GetPlayerState()->GetTeam();
}
}
return false;
}
#pragma endregion
// Called when the player press a key to change his character's weapon
void AMurphysLawCharacter::EquipWeapon(int32 Index)
{
// Checks if the index passed in parameter is within the boundaries of our Inventory
if (Index >= Inventory->NumberOfWeaponInInventory) return;
// If the server modifies the value of the property, it is sent to the clients automatically
if (Role == ROLE_Authority)
{
Server_ChangeCurrentWeapon_Implementation(Index);
}
else
{
// If a client wants to modify the value, it has to send a request to the server
Server_ChangeCurrentWeapon(Index);
}
}
void AMurphysLawCharacter::ToggleCrouch()
{
// If the character is not crouched
if (CanCrouch())
{
IsCrouched = true;
Crouch();
// Returns true if the weapon hold by the character should be reloaded, false otherwise
bool AMurphysLawCharacter::ShouldReload() const
{
return HasWeaponEquipped()
&& !GetEquippedWeapon()->IsReloading
&& GetEquippedWeapon()->GetNumberOfAmmoLeftInMagazine() <= 0
&& GetEquippedWeapon()->GetNumberOfAmmoLeftInInventory() > 0;
}
if (Role == ROLE_Authority)
{
ValidTeamBodyMeshColor = true;
ValidTeamMaskMeshColor = true;
ApplyMeshTeamColor();
}
}
void AMurphysLawCharacter::OnRep_TeamBodyMeshColor()
{
ValidTeamBodyMeshColor = true;
ApplyMeshTeamColor();
}
void AMurphysLawCharacter::OnRep_TeamMaskMeshColor()
{
ValidTeamMaskMeshColor = true;
ApplyMeshTeamColor();
}
void AMurphysLawCharacter::ApplyMeshTeamColor()
{
// Put color on meshes
if (ValidTeamBodyMeshColor && ValidTeamMaskMeshColor)
{
/* Get references to mesh material to be able to color them. */
UMaterialInstanceDynamic* ShaderMeshBody = GetMesh()->CreateDynamicMaterialInstance(0);
UMaterialInstanceDynamic* ShaderMeshArms = GetMesh1P()->CreateDynamicMaterialInstance(0);
checkf(ShaderMeshBody != nullptr && ShaderMeshArms != nullptr, TEXT("Unable to find first material on character"));
ShaderMeshArms->SetVectorParameterValue(MATERIAL_PARAM_TEAM_COLOR_CLOTHES, TeamBodyMeshColor);
ShaderMeshArms->SetVectorParameterValue(MATERIAL_PARAM_TEAM_COLOR_MASK, TeamMaskMeshColor);
ShaderMeshBody->SetVectorParameterValue(MATERIAL_PARAM_TEAM_COLOR_CLOTHES, TeamBodyMeshColor);
ShaderMeshBody->SetVectorParameterValue(MATERIAL_PARAM_TEAM_COLOR_MASK, TeamMaskMeshColor);
}
}
Super::Jump();
UpdateStaminaLevel(-JumpStaminaDecayAmount);
}
// Make sure the value stays between 0 and its maximum value
CurrentStamina = UKismetMathLibrary::FClamp(GetCurrentStaminaLevel(), 0.f, GetMaxStaminaLevel());
}
// To make sure all the weapons are teleported aswell as the character
Inventory->AttachAllWeaponsToOwner();
}
EXAMPLE #3
#include "FP_FirstPerson.h"
#include "FP_FirstPersonCharacter.h"
#include "Animation/AnimInstance.h"
//////////////////////////////////////////////////////////////////////////
// AFP_FirstPersonCharacter
AFP_FirstPersonCharacter::AFP_FirstPersonCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
WeaponRange = 5000.0f;
WeaponDamage = 500000.0f;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
//////////////////////////////////////////////////////////////////////////
// Input
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AFP_FirstPersonCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AFP_FirstPersonCharacter::LookUpAtRate);
}
void AFP_FirstPersonCharacter::OnFire()
{
// Play a sound if there is one
if (FireSound != NULL)
{
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
}
// Now send a trace from the end of our gun to see if we should hit anything
APlayerController* PlayerController = Cast<APlayerController>(GetController());
// Calculate the direction of fire and the start location for trace
FVector CamLoc;
FRotator CamRot;
PlayerController->GetPlayerViewPoint(CamLoc, CamRot);
const FVector ShootDir = CamRot.Vector();
// Adjust trace so there is nothing blocking the ray between the camera and the pawn, and calculate distance from adjusted start
StartTrace = StartTrace + ShootDir * ((GetActorLocation() - StartTrace) | ShootDir);
}
// If the index matches the start index and we didn't process any movement we assume we want to fire
if ((FingerIndex == TouchItem.FingerIndex) && (TouchItem.bMoved == false))
{
OnFire();
}
FHitResult Hit(ForceInit);
GetWorld()->LineTraceSingleByChannel(Hit, StartTrace, EndTrace, COLLISION_WEAPON, TraceParams);
return Hit;
}
EXAMPLE #4
#include "ShaderPluginDemo.h"
#include "ShaderPluginDemoCharacter.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/InputSettings.h"
#include "Components/SceneCaptureComponent2D.h"
#include "Engine/TextureRenderTarget2D.h"
#include "../Public/HighResScreenshot.h"
//////////////////////////////////////////////////////////////////////////
// AShaderPluginDemoCharacter
AShaderPluginDemoCharacter::AShaderPluginDemoCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(-39.56f, 1.75f, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
/*RenderTargetL = CreateDefaultSubobject<UTextureRenderTarget2D>(TEXT("RenderTarget_L"));
RenderTargetL->InitAutoFormat(1024, 1024);
RenderTargetL->AddressX = TA_Wrap;
RenderTargetL->AddressY = TA_Wrap;*/
/*RenderTargetR = CreateDefaultSubobject<UTextureRenderTarget2D>(TEXT("RenderTarget_R"));
RenderTargetR->InitAutoFormat(1024, 1024);
RenderTargetR->AddressX = TA_Wrap;
RenderTargetR->AddressY = TA_Wrap;*/
StereoCameraComponentL = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("StereoCameraComponent_L"));
//StereoCameraComponentL->FOVAngle = 90.f;
StereoCameraComponentL->AttachParent = GetCapsuleComponent();
StereoCameraComponentL->RelativeLocation = FVector(0.f, 0.f, 70.f); // Position the camera
StereoCameraComponentL->TextureTarget = RenderTargetL;
StereoCameraComponentL->bCaptureEveryFrame = false;
StereoCameraComponentR = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("StereoCameraComponent_R"));
StereoCameraComponentR->AttachParent = GetCapsuleComponent();
StereoCameraComponentR->RelativeLocation = FVector(0.f, 30.f, 70.f); // Position the camera
StereoCameraComponentR->TextureTarget = RenderTargetR;
StereoCameraComponentR->bCaptureEveryFrame = false;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
Mesh1P->RelativeRotation = FRotator(1.9f, -19.19f, 5.2f);
Mesh1P->RelativeLocation = FVector(-0.5f, -4.4f, -155.7f);
FP_MuzzleLocation = CreateDefaultSubobject<USceneComponent>(TEXT("MuzzleLocation"));
FP_MuzzleLocation->AttachTo(FP_Gun);
FP_MuzzleLocation->SetRelativeLocation(FVector(0.2f, 48.4f, -10.6f));
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
//ShaderPluginDemo variables
EndColorBuildup = 0;
EndColorBuildupDirection = 1;
PixelShaderTopLeftColor = FColor::Green;
ComputeShaderSimulationSpeed = 1.0;
ComputeShaderBlend = 0.5f;
ComputeShaderBlendScalar = 0;
TotalElapsedTime = 0;
}
//Since we need the featurelevel, we need to create the shaders from beginplay, and not in the ctor.
void AShaderPluginDemoCharacter::BeginPlay()
{
// Call the base class
Super::BeginPlay();
FP_Gun->AttachTo(Mesh1P, TEXT("GripPoint"), EAttachLocation::SnapToTargetIncludingScale, true); //Attach gun mesh component to Skeleton, doing it here because the skelton is
not yet created in the constructor
if (PixelShading)
{
delete PixelShading;
}
if (ComputeShading)
{
delete ComputeShading;
}
}
//Saving functions
void AShaderPluginDemoCharacter::SavePixelShaderOutput()
{
PixelShading->Save();
}
void AShaderPluginDemoCharacter::SaveComputeShaderOutput()
{
ComputeShading->Save();
}
TotalElapsedTime += DeltaSeconds;
if (PixelShading)
{
EndColorBuildup = FMath::Clamp(EndColorBuildup + DeltaSeconds * EndColorBuildupDirection, 0.0f, 1.0f);
if (EndColorBuildup >= 1.0 || EndColorBuildup <= 0)
{
EndColorBuildupDirection *= -1;
}
if (ComputeShading)
{
ComputeShading->ExecuteComputeShader(TotalElapsedTime);
InputTexture = ComputeShading->GetTexture(); //This is the output texture from the compute shader that we will pass to the pixel shader.
}
FReadSurfaceDataFlags ReadPixelFlags(RCM_UNorm);
ReadPixelFlags.SetLinearToGamma(true);
TArray<FColor> OutBMP;
RTResource->ReadPixels(OutBMP, ReadPixelFlags);
FIntRect SourceRect;
FString ResultPath;
FHighResScreenshotConfig& HighResScreenshotConfig = GetHighResScreenshotConfig();
if (HighResScreenshotConfig.SaveImage(FPaths::GameSavedDir() + TEXT("Screenshots/") + Filename, OutBMP, DestSize, &ResultPath) && debug) {
UE_LOG(LogFPChar, Warning, TEXT("Screenshot saved to: %s"), *ResultPath);
}
void AShaderPluginDemoCharacter::OnFire()
{
//Try to set a texture to the object we hit!
FHitResult HitResult;
FVector StartLocation = FirstPersonCameraComponent->GetComponentLocation();
FRotator Direction = FirstPersonCameraComponent->GetComponentRotation();
FVector EndLocation = StartLocation + Direction.Vector() * 10000;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(this);
if (NULL != HitActor)
{
HitActor->GetComponents<UStaticMeshComponent>(StaticMeshComponents);
for (int32 i = 0; i < StaticMeshComponents.Num(); i++)
{
UStaticMeshComponent* CurrentStaticMeshPtr = StaticMeshComponents[i];
CurrentStaticMeshPtr->SetMaterial(0, MaterialToApplyToClickedObject);
UMaterialInstanceDynamic* MID = CurrentStaticMeshPtr->CreateAndSetMaterialInstanceDynamic(0);
UTexture* CastedRenderTarget = Cast<UTexture>(RenderTarget);
MID->SetTextureParameterValue("InputTexture", CastedRenderTarget);
}
}
}
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AShaderPluginDemoCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AShaderPluginDemoCharacter::LookUpAtRate);
}
EXAMPLE #5
#include "Totem.h"
#include "TotemCharacter.h"
#include "TotemProjectile.h"
#include "Animation/AnimInstance.h"
#include "Engine.h"
#include "Cyclone.h"
#include "QuakeAttack.h"
#include "UnrealNetwork.h"
#include "TotemPlayerState.h"
#include "TotemPlayerController.h"
#include "TotemGameMode.h"
#include "TerrainManager.h"
#include "TotemGameState.h"
//////////////////////////////////////////////////////////////////////////
// ATotemCharacter
// Create a CameraComponent
PlayerBody = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("PlayerBody"));
PlayerBody->AttachParent = GetCapsuleComponent();
PlayerBody->RelativeLocation = FVector(0, 0, 0); // Position the body
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = ObjectInitializer.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true); // only the owning player will see this mesh
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->RelativeLocation = FVector(0.f, 0.f, -150.f);
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
//bReplicates = true;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
Metrics::CreateInstance();
//Death state
bIsDead = false;
TotalDeadBodyDuration = 5.0f;
CurrentDeadBodyDuration = -1.0f;
Team = ETeam::NO_TEAM;
bCanBasicAttack = false;
bCanUseAbility = false;
bAcceptMoveInput = false;
bReborn = true;
TotalRebornDuration = 0.1f;
bAcceptCameraChange = true;
bThirdPersonCamLerp = false;
bThirdPersonDeathCamLerp = false;
bRightButtonDownThisFrame = false;
TotemCharacterMoveState = ETotemCharacterMoveState::NoMove;
void ATotemCharacter::BeginPlay()
{
Super::BeginPlay();
NormalWalkSpeed = GetCharacterMovement()->MaxWalkSpeed;
}
void ATotemCharacter::ServerSpawnProjectile_Implementation(const FVector& SpawnLocation, const FRotator& SpawnRotation, AActor* TheOwner, APawn* TheInstigator)
{
//if (GEngine)
//{
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Should appear only on server!"));
//}
UWorld* const World = GetWorld();
if (World != NULL)
{
//to add owner and instigator information
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = TheOwner;
SpawnParams.Instigator = TheInstigator;
if (ProjectileClass)
{
FVector Offset = RootComponent->GetComponentRotation().Vector();
Offset.Z = 0.0f;
Offset.Normalize();
Offset *= DistanceFromPlayer;
World->SpawnActor<ATotemProjectile>(ProjectileClass, SpawnLocation + Offset, SpawnRotation, SpawnParams);
ATotemPlayerState *state = nullptr;
if (Cast<ATotemPlayerController>(Controller))
{
state = Cast<ATotemPlayerState>(Cast<ATotemPlayerController>(Controller)->PlayerState);
}
if (state)
{
#if WRITE_METRICS
std::string team;
switch (state->Team)
{
case ETeam::RED_TEAM:
team = "Red";
break;
case ETeam::BLUE_TEAM:
team = "Blue";
break;
default:
team = "None";
break;
}
std::string attack;
if (Cast<AEarthShaman>(this))
{
attack = "Rock fist";
}
else if (Cast<AWindShaman>(this))
{
attack = "Sonic bolt";
}
else
{
attack = "Nothing?";
}
Metrics::WriteToFile(std::string(TCHAR_TO_UTF8(*(state->MyName))), team, attack);
#endif
}
}
else if (FireProjectileClass)
{
AFireProjectile* shotProjectile = World->SpawnActor<AFireProjectile>(FireProjectileClass, SpawnLocation, SpawnRotation, SpawnParams);
}
}
}
bool ATotemCharacter::ServerSpawnProjectile_Validate(const FVector& SpawnLocation, const FRotator& SpawnRotation, AActor* TheOwner, APawn* TheInstigator)
{
return true;
}
//////////////////////////////////////////////////////////////////////////
// Input
//// We have 2 versions of the rotation bindings to handle different kinds of devices differently
//// "turn" handles devices that provide an absolute delta, such as a mouse.
//// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
//InputComponent->BindAxis("Turn", this, &ATotemCharacter::AddControllerYawInput);
//InputComponent->BindAxis("TurnRate", this, &ATotemCharacter::TurnAtRate);
//InputComponent->BindAxis("LookUp", this, &ATotemCharacter::AddControllerPitchInput);
//InputComponent->BindAxis("LookUpRate", this, &ATotemCharacter::LookUpAtRate);
void ATotemCharacter::ToggleDebugDeathCam()
{
bDeathCam = !bDeathCam;
if (bDeathCam)
{
bThirdPersonCamLerp = true;
ThirdPersonCamDistance = ThirdPersonDeathCamDistance;
}
else
{
bThirdPersonCamLerp = false;
ThirdPersonCamDistance = 0.0f;
}
}
if (PlayerHealth <= 0)
{
PlayerHealth = 0;
if (character)
{
#if WRITE_METRICS
if (type != AbilityType::NONE && type != AbilityType::End)
{
ATotemPlayerController* control = Cast<ATotemPlayerController>(Controller);
if (control)
{
ATotemPlayerState* state = Cast<ATotemPlayerState>(control->PlayerState);
ATotemPlayerState* attackerState = Cast<ATotemPlayerState>(player->PlayerState);
if (state && attackerState)
{
std::string team;
std::string attackerTeam;
switch (state->Team)
{
case ETeam::RED_TEAM:
team = "Red";
break;
case ETeam::BLUE_TEAM:
team = "Blue";
break;
default:
team = "None";
break;
}
switch (attackerState->Team)
{
case ETeam::RED_TEAM:
attackerTeam = "Red";
break;
case ETeam::BLUE_TEAM:
attackerTeam = "Blue";
break;
default:
attackerTeam = "None";
break;
}
Metrics::WriteToFile(std::string(TCHAR_TO_UTF8(*(attackerState->MyName))), attackerTeam,
std::string("Killed"), std::string(TCHAR_TO_UTF8(*(state->MyName))), team, std::string("Using: " + std::string(TCHAR_TO_UTF8(*(abilityName.ToString())))));
// Player statistics part
state->NumOfDie += 1;
// Prevent count friendly kill
if (team != attackerTeam)
{
attackerState->NumOfKill += 1;
}
}
}
}
#endif
ATotemPlayerController* controller = Cast<ATotemPlayerController>(GetController());
if (controller && controller != player)
{
character->DealtDamageTo(nullptr, controller, player, true);
}
}
else if (PreviousHit.controller)
{
////Tell controller to count the kill
//ATotemCharacter* character = Cast<ATotemCharacter>(PreviousHit.controller->GetPawn());
//if (character)
//{
// ATotemPlayerController* controller = Cast<ATotemPlayerController>(GetController());
// if (controller)
// {
// character->DealtDamageTo(nullptr, controller, PreviousHit.controller, true);
// }
//}
//else
//{
// //TODO: update score on the controller if previous hit player died in the meantime
//}
DeathToLava(PreviousHit.controller, PreviousHit.type);
// Add kill and dead statistics, hopefully it will work
ATotemPlayerState* AttackerState = Cast<ATotemPlayerState>(PreviousHit.controller->PlayerState);
if (Controller)
{
ATotemPlayerController* VictimController = Cast<ATotemPlayerController>(Controller);
if (VictimController)
{
ATotemPlayerState* VictimState = Cast<ATotemPlayerState>(Controller->PlayerState);
if (VictimState)
{
VictimState->NumOfDie += 1;
if (AttackerState)
{
if (AttackerState->Team != VictimState->Team)
{
AttackerState += 1;
}
}
}
}
}
#if WRITE_METRICS
ATotemPlayerController* control = Cast<ATotemPlayerController>(Controller);
if (control)
{
ATotemPlayerState* state = Cast<ATotemPlayerState>(control->PlayerState);
ATotemPlayerState* attackerState = Cast<ATotemPlayerState>(PreviousHit.controller->PlayerState);
if (state && attackerState)
{
std::string team;
std::string attackerTeam;
switch (state->Team)
{
case ETeam::RED_TEAM:
team = "Red";
break;
case ETeam::BLUE_TEAM:
team = "Blue";
break;
default:
team = "None";
break;
}
switch (attackerState->Team)
{
case ETeam::RED_TEAM:
attackerTeam = "Red";
break;
case ETeam::BLUE_TEAM:
attackerTeam = "Blue";
break;
default:
attackerTeam = "None";
break;
}
Metrics::WriteToFile(std::string(TCHAR_TO_UTF8(*(attackerState->MyName))), attackerTeam, std::string("Killed"),
std::string(TCHAR_TO_UTF8(*(state->MyName))), team, std::string("Using: " + std::string(TCHAR_TO_UTF8(*(abilityName.ToString())))));
}
}
#endif
}
KillPlayer();
}
else if (character)
{
ATotemPlayerController* controller = Cast<ATotemPlayerController>(GetController());
if (controller)
{
character->DealtDamageTo(nullptr, controller, player, false);
}
}
}
if (!bInvincible )
{
OnDamageTaken(player);
DamageTakenBy(type, abilityName);
}
}
if (bThirdPersonDeathCamLerp)
{
if (Controller)
{
Controller->SetControlRotation(FRotator(-1.0f * DeathCamAngle, 0, 0));
}
}
if (bThirdPersonCamLerp || bThirdPersonDeathCamLerp )
{
CameraBoom->TargetArmLength = FMath::Lerp<float>(CameraBoom->TargetArmLength, ThirdPersonCamDistance, DeltaTime*4.0f);
}
else
{
CameraBoom->TargetArmLength = FMath::Lerp<float>(CameraBoom->TargetArmLength, 0, DeltaTime*4.0f);
}
if (HasAuthority())
{
if (bBeingKnockedBack)
{
TimeSinceKnockedBack -= DeltaTime;
if (TimeSinceKnockedBack < 0.0f)
{
bBeingKnockedBack = false;
}
}
#if (WRITE_METRICS > 1)
if (DeltaTime >= .025)
{
ATotemPlayerController* control = Cast<ATotemPlayerController>(Controller);
if(control)
{
ATotemPlayerState* state = Cast<ATotemPlayerState>(control->PlayerState);
if(state)
{
std::string team;
switch (state->Team)
{
case ETeam::RED_TEAM:
team = "Red";
break;
case ETeam::BLUE_TEAM:
team = "Blue";
break;
default:
team = "None";
break;
}
Metrics::WriteToFile(std::string(TCHAR_TO_UTF8(*(state->MyName))), team, std::string("Frame rate hit"),
std::string(std::to_string(DeltaTime) + "ms"), std::string(std::to_string(1.0f/DeltaTime) + "fps"));
}
}
}
#endif
}
//Keep track of how long has passed since the last attack
TimeSinceAttack += DeltaTime;
ShotPressedDuration += DeltaTime;
if (OverlappedCyclones.Num() == 0)
{
//Do this to prevent bCanMove be replictated every frame
if (!bCanMove)
{
bCanMove = true;
}
AttachCyclone = nullptr;
}
else if (OverlappedCyclones.Num() > 0)
{
if (bCanMove)
{
bCanMove = false;
}
if (AttachCyclone)
{
FVector CycloneVelocity = AttachCyclone->ProjectileMovement->Velocity;
ATotemPlayerController* own = Cast<ATotemPlayerController>(AttachCyclone->GetOwner());
if (own)
{
ReduceHealth(AttachCyclone->Damage * DeltaTime, own, AbilityType::WIND, FName(TEXT("Cyclone"))); //every second reduce Damage
amount of health
}
LaunchCharacter(CycloneVelocity, true, true);
}
//CharacterMovement->Velocity = CycloneVelocity;
}
}
if (bClickedThisFrame)
{
bClickedThisFrame = false;
if (Controller)
{
APlayerController* control = Cast<APlayerController>(Controller);
if (control)
{
if (!control->IsInputKeyDown(EKeys::LeftMouseButton))
{
LeftUp();
}
}
}
}
if (bRightButtonDownThisFrame)
{
bRightButtonDownThisFrame = false;
if (Controller)
{
APlayerController* control = Cast<APlayerController>(Controller);
if (control)
{
if (!control->IsInputKeyDown(EKeys::RightMouseButton))
{
RightUp();
}
}
}
}
//CheckShiftKey();
// bThirdPersonCamLerp = true;
// //PC->HandleDead(loc, rot)
//}
bThirdPersonDeathCamLerp = true;
ThirdPersonCamDistance = ThirdPersonDeathCamDistance;
ATotemPlayerController *PC = Cast<ATotemPlayerController>(Controller);
if (PC)
{
PC->DisableInput(PC);
}
CurrentDeadBodyDuration = TotalDeadBodyDuration;
bIsDead = true;
EnterDeath();
GetWorld()->GetTimerManager().SetTimer(mDeathDissolveEffectTimerHandle, this, &ATotemCharacter::CallBlueprintEventForMaterial,
DeathDissolvePlayAfterTimer, false);
//don't destory pawn himself, will cause weird
//Problem. But I don't know why...
//Destroy();
}
}
}
void ATotemCharacter::OnFire()
{
//only server can spawn projectile theoretically
// try and fire a projectile
if (ProjectileClass != NULL || FireProjectileClass != NULL)
{
const FRotator SpawnRotation = GetControlRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle pos ition
const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
}
void ATotemCharacter::OnShotDown()
{
ShotPressed = true;
ShotFired = false;
ShotDownMetrics();
}
void ATotemCharacter::ShotDownMetrics_Implementation()
{
#if WRITE_METRICS
bool ATotemCharacter::ShotDownMetrics_Validate()
{
return true;
}
void ATotemCharacter::OnShotUp()
{
ShotPressed = false;
ShotUpMetrics();
}
void ATotemCharacter::ShotUpMetrics_Implementation()
{
#if WRITE_METRICS
if (Cast<AFireShaman>(this))
{
ATotemPlayerController* control = Cast<ATotemPlayerController>(Controller);
if (control)
{
ATotemPlayerState* state = Cast<ATotemPlayerState>(control->PlayerState);
if (state)
{
std::string team;
switch (state->Team)
{
case ETeam::RED_TEAM:
team = "Red";
break;
case ETeam::BLUE_TEAM:
team = "Blue";
break;
default:
team = "None";
break;
}
Metrics::WriteToFile(std::string(TCHAR_TO_UTF8(*(state->MyName))), team, std::string("Flamethrower end"));
}
}
}
#endif
}
bool ATotemCharacter::ShotUpMetrics_Validate()
{
return true;
}
void ATotemCharacter::RightUp()
{
void ATotemCharacter::RightDown()
{
bRightButtonDownThisFrame = true;
}
void ATotemCharacter::ScrollUp()
{
if (CurrentAbility != nullptr) CurrentAbility->ScrollUp();
}
void ATotemCharacter::ScrollDown()
{
if (CurrentAbility != nullptr) CurrentAbility->ScrollDown();
}
int ATotemCharacter::CurrentAbilityIndex()
{
if (CurrentAbility != nullptr)
{
return CurrentAbility->GetIndex();
}
else
{
return -1;
}
}
void ATotemCharacter::BeginDestroy()
{
while (NumAbilities > 0)
{
BaseAbility* DestroyAbility = CurrentAbility;
CurrentAbility = CurrentAbility->GetNextAbility();
delete DestroyAbility;
--NumAbilities;
}
Super::BeginDestroy();
}
void ATotemCharacter::Jump()
{
//ActInAir();
Super::Jump();
}
return Ability->CooldownLeft();
}
return Ability->GetCooldown();
}
void ATotemCharacter::ClientPlaySound_Implementation(USoundBase* Sound, float distToPlay, float VolumeMultiplier, float PitchMultiplier, float StartTime, USoundAttenuation*
AttenuationSettings)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("ClientPlayExplosionSound is triggered!"));
}
for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
if ((*Iterator)->IsLocalPlayerController())
{
ATotemCharacter* MyCharacter = Cast<ATotemCharacter>((*Iterator)->GetPawn());
if (MyCharacter)
{
//FVector use local variable store actor location
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Local player is found!"));
}
if ((GetActorLocation() - MyCharacter->GetActorLocation()).Size() <= distToPlay)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Dist check succeed!"));
}
UGameplayStatics::PlaySoundAtLocation(this, Sound, GetActorLocation(), VolumeMultiplier, PitchMultiplier, StartTime,
AttenuationSettings);
}
}
break;
}
}
}
void ATotemCharacter::ShrineUnlocked(FString name)
{
#if WRITE_METRICS
Metrics::WriteToFile(std::string(), std::string(), std::string(TCHAR_TO_UTF8(*name) + std::string(" shrine unlocked")));
#endif
}
//
void ATotemCharacter::EnterDeath()
{
ClientSetIfAcceptMoveInput(false);
bCanBasicAttack = false;
bCanUseAbility = false;
bAcceptCameraChange = false;
GetCharacterMovement()->Velocity = FVector(0.0f);
}
void ATotemCharacter::ExitReborn()
{
ClientSetIfAcceptMoveInput(true);
bCanBasicAttack = true;
bCanUseAbility = true;
}
//
//void ATotemCharacter::ActInAir_Implementation()
//{
//
//}
//
//bool ATotemCharacter::ActInAir_Validate()
//{
// return true;
//}
TActorIterator<ATotemCharacter> characterIterator(world);
void ATotemCharacter::ToggleSpectator()
{
if (Controller)
{
ATotemPlayerController* TotemPlayerController = Cast<ATotemPlayerController>(Controller);
if (TotemPlayerController)
{
TotemPlayerController->ServerSetMyShaman(EPlayerType::SPECTATE_SHAMAN);
ATotemPlayerState* TotemPlayerState = Cast<ATotemPlayerState>(TotemPlayerController->PlayerState);
if (TotemPlayerState)
{
TotemPlayerState->bDisplayUI = false;
}
}
}
}
void ATotemCharacter::LeftDown()
{
bClickedThisFrame = true;
}
void ATotemCharacter::LeftUp()
{
bool ATotemCharacter::Invincible()
{
return bInvincible;
}
void ATotemCharacter::OnRep_TotemCharacterMoveState()
{
// change speed here GetCharacterMovement()->MaxWalkSpeed = NormalMaxSpeed;
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Unreal API Shit!"));
}
switch (TotemCharacterMoveState)
{
case ETotemCharacterMoveState::NoMove:
{
GetCharacterMovement()->MaxWalkSpeed = NormalWalkSpeed;
break;
}
case ETotemCharacterMoveState::Sprint:
{
GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
break;
}
}
void ATotemCharacter::CheckShiftKey()
{
//For Sprint, designed only execute on owning client
if (Controller)
{
if (Controller->IsLocalPlayerController())
{
APlayerController* PlayerController = Cast<APlayerController>(Controller);
if (PlayerController)
{
if (PlayerController->IsInputKeyDown(EKeys::LeftShift))
{
// if no move state && on the ground
if (TotemCharacterMoveState == ETotemCharacterMoveState::NoMove && GetCharacterMovement()->IsWalking())
{
SetTotemCharacterMoveState(ETotemCharacterMoveState::Sprint);
}
}
else
{
if (TotemCharacterMoveState == ETotemCharacterMoveState::Sprint)
{
SetTotemCharacterMoveState(ETotemCharacterMoveState::NoMove);
}
}
}
}
}
}
bool ATotemCharacter::RayCastOnGround()
{
UWorld *world = GetWorld();
if (world)
{
FHitResult Hit(ForceInit);
FCollisionQueryParams collisionParams(FName(TEXT("EARTH_SHAMAN_TRACE")), true, this);
world->LineTraceSingle(Hit, StartTrace, EndTrace, ECC_WorldStatic, collisionParams);
return false;
}
void ATotemCharacter::CallBlueprintEventForMaterial()
{
bDeathEffectFired = true;
}
EXAMPLE #6
#include "GameWeapons.h"
#include "States/GWWeaponState.h"
#include "Tracing/GWTraceBase.h"
#include "Tracing/GWTraceRangedWeapon.h"
#include "Ammo/GWAmmo.h"
#include "IGISkeletalMesh.h"
#include "Net/UnrealNetwork.h"
#include "GWWeaponRanged.h"
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = false;
PrimaryActorTick.bAllowTickOnDedicatedServer = true;
PrimaryActorTick.bRunOnAnyThread = true;
PrimaryActorTick.TickGroup = ETickingGroup::TG_DuringPhysics;
SetTickGroup(ETickingGroup::TG_DuringPhysics);
bIsWeaponFiring = false;
ReloadEndCount = 0;
}
void AGWWeaponRanged::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (bTraceEveryTick && bIsWeaponFiring && TargetingMethod)
{
TargetingMethod->SingleLineTraceSetHitLocation();
if (Role < ROLE_Authority || GetNetMode() == ENetMode::NM_Standalone)
OnWeaponFiring(HitInfo.Origin, HitInfo.HitLocation);
}
}
void AGWWeaponRanged::BeginPlay()
{
CurrentState = ActiveState;
RemaningAmmo = MaximumAmmo;
RemainingMagazineAmmo = MagazineSize;
CurrentSpread = BaseSpread;
CurrentHorizontalRecoil = RecoilConfig.HorizontalRecoilBase;
CurrentVerticalRecoil = RecoilConfig.VerticalRecoilBase;
if (TargetingMethod)
{
TargetingMethod->SetRange(Range);
TargetingMethod->SetCurrentSpread(CurrentSpread);
TargetingMethod->Initialize();
}
if (TypeOfAmmo)
{
CurrentAmmo = NewObject<UGWAmmo>(TypeOfAmmo);
}
}
void AGWWeaponRanged::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
void AGWWeaponRanged::InitializeWeapon()
{
Super::InitializeWeapon();
}
void AGWWeaponRanged::InputPressed()
{
BeginFire();
}
void AGWWeaponRanged::InputReleased()
{
EndFire();
}
void AGWWeaponRanged::InputReload()
{
BeginReload();
}
void AGWWeaponRanged::FireWeapon(const FHitResult& TargetIn, float DamageIn, APawn* InstigatorIn)
{
if (CurrentAmmo)
{
CurrentAmmo->ApplyDamage(TargetIn, DamageIn, InstigatorIn);
}
}
void AGWWeaponRanged::ShootWeapon()
{
if (!CheckIfHaveAmmo())
{
CurrentState->EndActionSequence();
return;
}
SubtractAmmo();
CalculateCurrentWeaponSpread();
OnShoot();
//}
if (GetNetMode() == ENetMode::NM_Standalone || Role < ROLE_Authority)
OnRep_HitInfo();
}
void AGWWeaponRanged::ActionEnd()
{
//activate states
void AGWWeaponRanged::BeginFire()
{
//if (Role < ROLE_Authority)
//{
// if (!CheckIfHaveAmmo())
// return;
// ServerBeginFire();
// bIsWeaponFiring = true;
// //start shooting also on onwing client, to provide better feedback.
// CurrentState->BeginActionSequence();
// //OnRep_HitInfo();
// GetWorldTimerManager().ClearTimer(ReduceSpreadOverTimeTimerHandle);
// //if (TargetingMethod)
// // TargetingMethod->Execute();
//}
//else
//{
if (!CheckIfHaveAmmo())
{
CurrentState->EndActionSequence();
return;
}
GetWorldTimerManager().ClearTimer(ReduceSpreadOverTimeTimerHandle);
bIsWeaponFiring = true;
CurrentState->BeginActionSequence();
//}
}
void AGWWeaponRanged::ServerBeginFire_Implementation()
{
BeginFire();
}
bool AGWWeaponRanged::ServerBeginFire_Validate()
{
return true;
}
void AGWWeaponRanged::EndFire()
{
//if (Role < ROLE_Authority)
//{
// bIsWeaponFiring = false;
// CurrentState->EndActionSequence();
void AGWWeaponRanged::BeginReload()
{
if (Role < ROLE_Authority)
{
OnRep_ReloadBeign();
ServerBeginReload();
}
else
{
ReloadBeginCount++;
GotoState(ReloadState);
if (GetNetMode() == ENetMode::NM_Standalone)
OnRep_ReloadBeign();
}
}
void AGWWeaponRanged::ServerBeginReload_Implementation()
{
BeginReload();
}
bool AGWWeaponRanged::ServerBeginReload_Validate()
{
return true;
}
void AGWWeaponRanged::CalculateReloadAmmo()
{
float NeededAmmo = MagazineSize - RemainingMagazineAmmo;
if (NeededAmmo <= RemainingMagazineAmmo)
return;
RemaningAmmo -= NeededAmmo;
RemainingMagazineAmmo += NeededAmmo;
}
void AGWWeaponRanged::EndReload()
{
if (Role < ROLE_Authority)
{
if (!CheckIfCanReload())
return;
CalculateReloadAmmo();
ServerEndReload();
}
else
{
/*
Impelemtnsome reload mechanic..
1. Where is ammo coming from ?
2. How it is setup ?
3. Does weapon have it's own magazine max ammo count, or is it stored externally ?
*/
if (!CheckIfCanReload())
return;
CalculateReloadAmmo();
ReloadEndCount++;
if (GetNetMode() == ENetMode::NM_Standalone)
OnRep_ReloadEnd();
}
}
void AGWWeaponRanged::ServerEndReload_Implementation()
{
EndReload();
}
bool AGWWeaponRanged::ServerEndReload_Validate()
{
return true;
}
void AGWWeaponRanged::OnRep_Shooting()
{
//OnWeaponFiring();
}
void AGWWeaponRanged::OnRep_ReloadBeign()
{
OnReloadBegin();
if (ReloadAnimation)
{
IIGISkeletalMesh* skelMeshInt = Cast<IIGISkeletalMesh>(Instigator);
if (!skelMeshInt)
return;
AnimInst->Montage_Play(ReloadAnimation, multiplier);
}
}
void AGWWeaponRanged::OnRep_ReloadEnd()
{
OnReloadEnd();
}
void AGWWeaponRanged::OnRep_HitInfo()
{
OnWeaponFiring(HitInfo.Origin, HitInfo.HitLocation);
}
bool AGWWeaponRanged::CheckIfHaveAmmo()
{
if (RemainingMagazineAmmo > 0)
return true;
else
return false;
}
void AGWWeaponRanged::SubtractAmmo()
{
RemainingMagazineAmmo -= AmmoCost;
}
bool AGWWeaponRanged::CheckIfCanReload()
{
if (RemainingMagazineAmmo >= MagazineSize)
return false;
else
return true;
}
void AGWWeaponRanged::CalculateCurrentWeaponSpread()
{
CurrentSpread = CurrentSpread * SpreadMultiplier;
CurrentHorizontalRecoil = CurrentHorizontalRecoil * RecoilConfig.HorizontalRecoilMultiplier;
CurrentVerticalRecoil = CurrentVerticalRecoil * RecoilConfig.VerticalRecoilMultiplier;
if (CurrentHorizontalRecoil > RecoilConfig.HorizontalRecoilMaximum)
{
CurrentHorizontalRecoil = RecoilConfig.HorizontalRecoilMaximum;
}
if (CurrentVerticalRecoil > RecoilConfig.VerticalRecoilMaximum)
{
CurrentVerticalRecoil = RecoilConfig.VerticalRecoilMaximum;
}
if (CurrentSpread > MaximumSpread)
{
CurrentSpread = MaximumSpread;
}
OnCurrentWeaponSpread.Broadcast(CurrentSpread);
if (TargetingMethod)
{
TargetingMethod->SetCurrentSpread(CurrentSpread);
}
}
void AGWWeaponRanged::ReduceSpreadOverTime()
{
CurrentSpread -= SpreadReduce;
CurrentHorizontalRecoil -= 1;
CurrentVerticalRecoil -= 1;
if (CurrentSpread <= BaseSpread)
{
CurrentSpread = BaseSpread;
GetWorldTimerManager().ClearTimer(ReduceSpreadOverTimeTimerHandle);
}
}
EXAMPLE #7
#include "UDKPresentation.h"
#include "UDKPresentationCharacter.h"
#include "UDKPresentationProjectile.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/InputSettings.h"
//////////////////////////////////////////////////////////////////////////
// AUDKPresentationCharacter
AUDKPresentationCharacter::AUDKPresentationCharacter()
{
maxJump = 1;
currentJump = 0;
maxAmmo = 0;
ammo = maxAmmo;
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
void AUDKPresentationCharacter::UpdateAmmo()
{
if (CharacterMovement->IsMovingOnGround()) {
ammo = maxAmmo;
}
}
void AUDKPresentationCharacter::MoreAmmo()
{
maxAmmo++;
}
int AUDKPresentationCharacter::GetMaxAmmo()
{
return maxAmmo;
}
int AUDKPresentationCharacter::GetAmmo()
{
if (CharacterMovement->IsMovingOnGround()) {
ammo = maxAmmo;
}
return ammo;
}
void AUDKPresentationCharacter::Jump()
{
if (CharacterMovement->IsMovingOnGround()) {
currentJump = 0;
bPressedJump = true;
JumpKeyHoldTime = 0.0f;
ammo = maxAmmo;
}
else {
DoubleJump();
}
}
void AUDKPresentationCharacter::DoubleJump() {
if (currentJump < maxJump) {
CharacterMovement->Velocity.Z = 0;
CharacterMovement->Velocity += FVector(0, 0, 500);
currentJump++;
}
}
void AUDKPresentationCharacter::StopJumping()
{
bPressedJump = false;
JumpKeyHoldTime = 0.0f;
}
//////////////////////////////////////////////////////////////////////////
// Input
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AUDKPresentationCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AUDKPresentationCharacter::LookUpAtRate);
}
void AUDKPresentationCharacter::OnFire()
{
if (CharacterMovement->IsMovingOnGround()) {
ammo = maxAmmo;
}
if (ammo <= 0) return;
// try and fire a projectile
if (ProjectileClass != NULL)
{
const FRotator SpawnRotation = GetControlRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle pos ition
const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
ammo--;
CharacterMovement->Velocity = GetControlRotation().Vector()*(-1000) + 0.5f * CharacterMovement->Velocity;
if (ScaledDelta.X != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.X * BaseTurnRate;
AddControllerYawInput(Value);
}
if (ScaledDelta.Y != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.Y* BaseTurnRate;
AddControllerPitchInput(Value);
}
TouchItem.Location = Location;
}
TouchItem.Location = Location;
}
}
}
}
EXAMPLES #8 and #9
// Fill out your copyright notice in the Description page of Project Settings.
#include "FPSCode.h"
#include "Gun.h"
#include "Animation/AnimInstance.h"
#include "FPSCodeCharacter.h"
#include "Kismet/KismetMathLibrary.h"
AGun::AGun()
{
Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
void AGun::BeginPlay()
{
Super::BeginPlay();
CurrentAmmo = MagSize;
//Applying negative recoil to compensate for recoil that was added during firing (occurs after stopping firing)
if (RecoilInterp)
{
if ((UGameplayStatics::GetPlayerController(this, 0)->GetControlRotation().Pitch > 270 && InitialRecoilPitch > 270) || (UGameplayStatics::GetPlayerController(this,
0)->GetControlRotation().Pitch < 270 && InitialRecoilPitch < 270))
{
if (UGameplayStatics::GetPlayerController(this, 0)->GetControlRotation().Pitch > InitialRecoilPitch)
{
float Pitch = UKismetMathLibrary::FInterpTo_Constant(UGameplayStatics::GetPlayerController(this, 0)->GetControlRotation().Pitch,
InitialRecoilPitch, Seconds, 12);
float Yaw = UGameplayStatics::GetPlayerController(this, 0)->GetControlRotation().Yaw;
float Roll = UGameplayStatics::GetPlayerController(this, 0)->GetControlRotation().Roll;
void AGun::Fire()
{
void AGun::OnEquip()
{
Super::OnEquip();
if (WeaponEquipAnimation)
{
Mesh->GetAnimInstance()->Montage_Play(WeaponEquipAnimation, 1.f);
}
if (PlayerEquipAnimation)
{
UAnimInstance* AnimInstance = Cast<AFPSCodeCharacter>(UGameplayStatics::GetPlayerCharacter(this, 0))->GetMesh1P()->GetAnimInstance();
if (AnimInstance)
{
AnimInstance->Montage_Play(PlayerEquipAnimation, 1.f);
}
}
void AGun::Attack()
{
if (CurrentAmmo > 0)
{
if (bIsAuto)
{
if (bCanAttack)
{
bCanAttack = false;
CanStopShooting = true;
GetWorld()->GetTimerManager().SetTimer(BoolTimerHandle, this, &AGun::SetCanAttack, 1 / (RateOfFire / 60)); //Setting timer for being able
to attack again (to prevent spamming attack)
GetWorld()->GetTimerManager().SetTimer(AutoTimerHandle, this, &AGun::Fire, 1 / (RateOfFire / 60), true, 0.f); //Setting timer for
refiring for automatic weapons
Fire();
}
}
}
}
void AGun::SetCanAttack()
{
bCanAttack = true;
}
void AGun::StopFire()
{
if (bIsAuto)
{
if (CanStopShooting)
{
CanStopShooting = false;
if (Flash)
{
Flash->DestroyComponent();
}
RecoilInterp = true;
GetWorld()->GetTimerManager().SetTimer(RecoilHandle, this, &AGun::DisableRecoilInterp, .4f); //Set timer to disable recoil after short amount of
time
}
}
}
void AGun::Reload()
{
if (!IsReloading)
{
if (CurrentAmmo < MagSize && TotalAmmo > 0)
{
IsReloading = true;
if (AnimInstance)
{
bCanAttack = false;
FTimerHandle AnimHandle;
TotalAmmo = 0;
}
else
{
TotalAmmo = TotalAmmo - (MagSize - CurrentAmmo);
CurrentAmmo = MagSize;
}
}
void AGun::DisableRecoilInterp()
{
RecoilInterp = false;
EXAMPLE #10
(see EXAMPLE # 3)
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
Character.cpp: ACharacter implementation
=============================================================================*/
#include "EnginePrivate.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Components/PrimitiveComponent.h"
#include "Net/UnrealNetwork.h"
#include "DisplayDebugHelpers.h"
#include "Animation/AnimInstance.h"
#include "Animation/AnimMontage.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/DamageType.h"
// Character rotation only changes in Yaw, to prevent the capsule from changing orientation.
// Ask the Controller for the full rotation if desired (ie for aiming).
bUseControllerRotationPitch = false;
bUseControllerRotationRoll = false;
bUseControllerRotationYaw = true;
CapsuleComponent = CreateDefaultSubobject<UCapsuleComponent>(ACharacter::CapsuleComponentName);
CapsuleComponent->InitCapsuleSize(34.0f, 88.0f);
CapsuleComponent->CanCharacterStepUpOn = ECB_No;
CapsuleComponent->bShouldUpdatePhysicsVolume = true;
CapsuleComponent->bCheckAsyncSceneOnMove = false;
CapsuleComponent->bCanEverAffectNavigation = false;
CapsuleComponent->bDynamicObstacle = true;
RootComponent = CapsuleComponent;
JumpKeyHoldTime = 0.0f;
JumpMaxHoldTime = 0.0f;
#if WITH_EDITORONLY_DATA
ArrowComponent = CreateEditorOnlyDefaultSubobject<UArrowComponent>(TEXT("Arrow"));
if (ArrowComponent)
{
ArrowComponent->ArrowColor = FColor(150, 200, 255);
ArrowComponent->bTreatAsASprite = true;
ArrowComponent->SpriteInfo.Category = ConstructorStatics.ID_Characters;
ArrowComponent->SpriteInfo.DisplayName = ConstructorStatics.NAME_Characters;
ArrowComponent->AttachParent = CapsuleComponent;
ArrowComponent->bIsScreenSizeScaled = true;
}
#endif // WITH_EDITORONLY_DATA
CharacterMovement = CreateDefaultSubobject<UCharacterMovementComponent>(ACharacter::CharacterMovementComponentName);
if (CharacterMovement)
{
CharacterMovement->UpdatedComponent = CapsuleComponent;
CrouchedEyeHeight = CharacterMovement->CrouchedHalfHeight * 0.80f;
}
Mesh = CreateOptionalDefaultSubobject<USkeletalMeshComponent>(ACharacter::MeshComponentName);
if (Mesh)
{
Mesh->AlwaysLoadOnClient = true;
Mesh->AlwaysLoadOnServer = true;
Mesh->bOwnerNoSee = false;
Mesh->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::AlwaysTickPose;
Mesh->bCastDynamicShadow = true;
Mesh->bAffectDynamicIndirectLighting = true;
Mesh->PrimaryComponentTick.TickGroup = TG_PrePhysics;
Mesh->bChartDistanceFactor = true;
Mesh->AttachParent = CapsuleComponent;
static FName MeshCollisionProfileName(TEXT("CharacterMesh"));
Mesh->SetCollisionProfileName(MeshCollisionProfileName);
Mesh->bGenerateOverlapEvents = false;
Mesh->bCanEverAffectNavigation = false;
}
BaseRotationOffset = FQuat::Identity;
}
void ACharacter::PostInitializeComponents()
{
Super::PostInitializeComponents();
if (!IsPendingKill())
{
if (Mesh)
{
BaseTranslationOffset = Mesh->RelativeLocation;
BaseRotationOffset = Mesh->RelativeRotation.Quaternion();
void ACharacter::UpdateNavigationRelevance()
{
if (CapsuleComponent)
{
CapsuleComponent->SetCanEverAffectNavigation(bCanAffectNavigationGeneration);
}
}
return Super::FindComponentByClass(ComponentClass);
}
void ACharacter::OnWalkingOffLedge_Implementation(const FVector& PreviousFloorImpactNormal, const FVector& PreviousFloorContactNormal, const FVector& PreviousLocation, float TimeDelta)
{
}
void ACharacter::NotifyJumpApex()
{
// Call delegate callback
if (OnReachedJumpApex.IsBound())
{
OnReachedJumpApex.Broadcast();
}
}
return !bIsCrouched && CharacterMovement && (CharacterMovement->IsMovingOnGround() || bCanHoldToJumpHigher) && CharacterMovement->IsJumpAllowed() && !CharacterMovement-
>bWantsToCrouch;
}
void ACharacter::OnJumped_Implementation()
{
}
// Deprecated
bool ACharacter::DoJump( bool bReplayingMoves )
{
return CanJump() && CharacterMovement->DoJump(bReplayingMoves);
}
void ACharacter::RecalculateBaseEyeHeight()
{
if (!bIsCrouched)
{
Super::RecalculateBaseEyeHeight();
}
else
{
BaseEyeHeight = CrouchedEyeHeight;
}
}
void ACharacter::OnRep_IsCrouched()
{
if (CharacterMovement)
{
if (bIsCrouched)
{
CharacterMovement->Crouch(true);
}
else
{
CharacterMovement->UnCrouch(true);
}
}
}
if (CharacterMovement != nullptr)
{
// Set prediction data time stamp to current time to stop extrapolating
// from time bReplicateMovement was turned off to when it was turned on again
FNetworkPredictionData_Server* NetworkPrediction = CharacterMovement->GetPredictionData_Server();
if (NetworkPrediction != nullptr)
{
NetworkPrediction->ServerTimeStamp = GetWorld()->GetTimeSeconds();
}
}
}
bool ACharacter::CanCrouch()
{
return !bIsCrouched && CharacterMovement && CharacterMovement->CanEverCrouch() && GetRootComponent() && !GetRootComponent()->IsSimulatingPhysics();
}
if (Mesh)
{
Mesh->RelativeLocation.Z = GetDefault<ACharacter>(GetClass())->Mesh->RelativeLocation.Z;
BaseTranslationOffset.Z = Mesh->RelativeLocation.Z;
}
else
{
BaseTranslationOffset.Z = GetDefault<ACharacter>(GetClass())->BaseTranslationOffset.Z;
}
K2_OnEndCrouch(HeightAdjust, ScaledHeightAdjust);
}
if (Mesh)
{
Mesh->RelativeLocation.Z = GetDefault<ACharacter>(GetClass())->Mesh->RelativeLocation.Z + HeightAdjust;
BaseTranslationOffset.Z = Mesh->RelativeLocation.Z;
}
else
{
BaseTranslationOffset.Z = GetDefault<ACharacter>(GetClass())->BaseTranslationOffset.Z + HeightAdjust;
}
K2_OnStartCrouch(HeightAdjust, ScaledHeightAdjust);
}
void ACharacter::ApplyDamageMomentum(float DamageTaken, FDamageEvent const& DamageEvent, APawn* PawnInstigator, AActor* DamageCauser)
{
UDamageType const* const DmgTypeCDO = DamageEvent.DamageTypeClass->GetDefaultObject<UDamageType>();
float const ImpulseScale = DmgTypeCDO->DamageImpulse;
// limit Z momentum added if already going up faster than jump (to avoid blowing character way up into the sky)
{
FVector MassScaledImpulse = Impulse;
if(!bMassIndependentImpulse && CharacterMovement->Mass > SMALL_NUMBER)
{
MassScaledImpulse = MassScaledImpulse / CharacterMovement->Mass;
}
CharacterMovement->AddImpulse(Impulse, bMassIndependentImpulse);
}
}
void ACharacter::ClearCrossLevelReferences()
{
if( BasedMovement.MovementBase != NULL && GetOutermost() != BasedMovement.MovementBase->GetOutermost() )
{
SetBase( NULL );
}
Super::ClearCrossLevelReferences();
}
namespace MovementBaseUtility
{
bool IsDynamicBase(const UPrimitiveComponent* MovementBase)
{
return (MovementBase && MovementBase->Mobility == EComponentMobility::Movable);
}
// @TODO: We need to find a more efficient way of finding all ticking components in an actor.
for (UActorComponent* Component : NewBaseOwner->GetComponents())
{
if (Component && Component->PrimaryComponentTick.bCanEverTick)
{
BasedObjectTick.AddPrerequisite(Component, Component->PrimaryComponentTick);
}
}
}
}
}
// @TODO: We need to find a more efficient way of finding all ticking components in an actor.
for (UActorComponent* Component : OldBaseOwner->GetComponents())
{
if (Component && Component->PrimaryComponentTick.bCanEverTick)
{
BasedObjectTick.RemovePrerequisite(Component, Component->PrimaryComponentTick);
}
}
}
}
}
BaseVelocity = MovementBase->GetComponentVelocity();
if (BaseVelocity.IsZero())
{
// Fall back to actor's Root component
const AActor* Owner = MovementBase->GetOwner();
if (Owner)
{
// Component might be moved manually (not by simulated physics or a movement component), see if the root component of the actor has a velocity.
BaseVelocity = MovementBase->GetOwner()->GetVelocity();
}
}
return BaseVelocity;
}
FVector GetMovementBaseTangentialVelocity(const UPrimitiveComponent* MovementBase, const FName BoneName, const FVector& WorldLocation)
{
if (MovementBaseUtility::IsDynamicBase(MovementBase))
{
if (const FBodyInstance* BodyInstance = MovementBase->GetBodyInstance(BoneName))
{
const FVector BaseAngVel = BodyInstance->GetUnrealWorldAngularVelocity();
if (!BaseAngVel.IsNearlyZero())
{
FVector BaseLocation;
FQuat BaseRotation;
if (MovementBaseUtility::GetMovementBaseTransform(MovementBase, BoneName, BaseLocation, BaseRotation))
{
const FVector RadialDistanceToBase = WorldLocation - BaseLocation;
const FVector TangentialVel = FVector::DegreesToRadians(BaseAngVel) ^ RadialDistanceToBase;
return TangentialVel;
}
}
}
}
return FVector::ZeroVector;
}
bool GetMovementBaseTransform(const UPrimitiveComponent* MovementBase, const FName BoneName, FVector& OutLocation, FQuat& OutQuat)
{
if (MovementBase)
{
if (BoneName != NAME_None)
{
const USkeletalMeshComponent* SkeletalBase = Cast<USkeletalMeshComponent>(MovementBase);
if (SkeletalBase)
{
const int32 BoneIndex = SkeletalBase->GetBoneIndex(BoneName);
if (BoneIndex != INDEX_NONE)
{
const FTransform BoneTransform = SkeletalBase->GetBoneTransform(BoneIndex);
OutLocation = BoneTransform.GetLocation();
OutQuat = BoneTransform.GetRotation();
return true;
}
UE_LOG(LogCharacter, Warning, TEXT("GetMovementBaseTransform(): Invalid bone '%s' for SkeletalMeshComponent base %s"), *BoneName.ToString(),
*GetPathNameSafe(MovementBase));
return false;
}
// TODO: warn if not a skeletal mesh but providing bone index.
}
// No bone supplied
OutLocation = MovementBase->GetComponentLocation();
OutQuat = MovementBase->GetComponentQuat();
return true;
}
// NULL MovementBase
OutLocation = FVector::ZeroVector;
OutQuat = FQuat::Identity;
return false;
}
}
if (bBaseChanged || bBoneChanged)
{
// Verify no recursion.
APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL);
for( ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) )
{
if( Loop == this )
{
UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName());
return;
}
}
// Set base.
UPrimitiveComponent* OldBase = BasedMovement.MovementBase;
BasedMovement.MovementBase = NewBaseComponent;
BasedMovement.BoneName = BoneName;
if (CharacterMovement)
{
if (bBaseChanged)
{
MovementBaseUtility::RemoveTickDependency(CharacterMovement->PrimaryComponentTick, OldBase);
MovementBaseUtility::AddTickDependency(CharacterMovement->PrimaryComponentTick, NewBaseComponent);
}
if (NewBaseComponent)
{
// Update OldBaseLocation/Rotation as those were referring to a different base
// ... but not when handling replication for proxies (since they are going to copy this data from the replicated values anyway)
if (!bInBaseReplication)
{
CharacterMovement->SaveBaseLocation();
}
// Enable pre-cloth tick if we are standing on a physics object, as we need to to use post-physics transforms
CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(NewBaseComponent->IsSimulatingPhysics());
}
else
{
BasedMovement.BoneName = NAME_None; // None, regardless of whether user tried to set a bone name, since we have no base component.
BasedMovement.bRelativeRotation = false;
CharacterMovement->CurrentFloor.Clear();
CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(false);
}
if (GetCharacterMovement() != nullptr)
{
AgentLocation = GetCharacterMovement()->GetActorFeetLocation();
}
return AgentLocation;
}
void ACharacter::TurnOff()
{
if (CharacterMovement != NULL)
{
CharacterMovement->StopMovementImmediately();
CharacterMovement->DisableMovement();
}
Super::TurnOff();
}
void ACharacter::Restart()
{
Super::Restart();
bPressedJump = false;
JumpKeyHoldTime = 0.0f;
ClearJumpInput();
UnCrouch(true);
if (CharacterMovement)
{
CharacterMovement->SetDefaultMovementMode();
}
}
void ACharacter::PawnClientRestart()
{
if (CharacterMovement != NULL)
{
CharacterMovement->StopMovementImmediately();
CharacterMovement->ResetPredictionData_Client();
}
Super::PawnClientRestart();
}
// If we are controlled remotely, set animation timing to be driven by client's network updates. So timing and events remain in sync.
if (Mesh && (GetRemoteRole() == ROLE_AutonomousProxy && GetNetConnection() != nullptr))
{
Mesh->bAutonomousTickPose = true;
}
}
void ACharacter::UnPossessed()
{
Super::UnPossessed();
if (CharacterMovement)
{
CharacterMovement->ResetPredictionData_Client();
CharacterMovement->ResetPredictionData_Server();
}
void ACharacter::TornOff()
{
Super::TornOff();
if (CharacterMovement)
{
CharacterMovement->ResetPredictionData_Client();
CharacterMovement->ResetPredictionData_Server();
}
void ACharacter::BaseChange()
{
if (CharacterMovement && CharacterMovement->MovementMode != MOVE_None)
{
AActor* ActualMovementBase = GetMovementBaseActor(this);
if ((ActualMovementBase != NULL) && !ActualMovementBase->CanBeBaseForCharacter(this))
{
CharacterMovement->JumpOff(ActualMovementBase);
}
}
}
void ACharacter::DisplayDebug(UCanvas* Canvas, const FDebugDisplayInfo& DebugDisplay, float& YL, float& YPos)
{
Super::DisplayDebug(Canvas, DebugDisplay, YL, YPos);
FString BaseString;
if ( CharacterMovement == NULL || BasedMovement.MovementBase == NULL )
{
BaseString = "Not Based";
}
else
{
BaseString = BasedMovement.MovementBase->IsWorldGeometry() ? "World Geometry" : BasedMovement.MovementBase->GetName();
BaseString = FString::Printf(TEXT("Based On %s"), *BaseString);
}
if ( CharacterMovement != NULL )
{
CharacterMovement->DisplayDebug(Canvas, DebugDisplay, YL, YPos);
}
const bool Crouched = CharacterMovement && CharacterMovement->IsCrouching();
FString T = FString::Printf(TEXT("Crouched %i"), Crouched);
YL = Canvas->DrawText(RenderFont, T, Indent, YPos );
YPos += YL;
}
}
if (CharacterMovement)
{
FVector FinalVel = LaunchVelocity;
const FVector Velocity = GetVelocity();
if (!bXYOverride)
{
FinalVel.X += Velocity.X;
FinalVel.Y += Velocity.Y;
}
if (!bZOverride)
{
FinalVel.Z += Velocity.Z;
}
CharacterMovement->Launch(FinalVel);
/** Don't process landed notification if updating client position by replaying moves.
* Allow event to be called if Pawn was initially falling (before starting to replay moves),
* and this is going to cause him to land. . */
bool ACharacter::ShouldNotifyLanded(const FHitResult& Hit)
{
if (bClientUpdating && !bClientWasFalling)
{
return false;
}
// Just in case, only allow Landed() to be called once when replaying moves.
bClientWasFalling = false;
return true;
}
void ACharacter::Jump()
{
bPressedJump = true;
JumpKeyHoldTime = 0.0f;
}
void ACharacter::StopJumping()
{
bPressedJump = false;
JumpKeyHoldTime = 0.0f;
}
void ACharacter::ClearJumpInput()
{
// Don't disable bPressedJump right away if it's still held
if (bPressedJump && (JumpKeyHoldTime >= GetJumpMaxHoldTime()))
{
bPressedJump = false;
}
}
//
// Static variables for networking.
//
static uint8 SavedMovementMode;
void ACharacter::PreNetReceive()
{
SavedMovementMode = ReplicatedMovementMode;
Super::PreNetReceive();
}
void ACharacter::PostNetReceive()
{
if (Role == ROLE_SimulatedProxy)
{
CharacterMovement->bNetworkUpdateReceived = true;
CharacterMovement->bNetworkMovementModeChanged = (CharacterMovement->bNetworkMovementModeChanged || (SavedMovementMode != ReplicatedMovementMode));
}
Super::PostNetReceive();
}
void ACharacter::OnRep_ReplicatedBasedMovement()
{
if (Role != ROLE_SimulatedProxy)
{
return;
}
// Skip base updates while playing root motion, it is handled inside of OnRep_RootMotion
if (IsPlayingNetworkedRootMotionMontage())
{
return;
}
// Make sure to use the values of relative location/rotation etc from the server.
BasedMovement = ReplicatedBasedMovement;
if (ReplicatedBasedMovement.HasRelativeLocation())
{
// Update transform relative to movement base
const FVector OldLocation = GetActorLocation();
const FQuat OldRotation = GetActorQuat();
MovementBaseUtility::GetMovementBaseTransform(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName, CharacterMovement->OldBaseLocation, CharacterMovement-
>OldBaseQuat);
const FVector NewLocation = CharacterMovement->OldBaseLocation + ReplicatedBasedMovement.Location;
if (ReplicatedBasedMovement.HasRelativeRotation())
{
// Relative location, relative rotation
FRotator NewRotation = (FRotationMatrix(ReplicatedBasedMovement.Rotation) * FQuatRotationMatrix(CharacterMovement->OldBaseQuat)).Rotator();
SetActorLocationAndRotation(NewLocation, NewRotation);
}
else
{
// Relative location, absolute rotation
SetActorLocationAndRotation(NewLocation, ReplicatedBasedMovement.Rotation);
}
// When position or base changes, movement mode will need to be updated. This assumes rotation changes don't affect that.
CharacterMovement->bJustTeleported |= (bBaseChanged || GetActorLocation() != OldLocation);
void ACharacter::OnRep_ReplicatedMovement()
{
// Skip standard position correction if we are playing root motion, OnRep_RootMotion will handle it.
if (!IsPlayingNetworkedRootMotionMontage())
{
Super::OnRep_ReplicatedMovement();
}
}
void ACharacter::OnRep_RootMotion()
{
if( Role == ROLE_SimulatedProxy )
{
UE_LOG(LogRootMotion, Log, TEXT("ACharacter::OnRep_RootMotion"));
// Delete this move and any prior one, we don't need them anymore.
UE_LOG(LogRootMotion, Log, TEXT("\tClearing old moves (%d)"), MoveIndex+1);
RootMotionRepMoves.RemoveAt(0, MoveIndex+1);
}
}
}
// Start with most recent move and go back in time to find a usable move.
for(int32 MoveIndex=RootMotionRepMoves.Num()-1; MoveIndex>=0; MoveIndex--)
{
if( CanUseRootMotionRepMove(RootMotionRepMoves[MoveIndex], ClientMontageInstance) )
{
FoundIndex = MoveIndex;
break;
}
}
// We can only extract root motion if we are within the same section.
// It's not trivial to jump through sections in a deterministic manner, but that is luckily not frequent.
const bool bSameSections = (AnimMontage->GetSectionIndexFromPosition(ServerPosition) == CurrentSectionIndex);
// if we are looping and just wrapped over, skip. That's also not easy to handle and not frequent.
const bool bHasLooped = (NextSectionIndex == CurrentSectionIndex) && (FMath::Abs(DeltaPosition) > (AnimMontage->GetSectionLength(CurrentSectionIndex) / 2.f));
// Can only simulate forward in time, so we need to make sure server move is not ahead of the client.
const bool bServerAheadOfClient = ((DeltaPosition * ClientMontageInstance.GetPlayRate()) < 0.f);
UE_LOG(LogRootMotion, Log, TEXT("\t\tACharacter::CanUseRootMotionRepMove ServerPosition: %.3f, ClientPosition: %.3f, DeltaPosition: %.3f, bSameSections: %d, bHasLooped:
%d, bServerAheadOfClient: %d"),
ServerPosition, ClientPosition, DeltaPosition, bSameSections, bHasLooped, bServerAheadOfClient);
// Relative Position
if( RootMotionRepMove.RootMotion.bRelativePosition )
{
bool bSuccess = false;
if( MovementBaseUtility::UseRelativeLocation(ServerBase) )
{
FVector BaseLocation;
FQuat BaseRotation;
MovementBaseUtility::GetMovementBaseTransform(ServerBase, ServerBaseBoneName, BaseLocation, BaseRotation);
UpdateSimulatedPosition(ServerLocation, ServerRotation);
bSuccess = true;
}
// If we received local space position, but can't resolve parent, then move can't be used. :(
if( !bSuccess )
{
return false;
}
}
// Absolute position
else
{
UpdateSimulatedPosition(RootMotionRepMove.RootMotion.Location, RootMotionRepMove.RootMotion.Rotation);
}
return true;
}
// Only need to check for encroachment when teleported without any velocity.
// Normal movement pops the character out of geometry anyway, no use doing it before and after (with different rules).
bSimGravityDisabled = false;
if (CharacterMovement->Velocity.IsZero())
{
if (GetWorld()->EncroachingBlockingGeometry(this, NewLocation, NewRotation))
{
bSimGravityDisabled = true;
}
}
void ACharacter::PostNetReceiveLocationAndRotation()
{
if( Role == ROLE_SimulatedProxy )
{
// Don't change transform if using relative position (it should be nearly the same anyway, or base may be slightly out of sync)
if (!ReplicatedBasedMovement.HasRelativeLocation())
{
const FVector OldLocation = GetActorLocation();
const FQuat OldRotation = GetActorQuat();
UpdateSimulatedPosition(ReplicatedMovement.Location, ReplicatedMovement.Rotation);
if ( RootMotionMontageInstance )
{
// Is position stored in local space?
RepRootMotion.bRelativePosition = BasedMovement.HasRelativeLocation();
RepRootMotion.bRelativeRotation = BasedMovement.HasRelativeRotation();
RepRootMotion.Location = RepRootMotion.bRelativePosition ? BasedMovement.Location : GetActorLocation();
RepRootMotion.Rotation = RepRootMotion.bRelativeRotation ? BasedMovement.Rotation : GetActorRotation();
RepRootMotion.MovementBase = BasedMovement.MovementBase;
RepRootMotion.MovementBaseBoneName = BasedMovement.BoneName;
RepRootMotion.AnimMontage = RootMotionMontageInstance->Montage;
RepRootMotion.Position = RootMotionMontageInstance->GetPosition();
ReplicatedMovementMode = CharacterMovement->PackNetworkMovementMode();
ReplicatedBasedMovement = BasedMovement;
// Optimization: only update and replicate these values if they are actually going to be used.
if (BasedMovement.HasRelativeLocation())
{
// When velocity becomes zero, force replication so the position is updated to match the server (it may have moved due to simulation on the client).
ReplicatedBasedMovement.bServerHasVelocity = !CharacterMovement->Velocity.IsZero();
// Make sure absolute rotations are updated in case rotation occurred after the base info was saved.
if (!BasedMovement.HasRelativeRotation())
{
ReplicatedBasedMovement.Rotation = GetActorRotation();
}
}
}
return Duration;
}
}
return 0.f;
}
if ( bShouldStopMontage )
{
AnimInstance->Montage_Stop(MontageToStop->BlendOutTime, MontageToStop);
}
}
return NULL;
}
void ACharacter::ClientCheatWalk_Implementation()
{
SetActorEnableCollision(true);
if (CharacterMovement)
{
CharacterMovement->bCheatFlying = false;
CharacterMovement->SetMovementMode(MOVE_Falling);
}
}
void ACharacter::ClientCheatFly_Implementation()
{
SetActorEnableCollision(true);
if (CharacterMovement)
{
CharacterMovement->bCheatFlying = true;
CharacterMovement->SetMovementMode(MOVE_Flying);
}
}
void ACharacter::ClientCheatGhost_Implementation()
{
SetActorEnableCollision(false);
if (CharacterMovement)
{
CharacterMovement->bCheatFlying = true;
CharacterMovement->SetMovementMode(MOVE_Flying);
}
}
/** Returns Mesh subobject **/
USkeletalMeshComponent* ACharacter::GetMesh() const {
return Mesh;
}
#if WITH_EDITORONLY_DATA
/** Returns ArrowComponent subobject **/
UArrowComponent* ACharacter::GetArrowComponent() const {
return ArrowComponent;
}
#endif
/** Returns CharacterMovement subobject **/
UCharacterMovementComponent* ACharacter::GetCharacterMovement() const {
return CharacterMovement;
}
/** Returns CapsuleComponent subobject **/
UCapsuleComponent* ACharacter::GetCapsuleComponent() const {
return CapsuleComponent;
}
EXAMPLE #11
#include "BET.h"
#include "BETCharacter.h"
#include "BETProjectile.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/InputSettings.h"
#include "BETProjectileWeapon.h"
#include "BETWeapon.h"
//////////////////////////////////////////////////////////////////////////
// ABETCharacter
ABETCharacter::ABETCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
// Create a gun mesh component
FP_Gun = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FP_Gun"));
FP_Gun->SetOnlyOwnerSee(true); // only the owning player will see this mesh
FP_Gun->bCastDynamicShadow = false;
FP_Gun->CastShadow = false;
FP_Gun->AttachTo(Mesh1P, TEXT("GripPoint"), EAttachLocation::SnapToTargetIncludingScale, true);
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
void ABETCharacter::BeginPlay()
{
Super::BeginPlay();
if (WeaponClass)
{
FActorSpawnParameters SpawnParameters;
SpawnParameters.Instigator = this;
Weapon = GetWorld()->SpawnActor<ABETWeapon>(WeaponClass, SpawnParameters);
Weapon->AttachRootComponentToActor(this);
}
}
//////////////////////////////////////////////////////////////////////////
// Input
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &ABETCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &ABETCharacter::LookUpAtRate);
}
void ABETCharacter::OnFire()
{
if (Weapon){
Weapon->Fire();
}
if (ScaledDelta.X != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.X * BaseTurnRate;
AddControllerYawInput(Value);
}
if (ScaledDelta.Y != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.Y* BaseTurnRate;
AddControllerPitchInput(Value);
}
TouchItem.Location = Location;
}
TouchItem.Location = Location;
}
}
}
}
#include "Wizards.h"
#include "WizardsCharacter.h"
#include "WizardsProjectile.h"
#include "WizardsBlast.h"
#include "WizardsCone.h"
#include "WizardsSaveGame.h"
#include "UnrealNetwork.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/InputSettings.h"
//////////////////////////////////////////////////////////////////////////
// AWizardsCharacter
AWizardsCharacter::AWizardsCharacter()
{
bReplicates = true;
//Tick for mana regen
PrimaryActorTick.bCanEverTick = true;
//Set Health and Mana
Health = 100.0;
maxHealth = 100.0;
Mana = 100.0;
maxMana = 100.0;
//Spell Stuff for Testing
//SList.spellCost = 10.0;
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Sparks.P_Sparks'"));
//SList.myParticle = ArbitraryParticleName.Object;
//SList.test = &ArbitraryParticleName;
currSpell = 0;
//For the record, this probably isn't the best way to get particles for the spells but it works
//A better method, implemented at a later and unknown date, would be to hold this array in its own class
//that is called once and never destroyed
//Projectiles
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName0(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Fire_Projectile.P_Fire_Projectile'"));
particleList.Add(ArbitraryParticleName0.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName1(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Lightning_Projectile.P_Lightning_Projectile'"));
particleList.Add(ArbitraryParticleName1.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName2(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Water_Projectile.P_Water_Projectile'"));
particleList.Add(ArbitraryParticleName2.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName3(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Ice_Projectile.P_Ice_Projectile'"));
particleList.Add(ArbitraryParticleName3.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName4(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Earth_Projectile.P_Earth_Projectile'"));
particleList.Add(ArbitraryParticleName4.Object);
//Now for all of the EXPLOSIONS
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName5(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Fire_Blast.P_Fire_Blast'"));
particleList.Add(ArbitraryParticleName5.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName6(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Lightning_Blast.P_Lightning_Blast'"));
particleList.Add(ArbitraryParticleName6.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName7(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Water_Blast.P_Water_Blast'"));
particleList.Add(ArbitraryParticleName7.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName8(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Ice_Blast.P_Ice_Blast'"));
particleList.Add(ArbitraryParticleName8.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName9(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Earth_Blast.P_Earth_Blast'"));
particleList.Add(ArbitraryParticleName9.Object);
//Next up is cones
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName10(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Fire_Cone.P_Fire_Cone'"));
particleList.Add(ArbitraryParticleName10.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName11(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Lightning_Cone.P_Lightning_Cone'"));
particleList.Add(ArbitraryParticleName11.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName12(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Water_Cone.P_Water_Cone'"));
particleList.Add(ArbitraryParticleName12.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName13(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Ice_Cone.P_Ice_Cone'"));
particleList.Add(ArbitraryParticleName13.Object);
ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName14(TEXT("ParticleSystem'/Game/FirstPerson/Particles/P_Earth_Cone.P_Earth_Cone'"));
particleList.Add(ArbitraryParticleName14.Object);
//spell test;
//SList.Add(test);
//SList[currSpell].spellCost = 10.0;
//SList[currSpell].theWizard = this;
//SList[currSpell].canBounce = true;
//ConstructorHelpers::FObjectFinder<UParticleSystem> ArbitraryParticleName8(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Sparks.P_Sparks'"));
//SList[currSpell].myParticle = ArbitraryParticleName8.Object;
//SList.test = &ArbitraryParticleName;
//SList.particleLocation = FName(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Sparks.P_Sparks'"));
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true); // only the owning player will see this mesh
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->RelativeLocation = FVector(0.f, 0.f, -150.f);
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
void AWizardsCharacter::newCharactersSpells()
{
UWizardsSaveGame* LoadGameInstance = NewObject<UWizardsSaveGame>();
// spellList = LoadGameInstance->spellList;
//if is empty
if (LoadGameInstance->LoadGameDataFromFile()) {
/////////////
// On Tick
void AWizardsCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (Mana <= maxMana) {
Mana += DeltaTime;
}
}
//////////////////////////////////////////////////////////////////////////
// Input
void AWizardsCharacter::OnFire()
{
if (!mySpellBook.IsValidIndex(0)) {
UE_LOG(LogTemp, Warning, TEXT("Spell Gathering Needed!"));
newCharactersSpells();
}
if (Mana > mySpellBook[currSpell].spellCost) {
Mana -= mySpellBook[currSpell].spellCost;
// try and fire a projectile
if (mySpellBook[currSpell].spellType == 0)
{
const FRotator SpawnRotation = GetControlRotation();
const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
}
}
void AWizardsCharacter::OffFire() {
if (activeAttack != NULL) {
activeAttack->Destroy();
ServerDestroyCone(activeAttack);
}
}
template<int newspell>
void AWizardsCharacter::spellSwitch()
{
currSpell = newspell;
}
float AWizardsCharacter::GetHealth() {
return Health;
}
float AWizardsCharacter::GetMana() {
return Mana;
}
}
else if (theSpell->spellType == 1) {
const FRotator SpawnRotation = FRotator(0.0);//GetControlRotation();
const FVector SpawnLocation = FVector(0.0);//GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
AWizardsBlast* wizardsSpell = World->SpawnActor<AWizardsBlast>(BlastClass, SpawnLocation, SpawnRotation);// , myparams);
wizardsSpell->SpellCreation(theSpell->myParticle, theSpell->spellSize, theSpell->spellDamage, this);
wizardsSpell->AttachRootComponentTo(GetCapsuleComponent());//Probably useful for Blasts, Rays, and Conical attacks
UE_LOG(LogTemp, Warning, TEXT("Boom!"));
}
else if (theSpell->spellType == 2) {
const FRotator SpawnRotation = FRotator(0.0);//GetControlRotation();
const FVector SpawnLocation = FVector(0.0);//GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
AWizardsCone* wizardsCone = World->SpawnActor<AWizardsCone>(ConeClass, SpawnLocation, SpawnRotation);// , myparams);
wizardsCone->SpellCreation(theSpell->myParticle, theSpell->spellSize, theSpell->spellDamage, this);
wizardsCone->AttachRootComponentTo(GetCapsuleComponent());//Probably useful for Blasts, Rays, and Conical attacks
activeAttack = Cast<AActor>(wizardsCone);
UE_LOG(LogTemp, Warning, TEXT("Svoosh!"));
}*/
}
bool AWizardsCharacter::ServerFireProjectile_Validate(FtheSpell castSpell, FRotator rotation, FVector location) {
return true;
}
//UE_LOG(LogTemp, Warning, TEXT("Role %d has currSpell %d and SpawnRotation "), Role, currSpell);
if (castSpell.spellType == 0)
{
UWorld* const World = GetWorld();
if (World)
{
// spawn the projectile at the muzzle
UParticleSystem* projParticle = particleList[castSpell.spellEffect + castSpell.spellType * 5];
UParticleSystem* blastParticle = particleList[castSpell.spellEffect + 5];
AWizardsProjectile* wizardsSpell = World->SpawnActor<AWizardsProjectile>(ProjectileClass, location, rotation);// , myparams);
wizardsSpell->SpellCreation(&castSpell, projParticle, blastParticle, this);
}
}
else if (castSpell.spellType == 1) {
UWorld* const World = GetWorld();
if (World)
{
// spawn the projectile at the muzzle
UParticleSystem* blastParticle = particleList[castSpell.spellEffect + castSpell.spellType * 5];
AWizardsBlast* wizardsSpell = World->SpawnActor<AWizardsBlast>(BlastClass, location, rotation);// , myparams);
wizardsSpell->SpellCreation(blastParticle, castSpell.spellSize, castSpell.spellDamage, this);
wizardsSpell->AttachRootComponentTo(GetCapsuleComponent());//Probably useful for Blasts, Rays, and Conical attacks
}
}
else if (castSpell.spellType == 2) {
UWorld* const World = GetWorld();
if (World)
{
// spawn the projectile at the muzzle
UParticleSystem* coneParticle = particleList[castSpell.spellEffect + castSpell.spellType * 5];
AWizardsCone* wizardsCone = World->SpawnActor<AWizardsCone>(ConeClass, location, rotation);// , myparams);
wizardsCone->SpellCreation(coneParticle, castSpell.spellSize, castSpell.spellDamage, this);
wizardsCone->AttachRootComponentTo(GetCapsuleComponent());//Probably useful for Blasts, Rays, and Conical attacks
activeAttack = Cast<AActor>(wizardsCone);
}
}
}
bool AWizardsCharacter::ClientFireProjectile_Validate(FtheSpell castSpell, FRotator rotation, FVector location){
return true;
}
}
bool AWizardsCharacter::ServerDestroyCone_Validate(AActor* theActor) {
return true;
}