#include "UnrealProject.h" #include "SpawnerBase.h" #include "CharacterBase.h" #include "ItemBase.h" #include "BaseSkillObject.h" #include "WiebertAnimation.h" #include "DefaultGameState.h" #include "MainCharacterAnimation.h" #include "SkillTreeState.h" ACharacterBase::ACharacterBase() { m_team = 0; bReplicates = true; visionRadius = 1000; } void ACharacterBase::BeginPlay() { Super::BeginPlay(); // If this actor is attached to a spawner base, it must be ignored AActor* const parent = GetAttachParentActor(); if (parent != nullptr && parent->IsA()) return; // Register to the minimap UWorld* const world = GetWorld(); if (IsValid(world)) { ADefaultGameState* const gameState = Cast(world->GetGameState()); if (IsValid(gameState)) { const FVector location = GetActorLocation(); minimapHandle.position = FVector2D(location.X, location.Y); minimapHandle.character = this; gameState->minimapQuadtree.AddObject(minimapHandle); } } } void ACharacterBase::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); // Unregister to the minimap ADefaultGameState* const gameState = Cast(GetWorld()->GetGameState()); if (IsValid(gameState) && minimapHandle.root) gameState->minimapQuadtree.RemoveObject(minimapHandle); minimapHandle.root = nullptr; minimapHandle.node = nullptr; minimapHandle.character = nullptr; } void ACharacterBase::Tick(float deltaTime) { Super::Tick(deltaTime); const FVector location = GetActorLocation(); minimapHandle.position = FVector2D(location.X, location.Y); } void ACharacterBase::m_EquipSkills_Implementation(const TArray& skills) { for(UBaseSkillObject* skill : skills) { // Check if not yet equiped if(!m_equipedSkills.Contains(skill)) { AItemBase::CreateItemsFromSkill(GetWorld(), skill, this); m_equipedSkills.Add(skill); } } } void ACharacterBase::EquipSkills(const TArray& skills) { m_EquipSkills(skills); } void ACharacterBase::EquipSkillsFromSkillTreeState(const struct FSkillTreeState& skState) { TArray skillObjects; for(const FSkillTreeStateObject& obj : skState.objects) { UBaseSkillObject* skillObj = obj.skillObject->GetDefaultObject(); if(!skillObj) continue; skillObjects.Add(skillObj); } m_EquipSkills(skillObjects); } void ACharacterBase::EquipItems_Implementation(const TArray>& itemClasses) { for(auto& itemClass : itemClasses) { EquipItem_Implementation(itemClass); } } void ACharacterBase::EquipItem_Implementation(TSubclassOf itemClass) { if(itemClass == nullptr) return; AItemBase* item = GetWorld()->SpawnActor(itemClass); AItemBase* existing = AItemBase::CheckSlotOccupied(item->type, this); if(existing) existing->Destroy(); if(item) { if(!item->AttachItemToCharacter(this)) { item->Destroy(); } } } void ACharacterBase::SendInitialAppearance(APlayerController* pc) { if(Role == ROLE_Authority) { m_ReceiveInitialAppearance(pc, GetEquipedSkills(), GetCharacterCustomization()); } } void ACharacterBase::m_ReceiveInitialAppearance_Implementation(APlayerController* pc, const TArray& itemClasses, const FCharacterCustomization& cc) { APlayerController* localPC = GetGameInstance()->GetFirstLocalPlayerController(); if(pc == localPC) { EquipSkills(itemClasses); SetCustomizations_Implementation(cc); } } void ACharacterBase::Destroyed() { auto destroyItems = m_items; for(auto item : destroyItems) { if(IsValid(item)) { item->Destroy(); } } Super::Destroyed(); } TArray> ACharacterBase::GetEquipedItemClasses() const { TArray> ret; for(auto item : m_items) { ret.Add(item->GetClass()); } return ret; } const TArray& ACharacterBase::GetEquipedItems() const { return m_items; } const FCharacterCustomization& ACharacterBase::GetCharacterCustomization() const { static FCharacterCustomization dummy; USkeletalMeshComponent* skMesh = GetMesh(); if(skMesh) { UWiebertAnimation* animBP = Cast(skMesh->GetAnimInstance()); if(animBP) { return animBP->charCustomization; } else { UMainCharacterAnimation* charBP = Cast(skMesh->GetAnimInstance()); if (charBP) { return charBP->charCustomization; } } } return dummy; } const TArray& ACharacterBase::GetEquipedSkills() const { return m_equipedSkills; } void ACharacterBase::UnequipSkills_Implementation(const TArray& skills) { for(auto skill : skills) { if(m_equipedSkills.Contains(skill)) { TArray items; m_mappedItems.MultiFind(skill, items); for(auto item : items) item->Destroy(); m_equipedSkills.Remove(skill); } } } void ACharacterBase::ClearEquipment_Implementation() { auto clearItems = m_items; for(auto item : clearItems) { if(IsValid(item)) { item->Destroy(); } } m_mappedItems.Reset(); m_equipedSkills.SetNum(0); m_items.SetNum(0); } void ACharacterBase::SetCustomizations_Implementation(const FCharacterCustomization& cc) { USkeletalMeshComponent* skMesh = GetMesh(); if(skMesh) { UWiebertAnimation* animBP = Cast(skMesh->GetAnimInstance()); if(animBP) { animBP->SetCharacterCustomization(cc); } else { UMainCharacterAnimation* charBP = Cast(skMesh->GetAnimInstance()); if (charBP) { charBP->SetCharacterCustomization(cc); } } } else { GERROR("Can't set customization, no skeletal mesh on character"); } } void ACharacterBase::m_OnItemAdded(AItemBase* item) { // Add item to list of items assigned to given skill object if(item->skillObject) m_mappedItems.Add(item->skillObject, item); m_items.Add(item); } void ACharacterBase::m_OnItemRemoved(AItemBase* item) { // Remove mapped item m_mappedItems.RemoveSingle(item->skillObject, item); m_items.Remove(item); } void ACharacterBase::m_OnRep_Team() { } int32 ACharacterBase::GetTeam() const { return m_team; } void ACharacterBase::SetTeam(int32 team) { check(Role == ROLE_Authority); // Server only call m_team = team; m_OnRep_Team(); } void ACharacterBase::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(ACharacterBase, m_team); DOREPLIFETIME(ACharacterBase, playerName); } void ACharacterBase::RegisterEffect(class AEffect* effect) { if(effect != nullptr) m_effects.Add(effect); } void ACharacterBase::UnRegisterEffect(class AEffect* effect) { if(effect == nullptr) { FWARNING("invalid effect is unregistering"); return; } m_effects.Remove(effect); } TArray ACharacterBase::GetEffects() { return m_effects; }