diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..fbec8216 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,91 @@ +[*.{cpp,h}] + +# Naming convention rules (note: currently need to be ordered from more to less specific) + +cpp_naming_rule.aactor_prefixed.symbols = aactor_class +cpp_naming_rule.aactor_prefixed.style = aactor_style + +cpp_naming_rule.swidget_prefixed.symbols = swidget_class +cpp_naming_rule.swidget_prefixed.style = swidget_style + +cpp_naming_rule.uobject_prefixed.symbols = uobject_class +cpp_naming_rule.uobject_prefixed.style = uobject_style + +cpp_naming_rule.booleans_prefixed.symbols = boolean_vars +cpp_naming_rule.booleans_prefixed.style = boolean_style + +cpp_naming_rule.structs_prefixed.symbols = structs +cpp_naming_rule.structs_prefixed.style = unreal_engine_structs + +cpp_naming_rule.enums_prefixed.symbols = enums +cpp_naming_rule.enums_prefixed.style = unreal_engine_enums + +cpp_naming_rule.templates_prefixed.symbols = templates +cpp_naming_rule.templates_prefixed.style = unreal_engine_templates + +cpp_naming_rule.general_names.symbols = all_symbols +cpp_naming_rule.general_names.style = unreal_engine_default + +# Naming convention symbols + +cpp_naming_symbols.aactor_class.applicable_kinds = class +cpp_naming_symbols.aactor_class.applicable_type = AActor + +cpp_naming_symbols.swidget_class.applicable_kinds = class +cpp_naming_symbols.swidget_class.applicable_type = SWidget + +cpp_naming_symbols.uobject_class.applicable_kinds = class +cpp_naming_symbols.uobject_class.applicable_type = UObject + +cpp_naming_symbols.boolean_vars.applicable_kinds = local,parameter,field +cpp_naming_symbols.boolean_vars.applicable_type = bool + +cpp_naming_symbols.enums.applicable_kinds = enum + +cpp_naming_symbols.templates.applicable_kinds = template_class + +cpp_naming_symbols.structs.applicable_kinds = struct + +cpp_naming_symbols.all_symbols.applicable_kinds = * + +# Naming convention styles + +cpp_naming_style.unreal_engine_default.capitalization = pascal_case +cpp_naming_style.unreal_engine_default.required_prefix = +cpp_naming_style.unreal_engine_default.required_suffix = +cpp_naming_style.unreal_engine_default.word_separator = + +cpp_naming_style.unreal_engine_enums.capitalization = pascal_case +cpp_naming_style.unreal_engine_enums.required_prefix = E +cpp_naming_style.unreal_engine_enums.required_suffix = +cpp_naming_style.unreal_engine_enums.word_separator = + +cpp_naming_style.unreal_engine_templates.capitalization = pascal_case +cpp_naming_style.unreal_engine_templates.required_prefix = T +cpp_naming_style.unreal_engine_templates.required_suffix = +cpp_naming_style.unreal_engine_templates.word_separator = + +cpp_naming_style.unreal_engine_structs.capitalization = pascal_case +cpp_naming_style.unreal_engine_structs.required_prefix = F +cpp_naming_style.unreal_engine_structs.required_suffix = +cpp_naming_style.unreal_engine_structs.word_separator = + +cpp_naming_style.uobject_style.capitalization = pascal_case +cpp_naming_style.uobject_style.required_prefix = U +cpp_naming_style.uobject_style.required_suffix = +cpp_naming_style.uobject_style.word_separator = + +cpp_naming_style.aactor_style.capitalization = pascal_case +cpp_naming_style.aactor_style.required_prefix = A +cpp_naming_style.aactor_style.required_suffix = +cpp_naming_style.aactor_style.word_separator = + +cpp_naming_style.swidget_style.capitalization = pascal_case +cpp_naming_style.swidget_style.required_prefix = S +cpp_naming_style.swidget_style.required_suffix = +cpp_naming_style.swidget_style.word_separator = + +cpp_naming_style.boolean_style.capitalization = pascal_case +cpp_naming_style.boolean_style.required_prefix = b +cpp_naming_style.boolean_style.required_suffix = +cpp_naming_style.boolean_style.word_separator = \ No newline at end of file diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini index 8c03c044..a457e63f 100644 --- a/Config/DefaultInput.ini +++ b/Config/DefaultInput.ini @@ -68,6 +68,7 @@ bCaptureMouseOnLaunch=True bEnableLegacyInputScales=True bEnableMotionControls=True bFilterInputByPlatformUser=False +bEnableInputDeviceSubsystem=True bShouldFlushPressedKeysOnViewportFocusLost=True bEnableDynamicComponentInputBinding=True bAlwaysShowTouchInterface=False @@ -90,6 +91,12 @@ DoubleClickTime=0.200000 +ActionMappings=(ActionName="Reload",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Left) +ActionMappings=(ActionName="Crouch",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=C) +ActionMappings=(ActionName="Crouch",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_RightThumbstick) ++ActionMappings=(ActionName="FKey",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F) ++ActionMappings=(ActionName="1Key",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=One) ++ActionMappings=(ActionName="2Key",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Two) ++ActionMappings=(ActionName="3Key",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Three) ++ActionMappings=(ActionName="4Key",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Four) ++ActionMappings=(ActionName="5Key",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Five) +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) +AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Gamepad_LeftY) diff --git a/Content/_Game/Assets/Textures/Icons/Backgrounds/CommonBackground.uasset b/Content/_Game/Assets/Textures/Icons/Backgrounds/CommonBackground.uasset new file mode 100644 index 00000000..778681ec Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/Backgrounds/CommonBackground.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/Backgrounds/DamagedBackground.uasset b/Content/_Game/Assets/Textures/Icons/Backgrounds/DamagedBackground.uasset new file mode 100644 index 00000000..55ed96c3 Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/Backgrounds/DamagedBackground.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/Backgrounds/LegendaryBackground.uasset b/Content/_Game/Assets/Textures/Icons/Backgrounds/LegendaryBackground.uasset new file mode 100644 index 00000000..abd9deef Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/Backgrounds/LegendaryBackground.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/Backgrounds/RareBackground.uasset b/Content/_Game/Assets/Textures/Icons/Backgrounds/RareBackground.uasset new file mode 100644 index 00000000..1d2245e5 Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/Backgrounds/RareBackground.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/Backgrounds/UncommonBackground.uasset b/Content/_Game/Assets/Textures/Icons/Backgrounds/UncommonBackground.uasset new file mode 100644 index 00000000..f4ac2f78 Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/Backgrounds/UncommonBackground.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/IconCircleOutlined2.uasset b/Content/_Game/Assets/Textures/Icons/ButtonIcons/IconCircleOutlined2.uasset similarity index 52% rename from Content/_Game/Assets/Textures/Icons/IconCircleOutlined2.uasset rename to Content/_Game/Assets/Textures/Icons/ButtonIcons/IconCircleOutlined2.uasset index 6c2f71ca..5a4dd4c3 100644 Binary files a/Content/_Game/Assets/Textures/Icons/IconCircleOutlined2.uasset and b/Content/_Game/Assets/Textures/Icons/ButtonIcons/IconCircleOutlined2.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/ButtonIcons/InventorySelectButton.uasset b/Content/_Game/Assets/Textures/Icons/ButtonIcons/InventorySelectButton.uasset new file mode 100644 index 00000000..ecfa0ea3 Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/ButtonIcons/InventorySelectButton.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/ButtonIcons/InventorySelectButton2.uasset b/Content/_Game/Assets/Textures/Icons/ButtonIcons/InventorySelectButton2.uasset new file mode 100644 index 00000000..8c8b4bb8 Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/ButtonIcons/InventorySelectButton2.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/WeaponIcons/ARIcon2.uasset b/Content/_Game/Assets/Textures/Icons/WeaponIcons/ARIcon2.uasset new file mode 100644 index 00000000..7035754f Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/WeaponIcons/ARIcon2.uasset differ diff --git a/Content/_Game/Assets/Textures/Icons/WeaponIcons/SMGIcon.uasset b/Content/_Game/Assets/Textures/Icons/WeaponIcons/SMGIcon.uasset new file mode 100644 index 00000000..811e2eec Binary files /dev/null and b/Content/_Game/Assets/Textures/Icons/WeaponIcons/SMGIcon.uasset differ diff --git a/Content/_Game/Character/ShooterCharacterBP.uasset b/Content/_Game/Character/ShooterCharacterBP.uasset index 58e93d56..9150dbe2 100644 Binary files a/Content/_Game/Character/ShooterCharacterBP.uasset and b/Content/_Game/Character/ShooterCharacterBP.uasset differ diff --git a/Content/_Game/GameMode/ShooterGameModeBaseBP.uasset b/Content/_Game/GameMode/ShooterGameModeBaseBP.uasset index f5a0639c..3b2362c4 100644 Binary files a/Content/_Game/GameMode/ShooterGameModeBaseBP.uasset and b/Content/_Game/GameMode/ShooterGameModeBaseBP.uasset differ diff --git a/Content/_Game/HUD/AmmoCountBP.uasset b/Content/_Game/HUD/AmmoCountBP.uasset index f7922887..b47f24e6 100644 Binary files a/Content/_Game/HUD/AmmoCountBP.uasset and b/Content/_Game/HUD/AmmoCountBP.uasset differ diff --git a/Content/_Game/HUD/AmmoPickupWidget.uasset b/Content/_Game/HUD/AmmoPickupWidget.uasset index 02d827be..36164d63 100644 Binary files a/Content/_Game/HUD/AmmoPickupWidget.uasset and b/Content/_Game/HUD/AmmoPickupWidget.uasset differ diff --git a/Content/_Game/HUD/InventoryBar.uasset b/Content/_Game/HUD/InventoryBar.uasset new file mode 100644 index 00000000..f05d84bd Binary files /dev/null and b/Content/_Game/HUD/InventoryBar.uasset differ diff --git a/Content/_Game/HUD/PickupWidgetBP.uasset b/Content/_Game/HUD/PickupWidgetBP.uasset index 0426753b..68ee902e 100644 Binary files a/Content/_Game/HUD/PickupWidgetBP.uasset and b/Content/_Game/HUD/PickupWidgetBP.uasset differ diff --git a/Content/_Game/HUD/ShooterHUDBP.uasset b/Content/_Game/HUD/ShooterHUDBP.uasset index fbce976e..d379b635 100644 Binary files a/Content/_Game/HUD/ShooterHUDBP.uasset and b/Content/_Game/HUD/ShooterHUDBP.uasset differ diff --git a/Content/_Game/HUD/ShooterHUDOverlayBP.uasset b/Content/_Game/HUD/ShooterHUDOverlayBP.uasset index 99d367d7..e974f731 100644 Binary files a/Content/_Game/HUD/ShooterHUDOverlayBP.uasset and b/Content/_Game/HUD/ShooterHUDOverlayBP.uasset differ diff --git a/Content/_Game/HUD/WeaponSlot.uasset b/Content/_Game/HUD/WeaponSlot.uasset new file mode 100644 index 00000000..5754955b Binary files /dev/null and b/Content/_Game/HUD/WeaponSlot.uasset differ diff --git a/Content/_Game/Maps/DefaultMap.umap b/Content/_Game/Maps/DefaultMap.umap index b303f338..23072de3 100644 Binary files a/Content/_Game/Maps/DefaultMap.umap and b/Content/_Game/Maps/DefaultMap.umap differ diff --git a/Content/_Game/Weapons/BaseWeapon/BaseWeaponBP.uasset b/Content/_Game/Weapons/BaseWeapon/BaseWeaponBP.uasset index 84f76e68..427b0c9d 100644 Binary files a/Content/_Game/Weapons/BaseWeapon/BaseWeaponBP.uasset and b/Content/_Game/Weapons/BaseWeapon/BaseWeaponBP.uasset differ diff --git a/Content/_Game/Weapons/BaseWeapon/SMGAnimBP.uasset b/Content/_Game/Weapons/BaseWeapon/SMGAnimBP.uasset index 7e8dbe2e..31f37893 100644 Binary files a/Content/_Game/Weapons/BaseWeapon/SMGAnimBP.uasset and b/Content/_Game/Weapons/BaseWeapon/SMGAnimBP.uasset differ diff --git a/Shooter.uproject b/Shooter.uproject index f97f35a2..2fbe866d 100644 --- a/Shooter.uproject +++ b/Shooter.uproject @@ -41,6 +41,14 @@ { "Name": "BlueprintSnapNodes", "Enabled": true + }, + { + "Name": "VisualStudioTools", + "Enabled": true, + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/362651520df94e4fa65492dbcba44ae2", + "SupportedTargetPlatforms": [ + "Win64" + ] } ] } \ No newline at end of file diff --git a/Source/Shooter/Item.cpp b/Source/Shooter/Item.cpp index f15055ad..4ea435a5 100644 --- a/Source/Shooter/Item.cpp +++ b/Source/Shooter/Item.cpp @@ -31,10 +31,11 @@ AItem::AItem() : MaterialIndex(0), bCanChangeCustomDepth(true), // Dynamic Material Parameters + PulseCurveTime(5.f), GlowAmount(150.f), FresnelExponent(3.f), FresnelReflectFraction(4.f), - PulseCurveTime(5.f) + SlotIndex(0) { // 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; @@ -77,6 +78,17 @@ void AItem::BeginPlay() InitializeCustomDepth(); StartPulseTimer(); + + // We wait a small delay to make sure all actors are spawned, + // then we set a small sphere radius and reset it again, + // this generates any overlap events that weren't accounted for on spawn + FTimerHandle TimerHandle; + GetWorldTimerManager().SetTimer(TimerHandle, [&]() + { + AreaSphereRadius = AreaSphere->GetUnscaledSphereRadius(); + AreaSphere->SetSphereRadius(1.f); + AreaSphere->SetSphereRadius(AreaSphereRadius); + }, 0.5, false); } void AItem::setActiveStars() @@ -425,6 +437,24 @@ void AItem::SetItemProperties(EItemState State) AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision); + // Set CollisionBox properties + CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); + CollisionBox->SetCollisionEnabled(ECollisionEnabled::NoCollision); + break; + case EItemState::EIS_PickedUp: + PickupWidget->SetVisibility(false); + + // Set Mesh properties + ItemMesh->SetSimulatePhysics(false); + ItemMesh->SetEnableGravity(false); + ItemMesh->SetVisibility(false); + ItemMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); + ItemMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision); + + // Set AreaSphere properties + AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); + AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision); + // Set CollisionBox properties CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); CollisionBox->SetCollisionEnabled(ECollisionEnabled::NoCollision); @@ -477,7 +507,6 @@ void AItem::FinishInterping() // Subtract 1 from the Item Count of the interp location struct Character->IncrementInterpLocItemCount(InterpLocIndex, -1); Character->GetPickupItem(this); - SetItemState(EItemState::EIS_PickedUp); } // Set scale back to normal SetActorScale3D(FVector(1.f)); diff --git a/Source/Shooter/Item.h b/Source/Shooter/Item.h index f169df86..1063bdab 100644 --- a/Source/Shooter/Item.h +++ b/Source/Shooter/Item.h @@ -120,6 +120,9 @@ private: UPROPERTY(VisibleAnywhere, BlueprintReadonly, Category = "Item Properties", meta = (AllowPrivateAccess = true)) USkeletalMeshComponent* ItemMesh; + UPROPERTY(VisibleAnywhere, BlueprintReadonly, Category = "Item Properties", meta = (AllowPrivateAccess = true)) + float AreaSphereRadius; + /* The name which appears on the Pickup Widget */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = true)) FString ItemName; @@ -233,6 +236,22 @@ private: UPROPERTY(VisibleAnywhere, Category = "Item Properties", meta = (AllowPrivateAccess = true)) float FresnelReflectFraction; + /** Background for this item in the inventory */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Inventory, meta = (AllowPrivateAccess = true)) + UTexture2D* IconBackground; + + /** Icon for this item in the inventory */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Inventory, meta = (AllowPrivateAccess = true)) + UTexture2D* IconItem; + + /** Icon for this item's ammo in the inventory */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Inventory, meta = (AllowPrivateAccess = true)) + UTexture2D* IconAmmo; + + /** Slot in the inventory array */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Inventory, meta = (AllowPrivateAccess = true)) + int32 SlotIndex; + public: FORCEINLINE UWidgetComponent* GetPickupWidget() const { return PickupWidget; } @@ -250,7 +269,10 @@ public: FORCEINLINE USoundCue* GetEquipSound() const { return EquipSound; } FORCEINLINE int32 GetItemCount() const { return ItemCount; } - + + FORCEINLINE int32 GetSlotIndex() const { return SlotIndex; } + FORCEINLINE void SetSlotIndex(int32 Index) { SlotIndex = Index; } + /** Called from the AShooterCharacter class */ void StartItemCurve(AShooterCharacter* Char); diff --git a/Source/Shooter/ShooterAnimInstance.cpp b/Source/Shooter/ShooterAnimInstance.cpp index 278d912f..e179fdda 100644 --- a/Source/Shooter/ShooterAnimInstance.cpp +++ b/Source/Shooter/ShooterAnimInstance.cpp @@ -17,6 +17,8 @@ UShooterAnimInstance::UShooterAnimInstance() : TIPCharacterYaw(0.f), TIPCharacterYawLastFrame(0.f), RootYawOffset(0.f), + RotationCurve(0.f), + RotationCurveLastFrame(0.f), Pitch(0.f), bReloading(false), OffsetState(EOffsetState::EOS_Hip), @@ -87,6 +89,11 @@ void UShooterAnimInstance::NativeInitializeAnimation() Super::NativeInitializeAnimation(); ShooterCharacter = Cast(TryGetPawnOwner()); + + if (!ShooterCharacter) return; + + TIPCharacterYaw = ShooterCharacter->GetActorRotation().Yaw; + TIPCharacterYawLastFrame = TIPCharacterYaw; } void UShooterAnimInstance::TurnInPlace() diff --git a/Source/Shooter/ShooterCharacter.cpp b/Source/Shooter/ShooterCharacter.cpp index 1ee0479a..f2a34270 100644 --- a/Source/Shooter/ShooterCharacter.cpp +++ b/Source/Shooter/ShooterCharacter.cpp @@ -150,6 +150,8 @@ void AShooterCharacter::BeginPlay() // Spawn the default weapon and equip it EquipWeapon(SpawnDefaultWeapon()); + Inventory.Add(EquippedWeapon); + EquippedWeapon->SetSlotIndex(0); InitializeAmmoMap(); @@ -175,26 +177,25 @@ void AShooterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCo PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AShooterCharacter::Jump); PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping); - PlayerInputComponent->BindAction("FireButton", IE_Pressed, this, - &AShooterCharacter::FireButtonPressed); - PlayerInputComponent->BindAction("FireButton", IE_Released, this, - &AShooterCharacter::FireButtonReleased); + PlayerInputComponent->BindAction("FireButton", IE_Pressed, this, &AShooterCharacter::FireButtonPressed); + PlayerInputComponent->BindAction("FireButton", IE_Released, this, &AShooterCharacter::FireButtonReleased); - PlayerInputComponent->BindAction("Aiming", IE_Pressed, this, - &AShooterCharacter::AimingButtonPressed); - PlayerInputComponent->BindAction("Aiming", IE_Released, this, - &AShooterCharacter::AimingButtonReleased); + PlayerInputComponent->BindAction("Aiming", IE_Pressed, this, &AShooterCharacter::AimingButtonPressed); + PlayerInputComponent->BindAction("Aiming", IE_Released, this, &AShooterCharacter::AimingButtonReleased); - PlayerInputComponent->BindAction("Select", IE_Pressed, this, - &AShooterCharacter::SelectButtonPressed); - PlayerInputComponent->BindAction("Select", IE_Released, this, - &AShooterCharacter::SelectButtonReleased); + PlayerInputComponent->BindAction("Select", IE_Pressed, this, &AShooterCharacter::SelectButtonPressed); + PlayerInputComponent->BindAction("Select", IE_Released, this, &AShooterCharacter::SelectButtonReleased); - PlayerInputComponent->BindAction("Reload", IE_Pressed, this, - &AShooterCharacter::ReloadButtonPressed); + PlayerInputComponent->BindAction("Reload", IE_Pressed, this, &AShooterCharacter::ReloadButtonPressed); - PlayerInputComponent->BindAction("Crouch", IE_Pressed, this, - &AShooterCharacter::CrouchButtonPressed); + PlayerInputComponent->BindAction("Crouch", IE_Pressed, this, &AShooterCharacter::CrouchButtonPressed); + + PlayerInputComponent->BindAction("FKey", IE_Pressed, this, &AShooterCharacter::KeyFPressed); + PlayerInputComponent->BindAction("1Key", IE_Pressed, this, &AShooterCharacter::Key1Pressed); + PlayerInputComponent->BindAction("2Key", IE_Pressed, this, &AShooterCharacter::Key2Pressed); + PlayerInputComponent->BindAction("3Key", IE_Pressed, this, &AShooterCharacter::Key3Pressed); + PlayerInputComponent->BindAction("4Key", IE_Pressed, this, &AShooterCharacter::Key4Pressed); + PlayerInputComponent->BindAction("5Key", IE_Pressed, this, &AShooterCharacter::Key5Pressed); } // Called every frame @@ -373,6 +374,56 @@ void AShooterCharacter::ResetEquipSoundTimer() bShouldPlayEquipSound = true; } +void AShooterCharacter::KeyFPressed() +{ + if (EquippedWeapon->GetSlotIndex() == 0) return; + + ExchangeInventoryItems(EquippedWeapon->GetSlotIndex(), 0); +} + +void AShooterCharacter::Key1Pressed() +{ + if (EquippedWeapon->GetSlotIndex() == 1) return; + ExchangeInventoryItems(EquippedWeapon->GetSlotIndex(), 1); +} + +void AShooterCharacter::Key2Pressed() +{ + if (EquippedWeapon->GetSlotIndex() == 2) return; + ExchangeInventoryItems(EquippedWeapon->GetSlotIndex(), 2); +} + +void AShooterCharacter::Key3Pressed() +{ + if (EquippedWeapon->GetSlotIndex() == 3) return; + ExchangeInventoryItems(EquippedWeapon->GetSlotIndex(), 3); +} + +void AShooterCharacter::Key4Pressed() +{ + if (EquippedWeapon->GetSlotIndex() == 4) return; + ExchangeInventoryItems(EquippedWeapon->GetSlotIndex(), 4); +} + +void AShooterCharacter::Key5Pressed() +{ + if (EquippedWeapon->GetSlotIndex() == 5) return; + ExchangeInventoryItems(EquippedWeapon->GetSlotIndex(), 5); +} + +void AShooterCharacter::ExchangeInventoryItems(int32 CurrentItemIndex, int32 NewItemIndex) +{ + if (CurrentItemIndex == NewItemIndex || NewItemIndex >= Inventory.Num()) return; + + auto OldEquippedWeapon = EquippedWeapon; + auto NewWeapon = Cast(Inventory[NewItemIndex]); + + EquipWeapon(NewWeapon); + + OldEquippedWeapon->SetItemState(EItemState::EIS_PickedUp); + NewWeapon->SetItemState(EItemState::EIS_Equipped); +} + int32 AShooterCharacter::GetInterpLocationIndex() { int32 LowestIndex = 1; @@ -695,20 +746,27 @@ void AShooterCharacter::TraceForItems() FHitResult ItemTraceResult; FVector HitLocation; TraceUnderCrosshairs(ItemTraceResult, HitLocation); + + TraceHitItem = Cast(ItemTraceResult.GetActor()); - if (ItemTraceResult.bBlockingHit) + if (TraceHitItem && ItemTraceResult.bBlockingHit) { // If an item was being looked at from last frame, we should hide its widget - SetItemPickupWidgetVisibility(TraceHitItem, false); - + if (OldTraceHitItem != TraceHitItem) + SetItemPickupWidgetVisibility(OldTraceHitItem, false); + // Show the new item's widget - TraceHitItem = Cast(ItemTraceResult.GetActor()); + OldTraceHitItem = TraceHitItem; + + if (TraceHitItem && TraceHitItem->GetItemState() == EItemState::EIS_EquipInterping) + TraceHitItem = nullptr; + SetItemPickupWidgetVisibility(TraceHitItem, true); } - else if (TraceHitItem) // Hide widget for the item from last frame + else if (OldTraceHitItem) // Hide widget for the item from last frame { - SetItemPickupWidgetVisibility(TraceHitItem, false); - TraceHitItem = nullptr; + SetItemPickupWidgetVisibility(OldTraceHitItem, false); + OldTraceHitItem = nullptr; } } else if (TraceHitItem) // Hide widget for the item from last frame @@ -751,6 +809,16 @@ void AShooterCharacter::EquipWeapon(AWeapon* WeaponToEquip) // Attach the weapon to the hand socket RightHandSocket HandSocket->AttachActor(WeaponToEquip, GetMesh()); + if (EquippedWeapon == nullptr) + { + // -1 == no EquippedWeapon yet. No need to reverse the icon animation + EquipItemDelegate.Broadcast(-1, WeaponToEquip->GetSlotIndex()); + } + else + { + EquipItemDelegate.Broadcast(EquippedWeapon->GetSlotIndex(), WeaponToEquip->GetSlotIndex()); + } + EquippedWeapon = WeaponToEquip; EquippedWeapon->SetItemState(EItemState::EIS_Equipped); @@ -776,6 +844,7 @@ void AShooterCharacter::SelectButtonPressed() if (TraceHitItem) { TraceHitItem->StartItemCurve(this); + TraceHitItem = nullptr; } } @@ -785,6 +854,12 @@ void AShooterCharacter::SelectButtonReleased() void AShooterCharacter::SwapWeapon(AWeapon* WeaponToSwap) { + if (EquippedWeapon->GetSlotIndex() <= Inventory.Num() - 1) + { + Inventory[EquippedWeapon->GetSlotIndex()] = WeaponToSwap; + WeaponToSwap->SetSlotIndex(EquippedWeapon->GetSlotIndex()); + } + DropWeapon(); EquipWeapon(WeaponToSwap); } @@ -840,7 +915,16 @@ void AShooterCharacter::GetPickupItem(AItem* Item) if (Weapon) { - SwapWeapon(Weapon); + if (Inventory.Num() < INVENTORY_CAPACITY) + { + Weapon->SetSlotIndex(Inventory.Num()); + Inventory.Add(Weapon); + Weapon->SetItemState(EItemState::EIS_PickedUp); + } + else // Inventory is full! Swap with EquippedWeapon + { + SwapWeapon(Weapon); + } } auto Ammo = Cast(Item); diff --git a/Source/Shooter/ShooterCharacter.h b/Source/Shooter/ShooterCharacter.h index b5dcd31c..6cfd14bd 100644 --- a/Source/Shooter/ShooterCharacter.h +++ b/Source/Shooter/ShooterCharacter.h @@ -42,6 +42,9 @@ struct FInterpLocation int32 ItemCount; }; +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FEquipItemDelegate, int32, CurrentSlotIndex, int32, NewSlotIndex); + + UCLASS() class SHOOTER_API AShooterCharacter : public ACharacter { @@ -194,6 +197,15 @@ protected: void ResetPickupSoundTimer(); void ResetEquipSoundTimer(); + void KeyFPressed(); + void Key1Pressed(); + void Key2Pressed(); + void Key3Pressed(); + void Key4Pressed(); + void Key5Pressed(); + + void ExchangeInventoryItems(int32 CurrentItemIndex, int32 NewItemIndex); + private: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = true)) USpringArmComponent* CameraBoom; @@ -338,6 +350,10 @@ private: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = true)) AItem* TraceHitItem; + /** Item hit by our trace in TraceForItems() from last frame (could be null) */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = true)) + AItem* OldTraceHitItem; + /** Distance outward from the camera for the interp destination */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Items, meta = (AllowPrivateAccess = true)) float CameraInterpDistance; @@ -443,6 +459,16 @@ private: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Items, meta = (AllowPrivateAccess = true)) float EquipSoundResetTime; + /** An array of AItems for our inventory */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Inventory, meta = (AllowPrivateAccess = true)) + TArray Inventory; + + const int32 INVENTORY_CAPACITY{ 6 }; + + /** Delegate for sending slot information to InventoryBar when equipping */ + UPROPERTY(BlueprintAssignable, Category = Delegates, meta = (AllowPrivateAccess = true)) + FEquipItemDelegate EquipItemDelegate; + public: /* Returns CameraBoom SubObject */ FORCEINLINE USpringArmComponent* GetCameraBoom() const { return CameraBoom; } diff --git a/Source/ShooterEditor.Target.cs b/Source/ShooterEditor.Target.cs index 6ba95104..aee4d95d 100644 --- a/Source/ShooterEditor.Target.cs +++ b/Source/ShooterEditor.Target.cs @@ -8,8 +8,8 @@ public class ShooterEditorTarget : TargetRules public ShooterEditorTarget( TargetInfo Target) : base(Target) { Type = TargetType.Editor; - DefaultBuildSettings = BuildSettingsVersion.V2; - IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_2; + DefaultBuildSettings = BuildSettingsVersion.V4; + IncludeOrderVersion = EngineIncludeOrderVersion.Latest; ExtraModuleNames.AddRange( new string[] { "Shooter" } ); } } diff --git a/shadertoolsconfig.json b/shadertoolsconfig.json new file mode 100644 index 00000000..9e8ecb44 --- /dev/null +++ b/shadertoolsconfig.json @@ -0,0 +1,8 @@ +{ + "hlsl.preprocessorDefinitions": { + }, + " hlsl.additionalIncludeDirectories": [ + ], + "hlsl.virtualDirectoryMappings": { + } +}