haxis/Source/UnrealProject/Creatures/NetworkPlayer.cpp

475 lines
14 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "NetworkPlayer.h"
#include "DefaultPlayerController.h"
#include "ItemBase.h"
#include "BaseSkillObject.h"
#include "AbilityInfo.h"
#include "NetworkSwitch.h"
#include "DefaultGameMode.h"
#include "DefaultPlayerState.h"
#include "IngameSkillTree.h"
#include "Modifier.h"
#include "SpawnerBase.h"
#include "TeamData.h"
static UTeamData* teamData;
ANetworkPlayer::ANetworkPlayer()
{
bReplicates = true;
m_SetupCamera();
m_initialised = false;
m_keyState = 0;
healthCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_PlayerHealth")).Object;
healthRegenCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_PlayerHealthRegen")).Object;
manaCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_PlayerMana")).Object;
manaRegenCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_PlayerManaRegen")).Object;
armorCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_PlayerArmor")).Object;
attackSpeedCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_PlayerAttackSpeed")).Object;
creatureDamageTakenCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_CreatureDamageTaken")).Object;
creatureDamageDealtCurve = ConstructorHelpers::FObjectFinder<UCurveFloat>(TEXT("/Game/ScalingCurves/CF_CreatureDamageDealt")).Object;
teamData = ConstructorHelpers::FObjectFinder<UTeamData>(TEXT("/Game/Assets/TeamData")).Object;
playerCircle = CreateDefaultSubobject<UStaticMeshComponent>("Player Circle");
playerCircle->AttachTo(RootComponent);
visionRadius = 2500;
}
void ANetworkPlayer::BeginPlay()
{
m_levelStatsInitialized = false;
Super::BeginPlay();
m_initialised = false;
}
void ANetworkPlayer::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
if (Role != ROLE_Authority)
return;
// Return the keys
ANetworkPlayer* const killedBy = Cast<ANetworkPlayer>(GetLastPlayerDamage());
if (m_health <= 0 && IsValid(killedBy) && killedBy->GetTeam() != GetTeam())
{
FText Source = FText::FromString(killedBy->playerName);
FText Target = FText::FromString(playerName);
onPlayerKilled.Broadcast(Source, Target, killedBy->GetTeam(), GetTeam());
// Assign keys to the player that killed us
for (auto iter = m_keyOrigins.CreateIterator(); iter; ++iter)
{
ASpawnerBase** find = killedBy->m_keyOrigins.Find(iter->Key);
if (!find)
killedBy->m_keyOrigins.Add(iter->Key, iter->Value);
else
iter->Value->hasDroppedKey = false;
}
killedBy->m_keyState |= m_keyState;
}
else
{
// Return the keys we have
for (auto iter = m_keyOrigins.CreateIterator(); iter; ++iter)
{
if (IsValid(iter->Value))
iter->Value->hasDroppedKey = false;
}
}
m_keyState = 0;
m_keyOrigins.Reset();
// Clean up screen effects and delegates.
m_filterTimelines.Empty();
for (int32 i = 0; i < m_delegates.Num(); i++)
{
GetWorldTimerManager().ClearTimer(m_delegates[i]);
}
m_delegates.Empty();
}
void ANetworkPlayer::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
for (auto& timeline : m_filterTimelines)
{
timeline.Value.TickTimeline(DeltaSeconds);
}
// Server only
if(Role == ROLE_Authority)
{
ADefaultPlayerState* state = Cast<ADefaultPlayerState>(PlayerState);
if(!m_levelStatsInitialized)
{
m_modifierManager->RecalculateCharacter();
CheckStatsOverflow();
if(!m_initialised)
{
m_health = m_maxHealth;
m_mana = m_maxMana;
m_initialised = true;
}
m_levelStatsInitialized = true;
}
}
}
void ANetworkPlayer::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
OnRep_PlayerState();
}
void ANetworkPlayer::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
// Initialize player circle
UMaterialInstanceDynamic* mi = playerCircle->CreateDynamicMaterialInstance(0);
FLinearColor teamColor = teamData->GetTeamColor(Cast<ADefaultPlayerState>(PlayerState)->GetTeam());
mi->SetVectorParameterValue("Color", teamColor);
}
void ANetworkPlayer::ResetModifiers()
{
// Learn abilities
m_SetLevelStats();
Super::ResetModifiers();
}
void ANetworkPlayer::OnLevelUp_Server(int32 newLevel)
{
check(Role == ROLE_Authority);
// Learn abilities
//m_SetLevelStats();
// Recalculate modifiers for new level
if(m_modifierManager)
m_modifierManager->RecalculateCharacter();
CheckStatsOverflow();
// Call blueprint level up event (server-side)
OnLevelUp(newLevel);
}
class ANetworkPlayer* ANetworkPlayer::GetTeamMate() const
{
ADefaultPlayerState* state = Cast<ADefaultPlayerState>(PlayerState);
if (state && state->teamMate)
return state->teamMate->character;
return nullptr;
}
void ANetworkPlayer::m_SetLevelStats()
{
Super::m_SetLevelStats();
// Update stats
ADefaultPlayerState* state = Cast<ADefaultPlayerState>(PlayerState);
float level = 1;
if(IsValid(state))
level = (float)state->GetLevel();
float newHealth = SampleHealthCurve(level);
float newMana = SampleManaCurve(level);
float newArmor = SampleArmorCurve(level);
float newAttackSpeed = SampleAttackSpeedCurve(level);
//GWPRINT(L"Setting level bases stats for level " + level + L"(" + levelScale + L")");
//GWPRINT(L"Health = " + m_maxHealth + L"->" + newHealth);
//GWPRINT(L"Mana = " + m_maxMana + L"->" + newMana);
//GWPRINT(L"Armor = " + m_armor + L"->" + newArmor);
//GWPRINT(L"Attack Speed = " + m_attackSpeed + L"->" + newAs);
if(!m_levelStatsInitialized)
{
m_health = newHealth;
m_mana = newMana;
}
m_maxHealth = newHealth;
m_maxMana = newMana;
baseArmor = newArmor;
m_attackSpeed = newAttackSpeed;
if(Role == ROLE_Authority)
{
// Send level-up/learn skill command
ADefaultPlayerController* controller = Cast<ADefaultPlayerController>(GetController());
if(controller)
{
controller->LearnSkillsForLevel();
}
}
}
void ANetworkPlayer::OnLevelUp_Implementation(int32 newLevel)
{
m_levelStatsInitialized = false;
}
bool ANetworkPlayer::ToggleSwitch_Validate(ANetworkSwitch* networkSwitch)
{
return networkSwitch && FVector::Dist(GetActorLocation(), networkSwitch->GetActorLocation()) < 600;
}
void ANetworkPlayer::ToggleSwitch_Implementation(ANetworkSwitch* networkSwitch)
{
if(FVector::Dist(GetActorLocation(), networkSwitch->GetActorLocation()) < 300)
networkSwitch->Toggle();
}
float ANetworkPlayer::SampleHealthCurve(float in)
{
if(GetCharacterClassProperties().healthCurve)
{
return GetCharacterClassProperties().healthCurve->GetFloatValue(in);
}
return healthCurve->GetFloatValue(in);
}
float ANetworkPlayer::SampleManaCurve(float in)
{
if(GetCharacterClassProperties().manaCurve)
{
return GetCharacterClassProperties().manaCurve->GetFloatValue(in);
}
return manaCurve->GetFloatValue(in);
}
float ANetworkPlayer::SampleArmorCurve(float in)
{
if(GetCharacterClassProperties().armorCurve)
{
return GetCharacterClassProperties().armorCurve->GetFloatValue(in);
}
return armorCurve->GetFloatValue(in);
}
float ANetworkPlayer::SampleAttackSpeedCurve(float in)
{
if(GetCharacterClassProperties().attackSpeedCurve)
{
return GetCharacterClassProperties().attackSpeedCurve->GetFloatValue(in);
}
return attackSpeedCurve->GetFloatValue(in);
}
bool ANetworkPlayer::HasKey(PlayerKeyType keyType) const
{
if (keyType == PlayerKeyType::None)
return m_keyState == 0;
return ((1 << (int32)keyType) & m_keyState) != 0;
}
bool ANetworkPlayer::HasAnyKey() const
{
return m_keyState != 0;
}
bool ANetworkPlayer::AssignKey(PlayerKeyType keyType, ASpawnerBase* origin)
{
check(Role == ROLE_Authority);
if (HasKey(keyType))
return false;
origin->hasDroppedKey = true;
// Store the origin for later
m_keyOrigins.Add((uint8)keyType, origin);
m_keyState += (1 << (int32)keyType);
return true;
}
bool ANetworkPlayer::ClearKey(PlayerKeyType keyType)
{
check(Role == ROLE_Authority);
if (!HasKey(keyType))
return false;
// Allow the boss to drop keys again
ASpawnerBase** find = m_keyOrigins.Find((uint8)keyType);
if (find)
{
if(IsValid(*find)) (*find)->hasDroppedKey = false;
m_keyOrigins.Remove((uint8)keyType);
}
m_keyState -= (1 << (int32)keyType);
return true;
}
void ANetworkPlayer::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ANetworkPlayer, m_keyState);
}
FCharacterClassProperty ANetworkPlayer::GetCharacterClassProperties() const
{
static FCharacterClassProperty dummy;
if(!Controller)
return dummy;
return Cast<ADefaultPlayerController>(Controller)->GetCharacterClassProperties();
}
//Screen Filters
void ANetworkPlayer::SetFilterDuration(float duration, UPostProcessComponent* filter)
{
FTimerHandle uniqueHandle;
FTimerDelegate stopFilterDelegate = FTimerDelegate::CreateUObject(this, &ANetworkPlayer::StopFilter, filter, uniqueHandle);
GetWorldTimerManager().SetTimer(uniqueHandle, stopFilterDelegate, duration, false);
m_delegates.Add(uniqueHandle);
}
void ANetworkPlayer::SetTimelineDuration(float duration, UPostProcessComponent* filter)
{
FTimerHandle uniqueHandle;
FTimerDelegate stopFilterDelegate = FTimerDelegate::CreateUObject(this, &ANetworkPlayer::StopTimeline, filter, uniqueHandle);
GetWorldTimerManager().SetTimer(uniqueHandle, stopFilterDelegate, duration, false);
m_delegates.Add(uniqueHandle);
}
void ANetworkPlayer::StartFilter(float duration, UPostProcessComponent* filter, UCurveFloat* timelineCurve)
{
if ( m_filterTimelines.Contains(filter) ) return;
if (timelineCurve)
{
FTimeline timeLine;
FOnTimelineFloatStatic timelineDelegate;
timelineDelegate.BindUObject(this, &ANetworkPlayer::FilterUpdate, filter);
timeLine.AddInterpFloat(timelineCurve, timelineDelegate);
timeLine.SetPlayRate(1.0f / duration);
timeLine.PlayFromStart();
m_filterTimelines.Add(filter, timeLine);
SetFilterDuration(duration, filter);
}
filter->bEnabled = true;
}
void ANetworkPlayer::StartFilterWithDelegate(float duration, UPostProcessComponent* filter, UCurveFloat* timelineCurve, FPostAction action)
{
if ( m_filterTimelines.Contains(filter) ) return;
if (timelineCurve)
{
FTimeline timeLine;
FOnTimelineFloatStatic timelineDelegate;
timelineDelegate.BindUObject(this, &ANetworkPlayer::FilterUpdate, filter, action);
timeLine.AddInterpFloat(timelineCurve, timelineDelegate);
timeLine.SetPlayRate(1.0f / duration);
timeLine.PlayFromStart();
m_filterTimelines.Add(filter, timeLine);
SetFilterDuration(duration, filter);
}
filter->bEnabled = true;
}
void ANetworkPlayer::EnableFilter(float duration, UPostProcessComponent* filter, UCurveFloat* timelineCurve)
{
if (m_filterTimelines.Contains(filter)) return;
if (!timelineCurve)
{
YERROR("No timelineCurve given.");
return;
}
FTimeline timeLine;
FOnTimelineFloatStatic timelineDelegate;
timelineDelegate.BindUObject(this, &ANetworkPlayer::FilterUpdate, filter);
timeLine.AddInterpFloat(timelineCurve, timelineDelegate);
timeLine.SetPlayRate(1.0f / duration);
timeLine.PlayFromStart();
m_filterTimelines.Add(filter, timeLine);
SetTimelineDuration(duration, filter);
filter->bEnabled = true;
}
void ANetworkPlayer::DisableFilter(float duration, UPostProcessComponent* filter, UCurveFloat* timeline)
{
StartFilter(duration, filter, timeline);
}
void ANetworkPlayer::EnableFilterWithDelegate(float duration, UPostProcessComponent* filter, UCurveFloat* timelineCurve, FPostAction action)
{
if (m_filterTimelines.Contains(filter)) return;
if (!timelineCurve)
{
YERROR("No timelineCurve given.");
return;
}
FTimeline timeLine;
FOnTimelineFloatStatic timelineDelegate;
timelineDelegate.BindUObject(this, &ANetworkPlayer::FilterUpdate, filter, action);
timeLine.AddInterpFloat(timelineCurve, timelineDelegate);
timeLine.SetPlayRate(1.0f / duration);
timeLine.PlayFromStart();
m_filterTimelines.Add(filter, timeLine);
SetTimelineDuration(duration, filter);
filter->bEnabled = true;
}
void ANetworkPlayer::DisableFilterWithDelegate(float duration, UPostProcessComponent* filter, UCurveFloat* timeline, FPostAction action)
{
StartFilterWithDelegate(duration, filter, timeline, action);
}
void ANetworkPlayer::StopFilter(UPostProcessComponent* filter, FTimerHandle handle)
{
filter->bEnabled = false;
m_delegates.Remove(handle);
if (!m_filterTimelines.Contains(filter))
{
YERROR("Can't find filter in timeline.");
return;
}
m_filterTimelines.Remove(filter);
}
void ANetworkPlayer::StopTimeline( UPostProcessComponent* filter, FTimerHandle handle )
{
m_delegates.Remove(handle);
if (!m_filterTimelines.Contains(filter))
{
YERROR("Can't find filter in timeline.");
return;
}
m_filterTimelines.Remove(filter);
}
void ANetworkPlayer::FilterUpdate(float value, UPostProcessComponent* filter)
{
filter->BlendWeight = value;
}
void ANetworkPlayer::FilterUpdate(float value, UPostProcessComponent* filter, FPostAction action)
{
action.ExecuteIfBound(value, filter);
}
void ANetworkPlayer::AddThreatLevel_Client_Implementation(const float a_NewThreat)
{
threats.Add(a_NewThreat);
threatLevel = a_NewThreat > threatLevel ? a_NewThreat : threatLevel;
}
void ANetworkPlayer::RemoveThreatLevel_Client_Implementation(const float a_NewThreat)
{
threats.RemoveSingle(a_NewThreat);
if (a_NewThreat == threatLevel)
{
threatLevel = 0;
for (int32 i = 0; i < threats.Num(); i++)
{
if (threats[i] > threatLevel)
{
threatLevel = threats[i];
}
}
}
}