Enable Disable CHARACTER MOVMENT

Screenshot 2024-06-02 102141

Okay, the problem is! when I am dead, I can move but respawning, I cant, however, the character does respawn, but just in a neutral state, not in the Attacking state as I have it set. please help!!!

Can you attach the whole ASlashCharacter code file in preformatted text instead of an image of part of a function?

I acctually just solved it, I had to set the state to unoccupied not attacking, but now the problem is my enemies don’t attack anymore after I respawn. do I just copy paste the code or is there a third party thing I can use for that?

Please If you need help, Paste the whole code file using the inline code block that you can use in the reply.

I am getting confused by the way you structure your question. Is the player state set to something that the enemies can see and attack. Have you reset the state of enemies?

This is why its better if we can see the whole code so it can be analyzed.

okay… its very long, been working on this for a few months now… this is the whole character code, I can copy paste the enemy one as well if you need that one to. if there is a software that makes this easier for you, please let me know!

include “Character/SlashCharacter.h”
include “Camera/CameraComponent.h”
include “GameFramework/SpringArmComponent.h”
include “GameFramework/CharacterMovementComponent.h”
include “Components/StaticMeshComponent.h”
include “Component/AttributeComponent.h”
include “Item/Item.h”
include “Item/Weapon/Weapon.h”
include “Animation/AnimMontage.h”
include “HUD/SlashHUD.h”
include “HUD/SlashOverlay.h”

ASlashCharacter::ASlashCharacter()
{
PrimaryActorTick.bCanEverTick = true;

bUseControllerRotationRoll = false;
bUseControllerRotationPitch = true;
bUseControllerRotationYaw = true;

GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 400.f, 0.f);

GetMesh()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
GetMesh()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldDynamic, ECollisionResponse::ECR_Overlap);
GetMesh()->SetGenerateOverlapEvents(true);

CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(GetRootComponent());
CameraBoom->TargetArmLength = 300.f;

ViewCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("ViewCamera"));
ViewCamera->SetupAttachment(CameraBoom);

RespawnDelay = 2.0f;
RespawnLocation = FVector(0.f, 0.f, 0.f);

}

void ASlashCharacter::Tick(float DeltaTime)
{
if (Attributes && SlashOverlay)
{
Attributes->RegenStamina(DeltaTime);
SlashOverlay->SetStaminaBarPercent(Attributes->GetStaminaPercent());

}

}

void ASlashCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);

PlayerInputComponent->BindAxis(FName("MoveForward"), this, &ASlashCharacter::MoveForward);
PlayerInputComponent->BindAxis(FName("Turn"), this, &ASlashCharacter::Turn);
PlayerInputComponent->BindAxis(FName("LookUp"), this, &ASlashCharacter::LookUp);
PlayerInputComponent->BindAxis(FName("MoveRight"), this, &ASlashCharacter::MoveRight);

PlayerInputComponent->BindAction(FName("Jump"), IE_Pressed, this, &ASlashCharacter::Jump);
PlayerInputComponent->BindAction(FName("Equip"), IE_Pressed, this, &ASlashCharacter::EKeyPressed);
PlayerInputComponent->BindAction(FName("Attack"), IE_Pressed, this, &ASlashCharacter::Attack);
PlayerInputComponent->BindAction(FName("Dodge"), IE_Pressed, this, &ASlashCharacter::Dodge);

RespawnLocation;

}

void ASlashCharacter::Jump()
{
if (IsUnoccupied())
{
Super::Jump();
}
}

float ASlashCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
HandleDamage(DamageAmount);
SetHUDHealth();
return DamageAmount;
}

void ASlashCharacter::GetHit_Implementation(const FVector& ImpactPoint, AActor* Hitter)
{
Super::GetHit_Implementation(ImpactPoint, Hitter);

SetWeaponCollisionEnabled(ECollisionEnabled::NoCollision);
if (Attributes && Attributes->GetHealthPercentage() > 0.f)
{
	ActionState = EActionState::EAS_HitReaction;
}

}

void ASlashCharacter::Respawn()
{
RespawnLocation;
SlashOverlay->SetHealthBarPercent(100.f);
ActionState = EActionState::EAS_Unoccupied;

GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
GetMesh()->SetGenerateOverlapEvents(true);

}

void ASlashCharacter::BeginPlay()
{
Super::BeginPlay();

Tags.Add(FName("EngageableTarget"));

InitializeSlashOverlay();

}

void ASlashCharacter::MoveForward(float Value)
{
if (ActionState == EActionState::EAS_Attacking) return;
if (Controller != -1.f)
{
// find out which way is forward
const FRotator ControlRotation = GetControlRotation();
const FRotator YawRotation(0.f, ControlRotation.Yaw, 0.f);
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
}

void ASlashCharacter::MoveRight(float Value)
{
if (ActionState == EActionState::EAS_Attacking) return;
if (Controller && (Value != 0.f))
{
// find out which way is right
const FRotator ControlRotation = GetControlRotation();
const FRotator YawRotation(0.f, ControlRotation.Yaw, 0.f);

	const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
	AddMovementInput(Direction, Value);
}

}

void ASlashCharacter::Turn(float Value)
{
AddControllerYawInput(Value);
}

void ASlashCharacter::LookUp(float Value)
{
AddControllerPitchInput(Value);
}

void ASlashCharacter::EKeyPressed()
{
AWeapon* OverlappingWeapon = Cast(OverlappingItem);

if (OverlappingWeapon)
{
	EquipWeapon(OverlappingWeapon);
}
else 
{
	if (CanDisarm())
	{
		Disarm();
	}
	else if (CanArm())
	{
		Arm();
	}
}

}

void ASlashCharacter::Attack()
{
Super::Attack();
if (CanAttack())
{
PlayAttackMontage();
ActionState = EActionState::EAS_Attacking;
}
}

void ASlashCharacter::Dodge()
{
if (IsOccupied() || !HasEnoughStamina()) return;

PlayDodgeMontage();
ActionState = EActionState::EAS_Dodge;

if (Attributes && SlashOverlay)
{
	Attributes->UseStamina(Attributes->GetDodgeCost());
	SlashOverlay->SetStaminaBarPercent(Attributes->GetStaminaPercent());
}

}

void ASlashCharacter::EquipWeapon(AWeapon* Weapon)
{
Weapon->Equip(GetMesh(), FName(“RightHandSocket”), this, this);
CharacterState = ECharacterState::ECS_EquippedKnife;
OverlappingItem = nullptr;
EquippedWeapon = Weapon;
}

void ASlashCharacter::AttackEnd()
{
ActionState = EActionState::EAS_Unoccupied;
}

void ASlashCharacter::DodgeEnd()
{
Super::DodgeEnd();

ActionState = EActionState::EAS_Unoccupied;

}

bool ASlashCharacter::CanAttack()
{
return ActionState == EActionState::EAS_Unoccupied &&
CharacterState != ECharacterState::ECS_Unequipped;
}

bool ASlashCharacter::CanDisarm()
{
return ActionState == EActionState::EAS_Unoccupied &&
CharacterState != ECharacterState::ECS_Unequipped;
}

bool ASlashCharacter::CanArm()
{
return ActionState == EActionState::EAS_Unoccupied &&
CharacterState == ECharacterState::ECS_Unequipped &&
EquippedWeapon;
}

void ASlashCharacter::Disarm()
{
PlayEquipMontage(FName(“Unequip”));
CharacterState = ECharacterState::ECS_Unequipped;
}

void ASlashCharacter::Arm()
{
PlayEquipMontage(FName(“Equip”));
CharacterState = ECharacterState::ECS_EquippedKnife;
}

void ASlashCharacter::PlayEquipMontage(const FName& SectionName)
{
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
if (AnimInstance && EquipMontage)
{
AnimInstance->Montage_Play(EquipMontage);
AnimInstance->Montage_JumpToSectionsEnd(SectionName, EquipMontage);
}
}

void ASlashCharacter::Die()
{
Super::Die();

ActionState = EActionState::EAS_Dead;
DisableMeshCollision();
GetWorld()->GetTimerManager().SetTimer(RespawnTimerHandle, this, &ASlashCharacter::Respawn, RespawnDelay, false);

}

bool ASlashCharacter::HasEnoughStamina()
{
return Attributes && Attributes->GetStamina() > Attributes->GetDodgeCost();
}

bool ASlashCharacter::IsOccupied()
{
return ActionState != EActionState::EAS_Unoccupied;
}

void ASlashCharacter::AttachWeaponToBack()
{
if (EquippedWeapon)
{
EquippedWeapon->AttachMeshToSocket(GetMesh(), FName(“SpineSocket”));
}
}

void ASlashCharacter::AttachWeaponToHand()
{
if (EquippedWeapon)
{
EquippedWeapon->AttachMeshToSocket(GetMesh(), FName(“RightHandSocket”));
}
}

void ASlashCharacter::HitReactEnd()
{
ActionState = EActionState::EAS_Unoccupied;
}

bool ASlashCharacter::IsUnoccupied()
{
return ActionState == EActionState::EAS_Unoccupied;
}

void ASlashCharacter::InitializeSlashOverlay()
{
APlayerController* PlayerController = Cast(GetController());
if (PlayerController)
{
ASlashHUD* SlashHUD = Cast(PlayerController->GetHUD());
if (SlashHUD)
{
SlashOverlay = SlashHUD->GetSlashOverlay();
if (SlashOverlay && Attributes)
{
SlashOverlay->SetHealthBarPercent(Attributes->GetHealthPercentage());
SlashOverlay->SetStaminaBarPercent(1.f);
}
}
}
}

void ASlashCharacter::SetHUDHealth()
{
if (SlashOverlay && Attributes)
{
SlashOverlay->SetHealthBarPercent(Attributes->GetHealthPercentage());
}
}

I Can not see you notify the enemies that you have respawned, Nor have you Reset the collisions. So you should be doing some other things also.

So you will want to :
1: Check the collision settings are re-enabled to allow overlap events to trigger enemy attacks.
2: Notify enemies that you have respawned.

So i would go about doing something like this:

In your ASlashCharacter::ASlashCharacter

void ASlashCharacter::Respawn()
{
    SetActorLocation(RespawnLocation);
    Attributes->SetHealth(Attributes->GetMaxHealth());
    SlashOverlay->SetHealthBarPercent(1.0f);
    ActionState = EActionState::EAS_Unoccupied;

    // Re-enable collisions for overlap events
    GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
    GetMesh()->SetGenerateOverlapEvents(true);

    NotifyEnemiesOfRespawn();  // Notify enemies of respawn
}
// Function to notify enemies of respawn
void ASlashCharacter::NotifyEnemiesOfRespawn()
{
    TArray<AActor*> OverlappingActors;
    GetOverlappingActors(OverlappingActors, AEnemy::StaticClass());

    for (AActor* Actor : OverlappingActors)
    {
        AEnemy* Enemy = Cast<AEnemy>(Actor);
        if (Enemy)
        {
            Enemy->OnCharacterRespawn(this);  // Implement this function in AEnemy class
        }
    }
}

Then in your enemy do something like this:

void AEnemy::OnCharacterRespawn(ASlashCharacter* Character)
{
    if (Character)
    {
        // Logic to re-engage the character
        EngageTarget(Character);
    }
}

Hope this helps and points you in the right direction.

Thank you so much!!! that really helps! my code is so long that i’ve always feared putting all of it in here. I know now for future reference! thanks!!

void AEnemy::OnCharacterRespawn(ASlashCharacter* Character) keeps giving me a syntax error.

// Fill out your copyright notice in the Description page of Project Settings.

include “Enemy/Enemy.h”
include “Components/SkeletalMeshComponent.h”
include “GameFramework/CharacterMovementComponent.h”
include “Perception/PawnSensingComponent.h”
include “Component/AttributeComponent.h”
include “HUD/HealthBarComponent.h”
include “Components/CapsuleComponent.h”
include “Navigation/PathFollowingComponent.h”
include “Item/Weapon/Weapon.h”
include “AIController.h”
include “Character/SlashCharacter.h”

AEnemy::AEnemy()
{
PrimaryActorTick.bCanEverTick = true;

GetMesh()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
GetMesh()->SetGenerateOverlapEvents(true);

HealthBarWidget = CreateDefaultSubobject<UHealthBarComponent>(TEXT("HealthBar"));
HealthBarWidget->SetupAttachment(GetRootComponent());

GetCharacterMovement()->bOrientRotationToMovement = true;
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;

PawnSensing = CreateDefaultSubobject<UPawnSensingComponent>(TEXT("PawnSensing"));
PawnSensing->SightRadius = 4000.f;
PawnSensing->SetPeripheralVisionAngle(80.f);

}

void AEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

if (IsDead()) return;
if (EnemyState > EEnemyState::EES_Patrolling)
{
	CheckCombatTarget();
}
else
{
	CheckPatrolTarget();
}

}

float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
HandleDamage(DamageAmount);
CombatTarget = EventInstigator->GetPawn();

if (IsInsideAttackRadius())
{
	EnemyState = EEnemyState::EES_Attacking;
}
else if (IsOutsideAttackRadius())
{
	ChaseTarget();
}

return DamageAmount;

}

void AEnemy::Destroyed()
{
if (EquippedWeapon)
{
EquippedWeapon->Destroy();
}
}

void AEnemy::GetHit_Implementation(const FVector& ImpactPoint, AActor* Hitter)
{
Super::GetHit_Implementation(ImpactPoint, Hitter);
if (!IsDead()) ShowHealthBar();
ClearPatrolTimer();
ClearAttackTimer();
SetWeaponCollisionEnabled(ECollisionEnabled::NoCollision);

StopAttackMontage();

}

void AEnemy::OnCharacterRespawn(ASlashCharacter* Character)
{
if (Character)
{

	// Logic to re-engage the character

}

}

void AEnemy::BeginPlay()
{
Super::BeginPlay();

if (PawnSensing) PawnSensing->OnSeePawn.AddDynamic(this, &AEnemy::PawnSeen);
InitializeEnemy();
Tags.Add(FName("Enemy"));

}

void AEnemy::Die()
{
Super::Die();

EnemyState = EEnemyState::EES_Dead;
ClearAttackTimer();
HideHealthBar();
DisableCapsule();
SetLifeSpan(DeathLifeSpan);
GetCharacterMovement()->bOrientRotationToMovement = false;
SetWeaponCollisionEnabled(ECollisionEnabled::NoCollision);

}

void AEnemy::Attack()
{
Super::Attack();
if (CombatTarget == nullptr) return;

EnemyState = EEnemyState::EES_Engaged;
PlayAttackMontage();

}

bool AEnemy::CanAttack()
{
bool bCanAttack =
IsInsideAttackRadius() &&
!IsAttacking() &&
!IsEngaged() &&
!IsDead();
return bCanAttack;
}

void AEnemy::AttackEnd()
{
EnemyState = EEnemyState::EES_NoState;
CheckCombatTarget();
}

void AEnemy::HandleDamage(float DamageAmount)
{
Super::HandleDamage(DamageAmount);

if (Attributes && HealthBarWidget)
{
	HealthBarWidget->SetHealthPercent(Attributes->GetHealthPercentage());
}

}

AActor* AEnemy::ChoosePatrolTarget()
{
TArray<AActor*> ValidTargets;
for (AActor* Target : PatrolTargets)
{
if (Target != PatrolTarget)
{
ValidTargets.AddUnique(Target);
}
}

const int32 NumPatrolTargets = ValidTargets.Num();
if (NumPatrolTargets > 0)
{
	const int32 TargetSelection = FMath::RandRange(0, NumPatrolTargets - 1);
	return ValidTargets[TargetSelection];
}
return nullptr;

}

void AEnemy::CheckCombatTarget()
{
if (IsOutsideCombatRadius())
{
ClearAttackTimer();
LoseInterest();
if (!IsEngaged()) StartPatrolling();
}
else if (IsOutsideAttackRadius() && !IsChasing())
{
ClearAttackTimer();
if (!IsEngaged()) ChaseTarget();
}
else if (CanAttack())
{
StartAttackTimer();
}
}

void AEnemy::PatrolTimerFinished()
{
MoveToTarget(PatrolTarget);
}

void AEnemy::HideHealthBar()
{
if (HealthBarWidget)
{
HealthBarWidget->SetVisibility(false);
}
}

void AEnemy::ShowHealthBar()
{
if (HealthBarWidget)
{
HealthBarWidget->SetVisibility(true);
}
}

void AEnemy::LoseInterest()
{
CombatTarget = nullptr;
HideHealthBar();
}

void AEnemy::StartPatrolling()
{
EnemyState = EEnemyState::EES_Patrolling;
GetCharacterMovement()->MaxWalkSpeed = PatrollingSpeed;
MoveToTarget(PatrolTarget);
}

void AEnemy::ChaseTarget()
{
EnemyState = EEnemyState::EES_Chasing;
GetCharacterMovement()->MaxWalkSpeed = ChasingSpeed;
MoveToTarget(CombatTarget);
}

bool AEnemy::IsOutsideCombatRadius()
{
return !InTargetRange(CombatTarget, CombatRadius);
}

bool AEnemy::IsOutsideAttackRadius()
{
return !InTargetRange(CombatTarget,AttackRadius);
}

bool AEnemy::IsInsideAttackRadius()
{
return InTargetRange(CombatTarget, AttackRadius);
}

bool AEnemy::IsChasing()
{
return EnemyState == EEnemyState::EES_Chasing;
}

bool AEnemy::IsAttacking()
{
return EnemyState == EEnemyState::EES_Attacking;
}

bool AEnemy::IsDead()
{
return EnemyState == EEnemyState::EES_Dead;
}

bool AEnemy::IsEngaged()
{
return EnemyState == EEnemyState::EES_Engaged;
}

void AEnemy::ClearPatrolTimer()
{
GetWorldTimerManager().ClearTimer(PatrolTimer);
}

void AEnemy::PawnSeen(APawn* SeenPawn)
{
const bool bShouldChaseTarget =
EnemyState != EEnemyState::EES_Dead &&
EnemyState != EEnemyState::EES_Chasing &&
EnemyState < EEnemyState::EES_Attacking &&
SeenPawn->ActorHasTag(FName(“EngageableTarget”));

if (bShouldChaseTarget)
{
	CombatTarget = SeenPawn;
	ClearPatrolTimer();
	ChaseTarget();
}

}

void AEnemy::StartAttackTimer()
{
EnemyState = EEnemyState::EES_Attacking;
const float AttackTime = FMath::RandRange(AttackMin, AttackMax);
GetWorldTimerManager().SetTimer(AttackTimer, this, &AEnemy::Attack, AttackTime);
}

void AEnemy::ClearAttackTimer()
{
GetWorldTimerManager().ClearTimer(AttackTimer);
}

void AEnemy::SpawnDefaultWeapon()
{
UWorld* World = GetWorld();
if (World && WeaponClass)
{
AWeapon* DefaultWeapon = World->SpawnActor(WeaponClass);
DefaultWeapon->Equip(GetMesh(), FName(“WeaponSocket”), this, this);
DefaultWeapon->IgnoreActors.Emplace(this);
EquippedWeapon = DefaultWeapon;
}
}

bool AEnemy::InTargetRange(AActor* Target, double Radius)
{
if (Target == nullptr) return false;
const double DistanceToTarget = (Target->GetActorLocation() - GetActorLocation()).Size();
return DistanceToTarget <= Radius;
}

void AEnemy::MoveToTarget(AActor* Target)
{
if (EnemyController == nullptr || Target == nullptr) return;
FAIMoveRequest MoveRequest;
MoveRequest.SetGoalActor(Target);
MoveRequest.SetAcceptanceRadius(AcceptanceRadius);
EnemyController->MoveTo(MoveRequest);
}

void AEnemy::InitializeEnemy()
{
EnemyController = Cast(GetController());
MoveToTarget(PatrolTarget);
HideHealthBar();
SpawnDefaultWeapon();
}

void AEnemy::CheckPatrolTarget()
{
if (InTargetRange(PatrolTarget, PatrolRadius))
{
PatrolTarget = ChoosePatrolTarget();
const float WaitTime = FMath::RandRange(PatrolWaitMin, PatrolWaitMax);
GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished, WaitTime);
}
}

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.