haxis/Source/UnrealProject/Creatures/NetworkCharacter.h

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;
};