// Project Lab - NHTV Igad #include "UnrealProject.h" #include "TouhouBoss.h" #include "CreatureSpawn.h" #include "AbilityEventGroup.h" #include "AbilityInfo.h" #include "Modifier.h" #include "NativeModifiers.h" #include "DefaultGameMode.h" #include "NetworkPlayer.h" ATouhouBoss::ATouhouBoss() { PrimaryActorTick.bCanEverTick = true; /* AudioComp = CreateDefaultSubobject(TEXT("Boss Audio")); if (AudioComp) { AudioComp->bAutoActivate = false; // with this true the sounds play at spawn (game starts) } */ outOfCombatRegen = 25.0f; secondPhasePercentage = 0.5f; rotationSpeed = 1; cooldown = 2.5f; } void ATouhouBoss::BeginPlay() { Super::BeginPlay(); if (Role != ROLE_Authority) return; m_engaged = false; } void ATouhouBoss::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); if (Role != ROLE_Authority) return; m_walkTimer = 0.0f; // Drop a key if (m_health <= 0) { ANetworkPlayer* const killedBy = Cast(GetLastPlayerDamage()); if (IsValid(killedBy) && IsValid(m_spawn)) { killedBy->AssignKey(PlayerKeyType::TreasureRoomKey, m_spawn); onBossKilled.Broadcast(killedBy->GetTeam()); } } } void ATouhouBoss::m_Engaged() { Super::m_Engaged(); m_engaged = true; ModifierManager* mod = GetModifierManager(); if (mod != nullptr && m_regenModifier != nullptr) { // Stop regenerating health. m_regenModifier->ForceDestroy(); m_regenModifier = nullptr; SetShield(false); // Plays a sound indicating that the boss was engaged and start playing the boss music. //PlayEngageSound(); } } void ATouhouBoss::m_Disengaged() { Super::m_Disengaged(); ModifierManager* mod = GetModifierManager(); if (mod != nullptr && m_regenModifier == nullptr) { m_engaged = false; // Start regenerating health. m_regenModifier = mod->AddModifier(ARegenModifier::StaticClass(), 0); Cast(m_regenModifier)->regenPerTick = outOfCombatRegen; // Remove invincibility if it's active. if (m_invincibilityModifier) { m_invincibilityModifier->ForceDestroy(); m_invincibilityModifier = nullptr; SetShield(false); } } } void ATouhouBoss::Tick(float deltaTime) { Super::Tick(deltaTime); // Only execute boss code on the server. if (Role != ROLE_Authority) return; // Calculate health as percentage for deciding which phase the boss should be in. float healthPerc = (float)m_health / (float)m_maxHealth; // If the distance of the target to the spawn is greater than the aggro range of the spawner, // then lose the target. if (IsValid(target)) { float targetDistSqr = FVector::DistSquared(target->GetActorLocation(), m_spawn->SpawnResetPosition()); float aggroSqr = m_spawn->deaggroRadius * m_spawn->deaggroRadius; if (aggroSqr < targetDistSqr) { target = nullptr; } } //disengage if (!IsValid(target) && m_regenModifier == nullptr) { m_Disengaged(); } //engage else if (target && !m_engaged) { m_Engaged(); } if (m_engaged) { if (m_invincibilityModifier) { m_invincibilityModifier->ForceDestroy(); m_invincibilityModifier = nullptr; SetShield(false); } if (!IsValid(target)) return; WalkPhase(deltaTime); } } void ATouhouBoss::WalkPhase(float deltaTime) { MoveToPoint(target->GetActorLocation()); m_walkTimer += deltaTime; // After 2.5 seconds, cast a random ability. if (m_walkTimer > cooldown && abilities.Num() > 0 && target) { // Cast a random ability UAbilityInfo* ability = abilities[FMath::Rand() % abilities.Num()]; if(IsValid(ability)) CastAbility(ability); m_walkTimer = 0; } } void ATouhouBoss::m_SpawnModifiers() { /*ModifierManager* mod = GetModifierManager(); if (mod != nullptr) { //m_regenModifier = mod->AddModifier(ARegenModifier::StaticClass(), 0); }*/ } void ATouhouBoss::SetShield_Implementation(bool on) { FWARNING("shield implemtentation not set in ATouHouBoss"); return; }