Step 1: the Salty project, two modules, tests and the gym
Salty.uproject (UE 5.8) from the Third Person template with class redirects, the SaltyCore and Salty modules, the three build targets, USaltyAssetManager calling InitGlobalData, Config/Tags with the 23 root namespaces, Scripts/run-tests.sh, build.sh and Authoring/create_gym.py, L_Gym, Git LFS attributes and the placeholder test. Template variants kept as reference (D-41). The four Fab packs stay out of the repository for now (~10 GB). The editor serves the engine MCP plugin on 127.0.0.1:8000 through DefaultEditorPerProjectUserSettings.ini. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
0e61a77346
commit
4f2c55cd2a
@@ -0,0 +1,126 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "CombatEnemySpawner.h"
|
||||
#include "Engine/World.h"
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "Components/ArrowComponent.h"
|
||||
#include "TimerManager.h"
|
||||
#include "CombatEnemy.h"
|
||||
|
||||
ACombatEnemySpawner::ACombatEnemySpawner()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
|
||||
// create the root
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
|
||||
|
||||
// create the reference spawn capsule
|
||||
SpawnCapsule = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Spawn Capsule"));
|
||||
SpawnCapsule->SetupAttachment(RootComponent);
|
||||
|
||||
SpawnCapsule->SetRelativeLocation(FVector(0.0f, 0.0f, 90.0f));
|
||||
SpawnCapsule->SetCapsuleSize(35.0f, 90.0f);
|
||||
SpawnCapsule->SetCollisionProfileName(FName("NoCollision"));
|
||||
|
||||
SpawnDirection = CreateDefaultSubobject<UArrowComponent>(TEXT("Spawn Direction"));
|
||||
SpawnDirection->SetupAttachment(RootComponent);
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// should we spawn an enemy right away?
|
||||
if (bShouldSpawnEnemiesImmediately)
|
||||
{
|
||||
// schedule the first enemy spawn
|
||||
GetWorld()->GetTimerManager().SetTimer(SpawnTimer, this, &ACombatEnemySpawner::SpawnEnemy, InitialSpawnDelay);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::EndPlay(EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
Super::EndPlay(EndPlayReason);
|
||||
|
||||
// clear the spawn timer
|
||||
GetWorld()->GetTimerManager().ClearTimer(SpawnTimer);
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::SpawnEnemy()
|
||||
{
|
||||
// ensure the enemy class is valid
|
||||
if (IsValid(EnemyClass))
|
||||
{
|
||||
// spawn the enemy at the reference capsule's transform
|
||||
FActorSpawnParameters SpawnParams;
|
||||
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
|
||||
ACombatEnemy* SpawnedEnemy = GetWorld()->SpawnActor<ACombatEnemy>(EnemyClass, SpawnCapsule->GetComponentTransform(), SpawnParams);
|
||||
|
||||
// was the enemy successfully created?
|
||||
if (SpawnedEnemy)
|
||||
{
|
||||
// subscribe to the death delegate
|
||||
SpawnedEnemy->OnEnemyDied.AddDynamic(this, &ACombatEnemySpawner::OnEnemyDied);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::OnEnemyDied()
|
||||
{
|
||||
// decrease the spawn counter
|
||||
--SpawnCount;
|
||||
|
||||
// is this the last enemy we should spawn?
|
||||
if (SpawnCount <= 0)
|
||||
{
|
||||
// schedule the activation on depleted message
|
||||
GetWorld()->GetTimerManager().SetTimer(SpawnTimer, this, &ACombatEnemySpawner::SpawnerDepleted, ActivationDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
// schedule the next enemy spawn
|
||||
GetWorld()->GetTimerManager().SetTimer(SpawnTimer, this, &ACombatEnemySpawner::SpawnEnemy, RespawnDelay);
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::SpawnerDepleted()
|
||||
{
|
||||
// process the actors to activate list
|
||||
for (AActor* CurrentActor : ActorsToActivateWhenDepleted)
|
||||
{
|
||||
// check if the actor is activatable
|
||||
if (ICombatActivatable* CombatActivatable = Cast<ICombatActivatable>(CurrentActor))
|
||||
{
|
||||
// activate the actor
|
||||
CombatActivatable->ActivateInteraction(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::ToggleInteraction(AActor* ActivationInstigator)
|
||||
{
|
||||
// stub
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::ActivateInteraction(AActor* ActivationInstigator)
|
||||
{
|
||||
// ensure we're only activated once, and only if we've deferred enemy spawning
|
||||
if (bHasBeenActivated || bShouldSpawnEnemiesImmediately)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// raise the activation flag
|
||||
bHasBeenActivated = true;
|
||||
|
||||
// spawn the first enemy
|
||||
SpawnEnemy();
|
||||
}
|
||||
|
||||
void ACombatEnemySpawner::DeactivateInteraction(AActor* ActivationInstigator)
|
||||
{
|
||||
// stub
|
||||
}
|
||||
Reference in New Issue
Block a user