// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "GameplayTagAssetInterface.h" #include "MWeapon.generated.h" class AMCharacter; class AMWeapon; UENUM(BlueprintType) enum class EWeaponType : uint8 { PrimaryWeapon = 0, Scanner, BlowTorch, Tablet, MaxWeaponType }; DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnTargetHit, AMWeapon*, Weapon, AActor*, TargetActor, AActor*, Shooter); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWeaponReloadStarted, AMWeapon*, Weapon); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWeaponReloadCompleted, AMWeapon*, Weapon); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWeaponReloadCancelled, AMWeapon*, Weapon); class USoundBase; class UMatineeCameraShake; class UNiagaraSystem; class AMProjectile; UCLASS() class MECHDEFENCE_API AMWeapon : public AActor { GENERATED_BODY() public: AMWeapon(); protected: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components") USkeletalMeshComponent* WeaponMesh; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") TSubclassOf DamageType; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") FName MuzzleSocketName; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta=(Tooltip="Name of socket on the player's skeleton where the weapon should be attached")) FName PlayerAttachmentSocketName; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta=(Tooltip="Name of the exposed variable in the beam particle system that will be updated to the location of the target when the weapon fires")) FName TracerParticleStartLocationName; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") UParticleSystem* MuzzleEffect; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") UNiagaraSystem* TracerEffect; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") UParticleSystem* DefaultImpactEffect; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") TSubclassOf CameraShakeClass; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") TSubclassOf ProjectileClass; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon", meta = (Tooltip = "When the bullet from this weapon hits a target, these tags will determine if the target is valid and if damage and other UI effects should be applied")) FGameplayTagContainer ValidTargetTags; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") float BaseDamage; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") float VulnerableDamageMultiplier; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta = (Tooltip = "Bullets fired per minute. Set it to 0 for weapons that should only fire once when fire button is pressed")) float RateOfFire; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta = (Tooltip = "Bullet spread angle in degrees", ClampMin = 0.f)) float BulletSpread; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta = (Tooltip = "Number of seconds after which StopFire is automatically called. Only used when RateOfFire is also set to 0", ClampMin = 0.f)) float StopFireDelay; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta = (Tooltip = "Number of bullets in one clip after which the weapon is going to be reloaded. Set zero to disable reloading altogether")) uint8 ClipSize; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta = (Tooltip = "Number of seconds it takes to reload the weapon")) float ReloadTime; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon", meta = (Tooltip = "Chance for the projectile particle to spawn. 1 would mean always and 0 would mean never", ClampMin = 0.f, ClampMax = 1.f)) float ProjectileSpawnChance; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") UAnimSequence* FireAnimation; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") USoundBase* FireSound; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") USoundBase* ReloadSound; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") float MaxWeaponRange; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon|Zoom") float ZoomInFOV; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Weapon|Zoom") bool bCanZoom; float TimeBetweenShots; float TimeLastFired; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Weapon") uint8 ClipRemainingBullets; bool bFiring; bool bReloading; FTimerHandle TimerHandle_TimeBetweenShots; FTimerHandle TimerHandle_Reload; bool bSecondaryFireBound; UFUNCTION() void HandleReloadComplete(); virtual void BeginPlay() override; UFUNCTION(BlueprintCallable) void Fire(); UFUNCTION(BlueprintCallable, BlueprintNativeEvent) void OnFire(); UFUNCTION(BlueprintCallable) void PlayFireEffects(FVector ShotDirection, UParticleSystem* ImpactEffect, FVector TraceEffectEndLocation, const FRotator ImpactParticleRotation); // This will hold the reload sound handle when it is played so that if the reload is cancelled // we can stop the sound from playing UAudioComponent* TempReloadSoundHandle; public: virtual void Tick(float DeltaTime) override; UFUNCTION(BlueprintCallable, BlueprintNativeEvent) bool StartFire(); UFUNCTION(BlueprintCallable, BlueprintNativeEvent) void StopFire(); UFUNCTION(BLueprintCallable, BlueprintNativeEvent) void StartSecondaryFire(); UFUNCTION(BLueprintCallable, BlueprintNativeEvent) void StopSecondaryFire(); UFUNCTION(BlueprintCallable) virtual void Reload(); UFUNCTION(BlueprintCallable) float GetReloadProgress(); UFUNCTION(BlueprintCallable) bool IsFiring() { return bFiring; } UFUNCTION(BlueprintCallable) bool IsReloading() { return bReloading; } UFUNCTION(BlueprintCallable) void CancelReload(); UFUNCTION() void HandleWeaponEquipped(AMCharacter* Character, AMWeapon* NewWeapon, AMWeapon* PreviousWeapon); UFUNCTION(BlueprintCallable, meta = (Tooltip = "Return the world coordinates of the position of the this weapon is aiming at")) FVector CalculateTargetedWorldLocation(TSubclassOf ValidTargetClass, ECollisionChannel TraceChannel) const; UFUNCTION(BlueprintCallable) AActor* GetTargetedActor(ECollisionChannel TraceChannel) const; FName GetPlayerAttachmentSocketName() const { return PlayerAttachmentSocketName; } UPROPERTY(BlueprintAssignable, Category = "Events") FOnTargetHit OnTargetHit; UPROPERTY(BlueprintAssignable, Category = "Events") FOnWeaponReloadStarted OnWeaponReloadStarted; UPROPERTY(BlueprintAssignable, Category = "Events") FOnWeaponReloadCompleted OnWeaponReloadCompleted; UPROPERTY(BlueprintAssignable, Category = "Events") FOnWeaponReloadCancelled OnWeaponReloadCancelled; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon") EWeaponType WeaponType; };