Files
BladeSmith/Source/BladeSmith/BladeSmithWeaponComponent.cpp
T
2025-08-06 23:47:59 +08:00

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);
}
}
}
}
}