Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VFX improvement #94

Merged
merged 5 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Cloud9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Cloud9.uproject
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@
"Name": "EditorScriptingUtilities",
"Enabled": true
}
],
"TargetPlatforms": [
"WindowsNoEditor"
]
}
Binary file modified Content/Blueprints/Weapons/FirearmWeaponsTable.uasset
Binary file not shown.
Binary file modified Content/Blueprints/Weapons/WeaponTableDefinitions.uasset
Binary file not shown.
Binary file modified Content/Maps/de_train/tools_wrongway_timer.uasset
Binary file not shown.
Binary file modified Content/Maps/warmup.umap
Binary file not shown.
Binary file added Content/Vefects/VFX/Tracers/FirearmTracer.uasset
Binary file not shown.
Binary file not shown.
25 changes: 24 additions & 1 deletion Source/Cloud9/Character/Cloud9Character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@
#include "Components/DecalComponent.h"
#include "Components/CapsuleComponent.h"

#include "Cloud9/Game/Cloud9GameInstance.h"
#include "Cloud9/Game/Cloud9DeveloperSettings.h"
#include "Cloud9/Game/Cloud9PlayerController.h"
#include "Cloud9/Character/Components/Cloud9CharacterMovement.h"
#include "Cloud9/Character/Components/Cloud9Inventory.h"
#include "Cloud9/Character/Components/Cloud9SpringArmComponent.h"
#include "Cloud9/Tools/Extensions/TContainer.h"

class UCloud9SpringArmComponent;
const FName ACloud9Character::SpringArmComponentName = TEXT("CameraBoom");
const FName ACloud9Character::CameraComponentName = TEXT("TopDownCamera");
const FName ACloud9Character::DecalComponentName = TEXT("CursorToWorld");
Expand Down Expand Up @@ -255,3 +256,25 @@ void ACloud9Character::OnConstruction(const FTransform& Transform)
MyMesh->bAffectDynamicIndirectLighting = true;
}
}

void ACloud9Character::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);

// Auto select any available weapon if nothing selected
if (not Inventory->GetSelectedWeapon())
{
Inventory->SelectOtherAvailableWeapon(false);
}

// TODO: Remove auto grenade add after debug
if (not Inventory->GetWeaponAt(EWeaponSlot::Grenade) and Inventory->GetSelectedWeapon() != nullptr)
{
if (let GameInstance = GetGameInstance<UCloud9GameInstance>(); IsValid(GameInstance))
{
GameInstance->GetDefaultWeaponsConfig()
| ETContainer::Filter{[this](let& Config) { return IsValid(Config) and Config.IsGrenadeWeapon(); }}
| ETContainer::ForEach{[this](let& Config) { Inventory->AddWeapon(Config); }};
}
}
}
1 change: 1 addition & 0 deletions Source/Cloud9/Character/Cloud9Character.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class ACloud9Character : public ACharacter
ACloud9Character(const FObjectInitializer& ObjectInitializer);

virtual void OnConstruction(const FTransform& Transform) override;
virtual void Tick(float DeltaSeconds) override;

/** Returns TopDownCameraComponent subobject **/
FORCEINLINE class UCameraComponent* GetTopDownCameraComponent() const { return TopDownCameraComponent; }
Expand Down
66 changes: 16 additions & 50 deletions Source/Cloud9/Character/Components/Cloud9Inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@

UCloud9Inventory::UCloud9Inventory()
{
PrimaryComponentTick.bCanEverTick = true;

SelectedWeaponSlot = EWeaponSlot::NotSelected;

let SlotsNumber = StaticEnum<EWeaponSlot>()->NumEnums();
Expand Down Expand Up @@ -73,45 +71,7 @@ void UCloud9Inventory::BeginPlay()
}
}

void UCloud9Inventory::TickComponent(
float DeltaTime,
ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

// Auto select any available weapon if nothing selected
if (not GetSelectedWeapon())
{
SelectOtherAvailableWeapon(false);
}

if (not GetWeaponAt(EWeaponSlot::Grenade) and GetSelectedWeapon() != nullptr)
{
// TODO: Remove auto grenade add after debug

let MyOwner = GetOwner<ACloud9Character>();

if (not IsValid(MyOwner))
{
log(Error, "[Actor='%s'] ACloud9Character isn't valid", *GetName());
return;
}

let GameInstance = MyOwner->GetGameInstance<UCloud9GameInstance>();

if (not IsValid(GameInstance))
{
log(Error, "[Actor='%s'] UCloud9GameInstance isn't valid", *GetName());
}

GameInstance->GetDefaultWeaponsConfig()
| ETContainer::Filter{[this](let& Config) { return IsValid(Config) and Config.IsGrenadeWeapon(); }}
| ETContainer::ForEach{[this](let& Config) { AddWeapon(Config); }};
}
}

bool UCloud9Inventory::SelectWeapon(EWeaponSlot Slot, bool Instant)
bool UCloud9Inventory::SelectWeapon(EWeaponSlot Slot, bool Instant, bool Force)
{
if (Slot == EWeaponSlot::NotSelected)
{
Expand Down Expand Up @@ -148,7 +108,7 @@ bool UCloud9Inventory::SelectWeapon(EWeaponSlot Slot, bool Instant)
"[Inventory='%s'] SelectedWeapon should not be valid if slot == EWeaponSlot::NotSelected",
*GetName());

if (PendingWeapon->ChangeState(EWeaponBond::Armed, Instant))
if (PendingWeapon->ChangeState(EWeaponBond::Armed, Instant, Force))
{
SelectedWeaponSlot = Slot;
return true;
Expand All @@ -160,14 +120,20 @@ bool UCloud9Inventory::SelectWeapon(EWeaponSlot Slot, bool Instant)

if (let SelectedWeapon = GetSelectedWeapon(); IsValid(SelectedWeapon))
{
SelectedWeapon->ChangeState(EWeaponBond::Holstered, true);
if (not SelectedWeapon->ChangeState(EWeaponBond::Holstered, true, Force))
{
log(Verbose,
"[Inventory='%s'] Can't change state of selected weapon from slot='%d'",
*GetName(), SelectedWeaponSlot);
return false;
}
}

if (not PendingWeapon->ChangeState(EWeaponBond::Armed, Instant))
if (not PendingWeapon->ChangeState(EWeaponBond::Armed, Instant, Force))
{
log(Verbose,
"[Inventory='%s'] Can't change state of pending weapon slot='%d'",
*GetName(), SelectedWeaponSlot);
"[Inventory='%s'] Can't change state of pending weapon to slot='%d'",
*GetName(), Slot);
return false;
}

Expand Down Expand Up @@ -324,9 +290,9 @@ bool UCloud9Inventory::RemoveWeapon(EWeaponSlot Slot)
return false;
}

if (Slot == SelectedWeaponSlot)
if (Slot == SelectedWeaponSlot and not SelectOtherAvailableWeapon(true))
{
SelectOtherAvailableWeapon(true);
return false;
}

WeaponAt(Slot)->Destroy();
Expand All @@ -335,7 +301,7 @@ bool UCloud9Inventory::RemoveWeapon(EWeaponSlot Slot)
return true;
}

bool UCloud9Inventory::SelectOtherAvailableWeapon(bool Instant)
bool UCloud9Inventory::SelectOtherAvailableWeapon(bool Instant, bool Force)
{
EWeaponSlot NewSlot = EWeaponSlot::NotSelected;
let Found = WeaponSlots
Expand All @@ -345,7 +311,7 @@ bool UCloud9Inventory::SelectOtherAvailableWeapon(bool Instant)

log(Verbose, "[Inventory='%s'] Change selected slot to '%d'", *GetName(), NewSlot);

return SelectWeapon(NewSlot, Instant);
return SelectWeapon(NewSlot, Instant, Force);
}

ACloud9WeaponBase* UCloud9Inventory::GetSelectedWeapon() const { return GetWeaponAt(SelectedWeaponSlot); }
Expand Down
10 changes: 4 additions & 6 deletions Source/Cloud9/Character/Components/Cloud9Inventory.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ class CLOUD9_API UCloud9Inventory
*
* @param Slot New slot weapon slot.
* @param Instant If set then no animation will be shown and switching will be instant.
* @param Force If set then other weapon will be selected even if animation playing
*/
UFUNCTION(BlueprintCallable)
bool SelectWeapon(EWeaponSlot Slot, bool Instant = false);
bool SelectWeapon(EWeaponSlot Slot, bool Instant = false, bool Force = false);

bool SelectOtherAvailableWeapon(bool Instant);
UFUNCTION(BlueprintCallable)
bool SelectOtherAvailableWeapon(bool Instant, bool Force = false);

UFUNCTION(BlueprintCallable)
ACloud9WeaponBase* GetWeaponAt(EWeaponSlot Slot) const;
Expand Down Expand Up @@ -101,10 +103,6 @@ class CLOUD9_API UCloud9Inventory

protected:
virtual void BeginPlay() override;
virtual void TickComponent(
float DeltaTime,
ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;

template <typename WeaponType = ACloud9WeaponBase>
WeaponType* WeaponAt(EWeaponSlot Slot) const { return WeaponSlots[Slot | EUEnum::To<int>{}]; }
Expand Down
14 changes: 7 additions & 7 deletions Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ bool ACloud9WeaponBase::UpdateWeaponAttachment(EWeaponSlot NewSlot, EWeaponBond
return false;
}

log(Verbose,
log(Display,
"[Weapon='%s' Slot='%s'] Update attachment to character '%s' into socket '%s'",
*GetName(), SLOT_NAME, *Character->GetName(), *SocketName.ToString());

Expand Down Expand Up @@ -419,27 +419,27 @@ bool ACloud9WeaponBase::RemoveFromInventory()
return true;
}

bool ACloud9WeaponBase::ChangeState(EWeaponBond NewBond, bool Instant)
bool ACloud9WeaponBase::ChangeState(EWeaponBond NewBond, bool Instant, bool Force)
{
if (let Character = GetOwner<ACloud9Character>(); not IsValid(Character))
{
log(Warning, "[Weapon='%s' Bond='%s'] Weapon not in any inventory", *GetName(), BOND_NAME);
log(Error, "[Weapon='%s' Bond='%s'] Weapon not in any inventory", *GetName(), BOND_NAME);
return false;
}

if (WeaponState.IsWeaponBond(NewBond))
{
log(Verbose, "[Weapon='%s' Bond='%s'] Weapon will remain the same", *GetName(), BOND_NAME);
log(Error, "[Weapon='%s' Bond='%s'] Weapon will remain the same", *GetName(), BOND_NAME);
return false;
}

if (IsAnyMontagePlaying())
if (not Force and IsAnyMontagePlaying())
{
log(Verbose, "[Weapon='%s' Bond='%s'] Montage is playing now", *GetName(), BOND_NAME);
return false;
}

if (IsActionInProgress())
if (not Force and IsActionInProgress())
{
log(Verbose, "[Weapon='%s' Bond='%s'] Some action is in progress", *GetName(), BOND_NAME);
return false;
Expand All @@ -451,7 +451,7 @@ bool ACloud9WeaponBase::ChangeState(EWeaponBond NewBond, bool Instant)
void ACloud9WeaponBase::PrimaryAction(bool IsReleased)
{
WeaponState.ActivateSequence(
EWeaponAction::Primary,
EWeaponAction::PrimaryStart,
EWeaponAction::PrimaryLoop,
EWeaponAction::PrimaryEnd,
IsReleased);
Expand Down
2 changes: 1 addition & 1 deletion Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class CLOUD9_API ACloud9WeaponBase : public AActor
bool AddToInventory(ACloud9Character* Character, EWeaponSlot NewSlot);
bool RemoveFromInventory();

bool ChangeState(EWeaponBond NewBond, bool Instant);
bool ChangeState(EWeaponBond NewBond, bool Instant, bool Force = false);

template <typename OnExecuteType, typename OnCompleteType>
FORCEINLINE bool ExecuteAction(
Expand Down
55 changes: 41 additions & 14 deletions Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "Cloud9WeaponFirearm.h"
#include "Engine/StaticMeshActor.h"
#include "NiagaraFunctionLibrary.h"

#include "Cloud9/Tools/Macro/Common.h"
#include "Cloud9/Tools/Macro/Logging.h"
Expand All @@ -33,6 +34,9 @@
#include "Cloud9/Character/Cloud9Character.h"
#include "Cloud9/Weapon/Tables/WeaponTableFirearm.h"

const FName ACloud9WeaponFirearm::TracerProbabilityParameterName = TEXT("Probability");
const FName ACloud9WeaponFirearm::TracerDirectionParameterName = TEXT("Direction");

FWeaponId ACloud9WeaponFirearm::GetWeaponId() const { return ETVariant::Convert<FWeaponId>(WeaponId); }

bool ACloud9WeaponFirearm::OnInitialize(const FWeaponId& NewWeaponId, FName NewWeaponSkin)
Expand Down Expand Up @@ -159,14 +163,14 @@ void ACloud9WeaponFirearm::Tick(float DeltaSeconds)
[this] { WeaponState.ClearAction(EWeaponAction::Deploy); }
);
}
else if (WeaponState.IsActionActive(EWeaponAction::Primary))
else if (WeaponState.IsActionActive(EWeaponAction::PrimaryStart))
{
WeaponState.ClearAction(EWeaponAction::Primary);
WeaponState.ClearAction(EWeaponAction::PrimaryStart);
}
else if (WeaponState.IsActionActive(EWeaponAction::PrimaryLoop))
{
ExecuteAction(
EWeaponAction::Primary,
EWeaponAction::PrimaryStart,
WeaponInfo->CycleTime,
[&]
{
Expand All @@ -179,7 +183,7 @@ void ACloud9WeaponFirearm::Tick(float DeltaSeconds)
// TODO: May be move to notifier?
MuzzleFlash->Activate(true);

if (not Fire(WeaponInfo, CommonData->ImpulseMultiplier))
if (not Fire(WeaponInfo, CommonData->Firearm))
{
log(Error, "[Weapon='%s'] Weapon fire failure", *GetName());
return false;
Expand All @@ -191,7 +195,7 @@ void ACloud9WeaponFirearm::Tick(float DeltaSeconds)

if (not WeaponInfo->bIsFullAuto)
{
WeaponState.ClearAction(EWeaponAction::Primary);
WeaponState.ClearAction(EWeaponAction::PrimaryStart);
}
}
else if (WeaponState.IsActionActive(EWeaponAction::PrimaryEnd))
Expand All @@ -209,7 +213,7 @@ const FFirearmWeaponInfo* ACloud9WeaponFirearm::GetWeaponInfo() const
return WeaponDefinition.GetWeaponInfo<FFirearmWeaponInfo>();
}

bool ACloud9WeaponFirearm::Fire(const FFirearmWeaponInfo* WeaponInfo, float ImpulseMultiplier) const
bool ACloud9WeaponFirearm::Fire(const FFirearmWeaponInfo* WeaponInfo, const FFirearmCommonData& FirearmCommonData) const
{
let Character = GetOwner<ACloud9Character>();

Expand Down Expand Up @@ -250,10 +254,33 @@ bool ACloud9WeaponFirearm::Fire(const FFirearmWeaponInfo* WeaponInfo, float Impu

log(Verbose, "Target = %s Owner = %s", *Target->GetName(), *Target->GetOwner()->GetName());

let Direction = (LineHit.Location - StartLocation) | EFVector::Normalize{};

if (Target->IsSimulatingPhysics() and Target->Mobility == EComponentMobility::Movable)
{
let Direction = (LineHit.Location - StartLocation) | EFVector::Normalize{};
Target->AddImpulse(WeaponInfo->Damage * ImpulseMultiplier * Direction, NAME_None, true);
let Velocity = WeaponInfo->Damage * FirearmCommonData.ImpulseMultiplier * Direction;
Target->AddImpulse(Velocity, NAME_None, true);
}

if (IsValid(FirearmCommonData.Tracer))
{
let Tracer = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
GetWorld(),
FirearmCommonData.Tracer,
StartLocation);
Tracer->SetVectorParameter(TracerDirectionParameterName, Direction);
Tracer->SetFloatParameter(TracerProbabilityParameterName, WeaponInfo->TracerProbability);
Tracer->SetAutoDestroy(true);
}

if (IsValid(FirearmCommonData.Squib))
{
let Squib = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
GetWorld(),
FirearmCommonData.Squib,
LineHit.Location,
CursorHit.Normal.Rotation());
Squib->SetAutoDestroy(true);
}

return true;
Expand Down Expand Up @@ -354,7 +381,7 @@ void ACloud9WeaponFirearm::DropMagazine() const
Mesh->SetSimulatePhysics(true);
Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

Magazine | EAActor::DestroyAfter{WeaponDefinition.GetCommonData()->MagazineLifetime};
Magazine | EAActor::DestroyAfter{WeaponDefinition.GetCommonData()->Firearm.MagazineLifetime};
}

void ACloud9WeaponFirearm::EjectCase() const
Expand Down Expand Up @@ -382,8 +409,8 @@ void ACloud9WeaponFirearm::EjectCase() const
let CommonData = WeaponDefinition.GetCommonData();

Case->SetMobility(EComponentMobility::Movable);
Case->SetActorRotation({0.0f, FMath::RandRange(0.0f, CommonData->CaseMaxEjectRotation), 0.0f});
Case->SetActorScale3D({CommonData->CaseScale, CommonData->CaseScale, CommonData->CaseScale});
Case->SetActorRotation({0.0f, FMath::RandRange(0.0f, CommonData->Case.MaxEjectRotation), 0.0f});
Case->SetActorScale3D({CommonData->Case.Scale, CommonData->Case.Scale, CommonData->Case.Scale});

let Mesh = Case->GetStaticMeshComponent();
Mesh->SetStaticMesh(CaseModel);
Expand All @@ -392,9 +419,9 @@ void ACloud9WeaponFirearm::EjectCase() const

let RightVector = GetWeaponMesh()->GetRightVector();
let ForwardVector = GetWeaponMesh()->GetForwardVector();
let ImpulseDirection = RightVector.RotateAngleAxis(CommonData->CaseEjectAngle, ForwardVector);
let ImpulseDirection = RightVector.RotateAngleAxis(CommonData->Case.EjectAngle, ForwardVector);

Mesh->AddImpulse(CommonData->CaseImpulse * ImpulseDirection, NAME_None, true);
Mesh->AddImpulse(CommonData->Case.EjectImpulse * ImpulseDirection, NAME_None, true);

Case | EAActor::DestroyAfter{CommonData->CaseLifetime};
Case | EAActor::DestroyAfter{CommonData->Case.Lifetime};
}
Loading