// 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(TEXT("/Game/ScalingCurves/CF_PlayerHealth")).Object; healthRegenCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_PlayerHealthRegen")).Object; manaCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_PlayerMana")).Object; manaRegenCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_PlayerManaRegen")).Object; armorCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_PlayerArmor")).Object; attackSpeedCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_PlayerAttackSpeed")).Object; creatureDamageTakenCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_CreatureDamageTaken")).Object; creatureDamageDealtCurve = ConstructorHelpers::FObjectFinder(TEXT("/Game/ScalingCurves/CF_CreatureDamageDealt")).Object; teamData = ConstructorHelpers::FObjectFinder(TEXT("/Game/Assets/TeamData")).Object; playerCircle = CreateDefaultSubobject("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(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(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(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(PlayerState); if (state && state->teamMate) return state->teamMate->character; return nullptr; } void ANetworkPlayer::m_SetLevelStats() { Super::m_SetLevelStats(); // Update stats ADefaultPlayerState* state = Cast(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(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& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(ANetworkPlayer, m_keyState); } FCharacterClassProperty ANetworkPlayer::GetCharacterClassProperties() const { static FCharacterClassProperty dummy; if(!Controller) return dummy; return Cast(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]; } } } }