#pragma once
#include "Abilities/Modifier.h"
#include "ScalingGraph.h"
#include "NativeModifiers.generated.h"

// Increase/Decrease movement speed
UCLASS()
class UNREALPROJECT_API ASpeedModifier : public AModifier
{
	GENERATED_BODY()

public:
	ASpeedModifier();

	virtual void ModifyCharacter();

	//adjusts the movementspeed of the character
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float speedMultiplier;
};


// Health Regen over time
UCLASS()
class UNREALPROJECT_API ARegenModifier : public AModifier
{
	GENERATED_BODY()

public:
	ARegenModifier();

	virtual void ModifierTick() override;
	virtual bool ShouldBeRemoved() const override;

	//the ammount of regen per tick (5 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float regenPerTick = 5.0f;
	//the total ammount of time the modifier should tick
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float regenTime;

private:
	FVector m_pos;
	float m_noDamageTime = 5.0f;
};

// Mana regen over time
UCLASS()
class UNREALPROJECT_API AManaRegenModifier : public AModifier
{
	GENERATED_BODY()

public:
	AManaRegenModifier();

	virtual void ModifierTick() override;
	virtual bool ShouldBeRemoved() const override;

	//the ammount of mana per tick (20 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float regenPerTick;
};

// Damage over time
UCLASS()
class UNREALPROJECT_API ADOTModifier : public AModifier
{
	GENERATED_BODY()

public:
	ADOTModifier();

	virtual void ModifierTick() override;

	//damage per tick (3 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float damagePerTick = 5.0f;
};

// Attack speed multiplier that scales with ability power
UCLASS()
class UNREALPROJECT_API AAttackSpeedModifier : public AModifier
{
	GENERATED_BODY()

public:
	AAttackSpeedModifier();
	virtual void ModifyCharacter();

	//adjusts the attack speed of the character
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	UCurveFloat* scalingGraph;
};

// Attack speed multiplier
UCLASS()
class UNREALPROJECT_API AAttackSpeedModifierConstant : public AModifier
{
	GENERATED_BODY()

public:
	AAttackSpeedModifierConstant();
	virtual void ModifyCharacter();
	bool ShouldBeRemoved() const override;

	//adjusts the attack speed of the character
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
	float attackSpeedMultiplier;
};

// Cooldown reduction
UCLASS()
class UNREALPROJECT_API ACooldownReductionModifier : public AModifier
{
	GENERATED_BODY()

public:
	ACooldownReductionModifier();
	virtual void ModifyCharacter();

	//adjusts the cooldown of every ability of the character, except for that standard attack
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	UCurveFloat* scalingGraph;
};

// Increase/Decrease Damage (multiplier)
UCLASS()
class UNREALPROJECT_API AADModifier : public AModifier
{
	GENERATED_BODY()

public:
	AADModifier();

	virtual void ModifyCharacter() override;

	//adjusts the damage of the standard attack
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* scalingGraph;
};


// Increase/Decrease magic Damage (multiplier)
UCLASS()
class UNREALPROJECT_API AAPModifier : public AModifier
{
	GENERATED_BODY()

public:
	AAPModifier();

	virtual void ModifyCharacter() override;

	//adjusts the damage of all abilities of the character except for the standard attack
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* scalingGraph;
};

// Increase/Decrease max health
UCLASS()
class UNREALPROJECT_API AMaxHealthModifier : public AModifier
{
	GENERATED_BODY()

public:
	AMaxHealthModifier();
	virtual void ModifyCharacter();

	//adjusts the max health of the character
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* scalingGraph;
};

// Increase/Decrease max health with a int32
UCLASS()
class UNREALPROJECT_API AConstMaxHealthModifier : public AModifier
{
	GENERATED_BODY()

public:
	AConstMaxHealthModifier();
	virtual void ModifyCharacter();

	//adjusts the max health of the character
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		int32 add;
};

// Increase/Decrease blocked mana
UCLASS()
class UNREALPROJECT_API ABlockManaModifier : public AModifier
{
	GENERATED_BODY()

public:
	ABlockManaModifier();

	virtual void ModifyCharacter() override;
	// mana blocked
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	int32 Mana;
};

// Mana over time cost with a curve
UCLASS()
class UNREALPROJECT_API AManaDrainCurveModifier : public AModifier
{
	GENERATED_BODY()

public:
	AManaDrainCurveModifier();

	virtual void ModifierTick() override;

	//mana drained per tick (20 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* ManaPerTick;
};


// Mana over time cost
UCLASS()
class UNREALPROJECT_API AManaDrainModifier : public AModifier
{
	GENERATED_BODY()

public:
	AManaDrainModifier();

	virtual void ModifierTick() override;

	//mana drained per tick (20 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		float ManaPerTick;
};

// Heal health 1 time
UCLASS()
class UNREALPROJECT_API AHealModifier : public AModifier
{
	GENERATED_BODY()

public:
	AHealModifier();

	virtual void ModifierTick() override;
	virtual bool ShouldBeRemoved() const override;
	//the ammount of health that is healed
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float health;

private:
	bool m_shouldBeRemoved = false;
};

// Stun
UCLASS()
class UNREALPROJECT_API AStunModifier : public AModifier
{
	GENERATED_BODY()

public:
	AStunModifier();
	virtual void ModifierStart() override;
	virtual void ModifierEnd() override;
	virtual void ModifierTick() override;
	virtual void ModifyCharacter() override;
};

// Stun
UCLASS()
class UNREALPROJECT_API ASilenceModifier : public AModifier
{
	GENERATED_BODY()

public:
	ASilenceModifier();
	virtual void ModifierStart() override;
	virtual void ModifierEnd() override;
};

// Damage taken multiplier (only meant for bosses, will not work with a timer)
UCLASS()
class UNREALPROJECT_API ADamageTakenModifier : public AModifier
{
	GENERATED_BODY()

public:
	ADamageTakenModifier();

	virtual void ModifyCharacter() override;
	virtual bool ShouldBeRemoved() const override;

	//adjusts the damage taken.
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(ExposeOnSpawn), Category = "Modifier")
	float damageTakenMultiplier;
};



//gives invisibility on the minimap with set breaks   DEPRECATED
UCLASS()
class UNREALPROJECT_API AVisibilityModifier : public AModifier
{
	GENERATED_BODY()
public:
	AVisibilityModifier();

	virtual void ModifierTick() override;
	virtual bool ShouldBeRemoved() const override;
	//DEPRECATED
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
	float visibleBreak = 5.0f;
	//DEPRECATED
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
	float visibleTime = 1.0f;

private:
	float m_timer;
	bool m_visible;
};


//gives a chance at healing instead of damage if the blow is the killing blow
UCLASS()
class UNREALPROJECT_API ADodgeDeathModifier : public AModifier
{
	GENERATED_BODY()

	float m_timer;
public:
	ADodgeDeathModifier();

	virtual bool ShouldBeRemoved() const override;
	virtual void ModifierTick() override;
	//the chance between 0 and 1 and the effect will be proced
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* dodgeChance;
	//the ammount of health that is healed on the effect
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* heal;

	//the cooldown for the dodgedeath in seconds
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* cooldown;



	virtual bool OnDamage(int32& damage, ANetworkCharacter* damageDealer) override;
};

//ignores a part of the enemy armor on all abilities
UCLASS()
class UNREALPROJECT_API AArmorIgnoreModifier : public AModifier
{
	GENERATED_BODY()

public:
	AArmorIgnoreModifier();
	virtual void ModifyCharacter();
	//the ammount of armor that is ignored (between 0 and 1)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
	UCurveFloat* scalingGraph;
};

//gives a chance at healing instead of damage if the blow is the killing blow
UCLASS()
class UNREALPROJECT_API ABeserkModifier : public AModifier
{
	GENERATED_BODY()
public:
	ABeserkModifier();


	virtual bool ShouldBeRemoved() const override;

	//the threshhold (between 0 and 1) where the effect will be proced
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* healthThreshold;
	//adjusts the attackspeed
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* attackSpeedMultiplier;
	  

	void m_Start();
	virtual void ModifierTick() override;
private:
	bool m_active;
	bool m_hasToActivate;
	class AAttackSpeedModifierConstant* m_ASModifier;

	virtual void AfterDamage(int32 damage) override;
};


// Increase/Decrease Damage (multiplier)
UCLASS()
class UNREALPROJECT_API AArmorReductionModifier : public AModifier
{
	GENERATED_BODY()

public:
	AArmorReductionModifier();

	virtual void ModifyCharacter() override;
	//adjusts the armor
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
	float armorReduction;
};


//regens health Per Tick
UCLASS()
class UNREALPROJECT_API AHealthRegenModifier : public AModifier
{
	GENERATED_BODY()

public:
	AHealthRegenModifier();
	//the ammount of health that is regened per tick (20 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* scalingGraph;

	virtual void ModifierTick() override;
};

//deals DOT on a standard attack
UCLASS()
class UNREALPROJECT_API AOnStandardAttackDOTModifier : public AModifier
{
	GENERATED_BODY()

private:
	float m_cooldownTimer;
public:
	AOnStandardAttackDOTModifier();
	//damage per tick on standard attack hit(3 ticks per second)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* damagePerTick;
	//the cooldown of the effect
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* cooldown;
	//the duration of the effect( of the DOT)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* damageDuration;

	virtual void ModifierTick() override;
	virtual void OnStandardAttack(ANetworkCharacter* targetcharacter) override;
};

//returns a part of the damage
UCLASS()
class UNREALPROJECT_API AReturnDamageModifier : public AModifier
{
	GENERATED_BODY()
public:
	AReturnDamageModifier();

	//chance between 0 and 1 of procing the effect
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* scalingGraph;

	virtual bool OnDamage(int32& damage, ANetworkCharacter* damageDealer) override;
};

//redirects a part of the damage to the ally
UCLASS()
class UNREALPROJECT_API ARedirectDamageModifier : public AModifier
{
	GENERATED_BODY()
public:
	ARedirectDamageModifier();

	//chance between 0 and 1, the ammount that is being redirected (how much goes from the ally to the player
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* redirectScalingGraph;
	//chance between 0 and 1, the ammount of what is redirected that is being absorbed
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* absorbScalingGraph;

	UFUNCTION(BlueprintImplementableEvent, Category = "Modifier")
	void DamageEvent();

	virtual bool OnDamage(int32& damage, ANetworkCharacter* damageDealer);
};

//increases attack damage of ally based on missing health
UCLASS()
class UNREALPROJECT_API ATrustModifier : public AModifier
{
	GENERATED_BODY()

public:
	ATrustModifier();
	virtual void ModifierTick() override;
	virtual void ModifyCharacter() override;
	//the ammount of damage the ally gets multiplied by the normalised value of the missing health
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* damageScalingGraph;
};


//increases armor
UCLASS()
class UNREALPROJECT_API AArmorIncreaseModifier : public AModifier
{
	GENERATED_BODY()

public:
	AArmorIncreaseModifier();
	virtual void ModifyCharacter();

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
	UCurveFloat* armorScalingGraph;
};

//increases attack damage of ally based on missing health
UCLASS()
class UNREALPROJECT_API AMoveToModifier : public AModifier
{
	GENERATED_BODY()

public:
	AMoveToModifier();
	virtual void ModifierStart();
	virtual void ModifierTick() override;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		FVector targetPos;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		float moveTime;
private:
	FVector m_movePerTick;
};

//increases attack damage of ally based on missing health
UCLASS()
class UNREALPROJECT_API AHealthRegenPercentageModifier : public AModifier
{
	GENERATED_BODY()

public:
	AHealthRegenPercentageModifier();

	//normalised percentage (0-1)
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* scalingGraph;

	virtual void ModifierTick() override;
};

//increases mana regen multiplier
UCLASS()
class UNREALPROJECT_API AManaRegenMultiplierModifier : public AModifier
{
	GENERATED_BODY()

public:
	AManaRegenMultiplierModifier();
	virtual void ModifyCharacter();

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* manaRegenMultiplierScalingGraph;
};


//increases mana regen multiplier
UCLASS()
class UNREALPROJECT_API AManaCostMultiplierModifier : public AModifier
{
	GENERATED_BODY()

public:
	AManaCostMultiplierModifier();
	virtual void ModifyCharacter();

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* manaCostMultiplierScalingGraph;
};

//debuffs positive effects
UCLASS()
class UNREALPROJECT_API AEffectMultiplierModifier : public AModifier
{
	GENERATED_BODY()

public:
	AEffectMultiplierModifier();
	virtual void ModifyCharacter();

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		bool positive;

	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* effectMultiplierScalingGraph;
};

//debuffs positive effects
UCLASS()
class UNREALPROJECT_API ACastingMovementSpeedMultiplierModifier : public AModifier
{
	GENERATED_BODY()

public:
	ACastingMovementSpeedMultiplierModifier();
	virtual void ModifyCharacter();


	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* movementSpeedMultiplierScalingGraph;
};

// deals more damage depending on the enemies hp (black/white threshhold)
UCLASS()
class UNREALPROJECT_API AReaperModifier : public AModifier
{
	GENERATED_BODY()

public:
	AReaperModifier();
	virtual bool OnDealDamage(int32& damage, ANetworkCharacter* damageTaker) override;

	//true == more damage when current health is less than threshhold  false == more damage when current health is more than threshhold
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		bool smaller;
		UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* damagemultiplier;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* threshhold;
};

//increases/decreases magic damage
UCLASS()
class UNREALPROJECT_API AMagicDamageMultiplierModifier : public AModifier
{
	GENERATED_BODY()

public:
	AMagicDamageMultiplierModifier();
	virtual void ModifyCharacter();


	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* magicDamageMultiplierScalingGraph;
};

//increases/decreases magic damage
UCLASS()
class UNREALPROJECT_API AStandardMeleeModifier : public AModifier
{
	GENERATED_BODY()

		float m_timer;
public:
	virtual void ModifierTick() override;
	AStandardMeleeModifier();
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		float maxTime;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		int32  maxCount;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Modifier")
		int32 count;
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		int32 team;
	UFUNCTION(BlueprintCallable, Category = "Modifier")
		bool AddCount();
};

//converts damage recieved to mana
UCLASS()
class UNREALPROJECT_API ADamageToManaModifier : public AModifier
{
	GENERATED_BODY()
public:
	ADamageToManaModifier();

	//the threshhold (between 0 and 1) where the effect will be proced
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn), Category = "Modifier")
		UCurveFloat* multiplier;
private:

	virtual void AfterDamage(int32 damage) override;
};