325 lines
11 KiB
C++
325 lines
11 KiB
C++
// Project Lab - NHTV Igad
|
|
|
|
#pragma once
|
|
#include <unordered_map>
|
|
using std::unordered_map;
|
|
#include "AbilityState.h"
|
|
#include "ScalingGraph.h"
|
|
#include "NetworkPossessable.h"
|
|
#include "IngameSkillTree.h"
|
|
#include "NetworkCharacter.generated.h"
|
|
|
|
class ACreatureSpawn;
|
|
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FCharacterKilled, ANetworkCharacter*, killer, UAbilityInfo*, ability);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnDamageTaken, ANetworkCharacter*, dealer, int32, damage, UAbilityInfo*, ability);
|
|
|
|
UCLASS(config = Game)
|
|
class ANetworkCharacter : public ANetworkPossessable
|
|
{
|
|
GENERATED_BODY()
|
|
public:
|
|
ANetworkCharacter();
|
|
|
|
virtual void BeginPlay() override;
|
|
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
|
virtual void Destroyed() override;
|
|
virtual void OnDeath(UAbilityInfo* ability);
|
|
void RegisterHealthBar();
|
|
void UnregisterHealthBar();
|
|
|
|
virtual void Tick(float DeltaSeconds) override;
|
|
|
|
// This processes the learned abilities on the server and calls LearnSkills on the owning client
|
|
void LearnSkills_Server(const TArray<FIngameSkillTreeSkill>& skills);
|
|
// This creates a list of all learned skills on the client's version of the character so that he gets an updated casting bar, etc.
|
|
UFUNCTION(Client, Reliable)
|
|
void LearnSkills(const TArray<FIngameSkillTreeSkill>& skills);
|
|
|
|
// The Buff/Modifier manager, for server side characters
|
|
class ModifierManager* GetModifierManager();
|
|
UFUNCTION(BlueprintCallable, Category = "modifiers")
|
|
TArray<class AModifier*> GetModifiersOfClass(TSubclassOf<class AModifier> modifierClass);
|
|
|
|
virtual void ResetModifiers();
|
|
void CheckStatsOverflow();
|
|
|
|
// Damage dealing
|
|
UFUNCTION(BlueprintCallable, Category = "Damage", meta = (WorldContext="WorldContextObject"))
|
|
int32 DealDamage(class UObject* WorldContextObject, int32 damage, float armorPercentageIgnore = 0.0f);
|
|
virtual int32 NativeDealDamage(class ANetworkCharacter* dealer, int32 damage, float armorPercentageIgnore = 0.0f, UAbilityInfo* ability = nullptr);
|
|
|
|
virtual void NativeOnKilled(class ANetworkCharacter* killer, class UAbilityInfo* ability);
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Damage")
|
|
void OnStandardAttack(ANetworkCharacter* targetCharacter);
|
|
|
|
|
|
|
|
// Healing
|
|
UFUNCTION(BlueprintCallable, Category = "Healing")
|
|
void AddHealth(int32 health);
|
|
virtual void NativeAddHealth(int32 health);
|
|
|
|
void RemoveHealth(int32 health);
|
|
void AddMana(float mana);
|
|
void RemoveMana(float mana);
|
|
UFUNCTION(BlueprintCallable, Category = "Damage")
|
|
float GetTimeSinceDamage() const;
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Animation")
|
|
void TriggerSwingAnimation_Server();
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
int32 GetHealth() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
int32 GetMana() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
int32 GetBlockedMana() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
int32 GetMaxHealth() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
int32 GetMaxMana() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
int32 GetArmor() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
bool GetHitable() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
void SetHitable(bool hitable);
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
float GetDamageMultiplier() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
float GetCooldownReduction() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
float GetAttackSpeed() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
float GetAttackDamage() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
float GetMagicDamage() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
float GetTotalDamage() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
bool IsStunned() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
bool CanRotate() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
bool IsSilenced() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
bool IsChanneling() const;
|
|
UFUNCTION(BlueprintCallable, Category = "State")
|
|
bool IsRanged() const;
|
|
bool CanBeStunned() const;
|
|
|
|
ANetworkCharacter* GetLastPlayerDamage() const;
|
|
|
|
void CastAbility(int32 abilityIndex);
|
|
void CastAbility(class UAbilityInfo* abilityInfo);
|
|
|
|
// Returns the ability that is currently being casted(channeling)
|
|
UFUNCTION(BlueprintCallable, Category = "Ability")
|
|
class UAbilityInfo* GetCastingAbility();
|
|
|
|
// Gets the persistent state of an ability between casts
|
|
class AAbilityState* GetAbilityState(class UAbilityInfo* abilityInfo);
|
|
|
|
// Gets the toggle state for abilities that have isToggleAbility set
|
|
bool GetAbilityToggleState(class UAbilityInfo* abilityInfo);
|
|
bool m_initialised;
|
|
|
|
// Minimap/FoW visibility
|
|
bool IsVisible() const;
|
|
|
|
// The collection of abilities this character has, for players.
|
|
// The first ability in this array is always treated the character's basic attack,
|
|
// and thus is affected by the attack speed variable of the character
|
|
UPROPERTY(EditDefaultsOnly, Category = "Ability")
|
|
TArray<class UAbilityInfo*> abilities;
|
|
|
|
UPROPERTY(BlueprintReadOnly, Replicated, Category = "Ability")
|
|
class UAbilityInfo* basicAttack;
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Ability")
|
|
TArray<class UAbilityInfo*> passives;
|
|
|
|
UPROPERTY(Replicated, BlueprintReadOnly, Category = "Animation")
|
|
int32 swingAnimationSequence;
|
|
|
|
UPROPERTY(EditAnywhere, Category = "Experience Settings")
|
|
int32 experienceGainOnKill;
|
|
|
|
// Intervals at which damage and healing combat text are spawned
|
|
UPROPERTY(EditAnywhere, Category = "Combat Text")
|
|
float healthAccumTimer;
|
|
UPROPERTY(EditAnywhere, Category = "Combat Text")
|
|
float damageAccumTimer;
|
|
|
|
// Duration before a team's damage is no longer valid
|
|
// Gets refreshed when a team deals damage to the creature
|
|
UPROPERTY(EditAnywhere, Category = "Team Damage Table")
|
|
float teamDamageTimer;
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Character")
|
|
FCharacterKilled onCharacterKilled;
|
|
// SERVER ONLY
|
|
UPROPERTY(BlueprintAssignable, Category = "Character")
|
|
FOnDamageTaken onDamageTaken;
|
|
|
|
METRICS_EXPR(Metrics::PlayerHandle* metricsHandle);
|
|
|
|
protected:
|
|
// Called when the character is spawned or reset to set initial modifiers like fixed health/mana-regen
|
|
// overridable
|
|
virtual void m_SpawnModifiers();
|
|
|
|
// This checks stunn state, etc. to allow NetworkPossessable to move
|
|
virtual bool m_AllowedToMove() override;
|
|
virtual bool m_AllowedToRotate() override;
|
|
virtual void m_SetLevelStats();
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Stats")
|
|
int32 baseMovementSpeed;
|
|
UPROPERTY(EditDefaultsOnly, Category = "Stats")
|
|
int32 baseArmor;
|
|
UPROPERTY(EditDefaultsOnly, Category = "Stats")
|
|
int32 passiveManaRegen;
|
|
UPROPERTY(EditDefaultsOnly, Category = "Stats")
|
|
int32 passiveHealthRegen;
|
|
|
|
UPROPERTY(Replicated)
|
|
int32 m_blockedMana;
|
|
UPROPERTY(Replicated)
|
|
float m_damageMultiplier;
|
|
UPROPERTY(Replicated)
|
|
float m_ignoreArmor;
|
|
UPROPERTY(Replicated)
|
|
float m_manaRegenMultiplier;
|
|
UPROPERTY(Replicated)
|
|
float m_manaUsageMultiplier;
|
|
UPROPERTY(Replicated)
|
|
float m_positiveEffectMultiplier;
|
|
UPROPERTY(Replicated)
|
|
float m_negativeEffectMultiplier;
|
|
UPROPERTY(Replicated)
|
|
float m_damageTakenMultiplier;
|
|
UPROPERTY(Replicated)
|
|
int32 m_armor;
|
|
UPROPERTY(Replicated)
|
|
bool m_stunned;
|
|
UPROPERTY(Replicated)
|
|
bool m_silenced;
|
|
//sileneCount is the ammount of silences by modifiers, silence by casting is not taking into account.
|
|
UPROPERTY(Replicated)
|
|
uint32 m_silenceCount;
|
|
UPROPERTY(Replicated)
|
|
bool m_visible;
|
|
UPROPERTY(Replicated)
|
|
bool m_hitable;
|
|
UPROPERTY(Replicated)
|
|
bool m_isRanged;
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "Stats")
|
|
bool canBeStunned;
|
|
UPROPERTY(EditDefaultsOnly, Category = "Stats")
|
|
bool canBeSilenced;
|
|
|
|
UPROPERTY(Replicated)
|
|
int32 m_health;
|
|
UPROPERTY(Replicated)
|
|
int32 m_maxHealth;
|
|
UPROPERTY(Replicated)
|
|
float m_mana;
|
|
UPROPERTY(Replicated)
|
|
int32 m_maxMana;
|
|
UPROPERTY(Replicated)
|
|
float m_cooldownReduction;
|
|
UPROPERTY(Replicated)
|
|
float m_attackSpeed;
|
|
UPROPERTY(Replicated)
|
|
float m_attackDamageMultiplier;
|
|
UPROPERTY(Replicated)
|
|
float m_magicDamageMultiplier;
|
|
|
|
UPROPERTY(Replicated)
|
|
bool m_usesMana;
|
|
|
|
UPROPERTY(Replicated)
|
|
float m_castingMovementspeedMultiplier;
|
|
|
|
friend class ModifierManager;
|
|
friend class APreCastAbilityEventGroup;
|
|
friend class AIllusionCharacter;
|
|
friend class ADefaultPlayerController;
|
|
class ModifierManager* m_modifierManager;
|
|
|
|
bool m_shouldBeDestroyed = false;
|
|
private:
|
|
// Request to the server to cast an ability
|
|
UFUNCTION(Reliable, Server, WithValidation)
|
|
void m_CastAbility_Server(class UAbilityInfo* ability);
|
|
void m_InitAbilitySequence(class UAbilityInfo* ability, class AAbilityState* state);
|
|
|
|
// Updates all the cooldown timers and ticks modifiers
|
|
void m_TickAbilities(float DeltaSeconds);
|
|
|
|
void m_SetAbilityCooldown(class UAbilityInfo* ability, class AAbilityState* state);
|
|
|
|
// Server only casting interupt
|
|
void m_InteruptSpellcasting();
|
|
|
|
// Called if we know an ability is successfully casted or not
|
|
UFUNCTION(Reliable, Client)
|
|
void m_OnAbilityCastConfirm(UAbilityInfo* ability, bool success, bool toggleState, float cooldown, float cooldownTime);
|
|
|
|
void m_PreCast(UAbilityInfo* ability);
|
|
// Called if we know an ability is successfully casted or not (server-side)
|
|
virtual void m_OnAbilityCastConfirm_Server(UAbilityInfo* ability, bool success);
|
|
|
|
// Callback for when an ability progresses to it's next state
|
|
UFUNCTION()
|
|
void m_OnAbilityEventGroupEnded(class UAbilityInfo* ability, class AAbilityEventGroup* current, class AAbilityEventGroup* next);
|
|
|
|
friend class ADefaultPlayerState;
|
|
|
|
// Active Stats
|
|
struct DamagePeriod
|
|
{
|
|
DamagePeriod(int32 damage, float timer) : damage(damage), timer(timer) {}
|
|
int32 damage;
|
|
float timer;
|
|
};
|
|
unordered_map<class ADefaultPlayerController*, DamagePeriod> m_damageAccum;
|
|
int32 m_damageAccumValue;
|
|
float m_damageAccumTimer;
|
|
int32 m_healAccumValue;
|
|
float m_healAccumTimer;
|
|
float m_totalDamage;
|
|
unordered_map<int32, DamagePeriod> m_teamDamageDealt;
|
|
|
|
UPROPERTY()
|
|
ANetworkCharacter* m_lastPlayerDamage;
|
|
|
|
// Keeps ability persistent state between casts
|
|
UPROPERTY()
|
|
TMap<class UAbilityInfo*, class AAbilityState*> m_abilityStates;
|
|
// Keeps ability execution states / active group (server-side)
|
|
UPROPERTY()
|
|
TMap<class UAbilityInfo*, class AAbilityEventGroup*> m_activeAbilities;
|
|
|
|
friend class AModifier;
|
|
friend class AVisibilityModifier;
|
|
float m_timeSinceDamage;
|
|
UPROPERTY()
|
|
class AAbilityEventGroup* m_channelGroup;
|
|
UPROPERTY(Replicated)
|
|
class UAbilityInfo* m_castingAbility;
|
|
UPROPERTY(Replicated)
|
|
bool m_channelStun;
|
|
UPROPERTY(Replicated)
|
|
bool m_allowChannelRotation;
|
|
|
|
|
|
class APreCastAbilityEventGroup* m_currentPreCast;
|
|
|
|
};
|
|
|