185 lines
4.7 KiB
C++
185 lines
4.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "BladeSmithWeaponComponent.h"
|
|
#include "BladeSmithCharacter.h"
|
|
#include "IronBlock.h"
|
|
#include "Animation/AnimInstance.h"
|
|
#include "Components/SkeletalMeshComponent.h"
|
|
#include "EnhancedInputComponent.h"
|
|
#include "EnhancedInputSubsystems.h"
|
|
#include "InputActionValue.h"
|
|
#include "Engine/LocalPlayer.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "Engine/World.h"
|
|
#include "DrawDebugHelpers.h"
|
|
#include "PhysicsEngine/PhysicsHandleComponent.h"
|
|
#include "Camera/CameraComponent.h"
|
|
|
|
// Sets default values for this component's properties
|
|
UBladeSmithWeaponComponent::UBladeSmithWeaponComponent()
|
|
{
|
|
// 设置默认值
|
|
HammerHeadOffset = FVector(0.0f, 0.0f, -50.0f);
|
|
HammerForce = 1000.0f;
|
|
HammerRange = 200.0f;
|
|
}
|
|
|
|
bool UBladeSmithWeaponComponent::AttachHammer(ABladeSmithCharacter* TargetCharacter)
|
|
{
|
|
Character = TargetCharacter;
|
|
if (Character == nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 附加到角色的第一人称网格
|
|
USkeletalMeshComponent* CharacterMesh = Character->GetMesh1P();
|
|
if (CharacterMesh)
|
|
{
|
|
AttachToComponent(CharacterMesh, FAttachmentTransformRules::KeepRelativeTransform);
|
|
SetOnlyOwnerSee(true);
|
|
SetOwnerNoSee(false);
|
|
CastShadow = false;
|
|
}
|
|
|
|
// 设置输入映射
|
|
if (APlayerController* PlayerController = Cast<APlayerController>(Character->GetController()))
|
|
{
|
|
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
|
{
|
|
if (HammerMappingContext)
|
|
{
|
|
Subsystem->AddMappingContext(HammerMappingContext, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void UBladeSmithWeaponComponent::SwingHammer()
|
|
{
|
|
// 播放锤击动画
|
|
if (HammerSwingAnimation && Character)
|
|
{
|
|
USkeletalMeshComponent* CharacterMesh = Character->GetMesh1P();
|
|
if (CharacterMesh)
|
|
{
|
|
CharacterMesh->PlayAnimation(HammerSwingAnimation, false);
|
|
}
|
|
}
|
|
|
|
// 延迟执行锤击检测,等待动画播放
|
|
GetWorld()->GetTimerManager().SetTimerForNextTick([this]()
|
|
{
|
|
PerformHammerHit();
|
|
});
|
|
}
|
|
|
|
FVector UBladeSmithWeaponComponent::GetHammerHeadLocation() const
|
|
{
|
|
if (Character)
|
|
{
|
|
FVector CameraLocation = Character->GetFirstPersonCameraComponent()->GetComponentLocation();
|
|
FVector CameraForward = Character->GetFirstPersonCameraComponent()->GetForwardVector();
|
|
|
|
// 计算锤子头部位置
|
|
return CameraLocation + CameraForward * HammerRange + HammerHeadOffset;
|
|
}
|
|
return FVector::ZeroVector;
|
|
}
|
|
|
|
void UBladeSmithWeaponComponent::PerformHammerHit()
|
|
{
|
|
if (!Character)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 获取锤子头部位置
|
|
FVector HammerHeadLocation = GetHammerHeadLocation();
|
|
FVector StartLocation = Character->GetFirstPersonCameraComponent()->GetComponentLocation();
|
|
|
|
// 执行射线检测
|
|
FHitResult HitResult;
|
|
FCollisionQueryParams QueryParams;
|
|
QueryParams.AddIgnoredActor(Character);
|
|
QueryParams.bTraceComplex = true;
|
|
|
|
bool bHit = GetWorld()->LineTraceSingleByChannel(
|
|
HitResult,
|
|
StartLocation,
|
|
HammerHeadLocation,
|
|
ECC_Visibility,
|
|
QueryParams
|
|
);
|
|
|
|
// 绘制调试线
|
|
FColor DebugColor = bHit ? FColor::Red : FColor::Green;
|
|
DrawDebugLine(GetWorld(), StartLocation, HammerHeadLocation, DebugColor, false, 2.0f);
|
|
|
|
if (bHit)
|
|
{
|
|
DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.0f, 8, FColor::Yellow, false, 2.0f);
|
|
}
|
|
|
|
// 处理碰撞结果
|
|
if (bHit)
|
|
{
|
|
// 播放锤击音效
|
|
if (HammerHitSound)
|
|
{
|
|
UGameplayStatics::PlaySoundAtLocation(this, HammerHitSound, HitResult.ImpactPoint, FRotator::ZeroRotator);
|
|
}
|
|
|
|
// 检查是否击中铁块
|
|
AIronBlock* IronBlock = Cast<AIronBlock>(HitResult.GetActor());
|
|
if (IronBlock)
|
|
{
|
|
HandleIronBlockHit(IronBlock, HitResult);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UBladeSmithWeaponComponent::HandleIronBlockHit(AIronBlock* IronBlock, const FHitResult& HitResult)
|
|
{
|
|
if (!IronBlock)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 计算锤击力度(基于角色移动速度)
|
|
float ImpactForce = HammerForce;
|
|
if (Character)
|
|
{
|
|
FVector CharacterVelocity = Character->GetVelocity();
|
|
float SpeedMultiplier = FMath::Clamp(CharacterVelocity.Size() / 500.0f, 0.5f, 2.0f);
|
|
ImpactForce *= SpeedMultiplier;
|
|
}
|
|
|
|
// 调用铁块的锤击处理函数
|
|
IronBlock->OnHammerHit(HitResult);
|
|
|
|
UE_LOG(LogTemp, Log, TEXT("Hammer hit iron block with force: %f"), ImpactForce);
|
|
}
|
|
|
|
void UBladeSmithWeaponComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
Super::EndPlay(EndPlayReason);
|
|
|
|
// 清理输入映射
|
|
if (Character)
|
|
{
|
|
if (APlayerController* PlayerController = Cast<APlayerController>(Character->GetController()))
|
|
{
|
|
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
|
{
|
|
if (HammerMappingContext)
|
|
{
|
|
Subsystem->RemoveMappingContext(HammerMappingContext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |