
A burnt-out employee trapped in a fake Motivational Simulation Program™ — a 2D character moving through a 3D world. Every run you fail, HR reboots you into a new department. Built solo in 6 days for the Epic MegaJam One Man Army modifier.
BTTask_FindRandomLocation, AIPerception, launch-force hit response.
One macro generates the full getter/setter/initter interface per attribute. The transient Damage meta-attribute is never replicated — it's consumed by the damage execution calc and converted to negative Health.
// One macro line = 4 accessors generated automatically
#define ATTRIBUTE_ACCESSORS(ClassName, Prop) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, Prop) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(Prop) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(Prop) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(Prop)
UCLASS()
class UHopperAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Health)
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UHopperAttributeSet, Health)
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_MaxHealth)
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(UHopperAttributeSet, MaxHealth)
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Stamina)
FGameplayAttributeData Stamina;
ATTRIBUTE_ACCESSORS(UHopperAttributeSet, Stamina)
// Transient — consumed by DamageExecution, never replicated
UPROPERTY(BlueprintReadOnly)
FGameplayAttributeData Damage;
ATTRIBUTE_ACCESSORS(UHopperAttributeSet, Damage)
virtual void PostGameplayEffectExecute(
const FGameplayEffectModCallbackData& Data) override;
};
3-layer noise blend (large 0.8× + detail 4×), radial falloff clamps island edges, voxel-snap rounds heights to 50-unit steps. Water vs grass determined by sign of final height.
const float MaxDist = FMath::Min(GridHalfW, GridHalfH) * 0.95f;
for (int32 y = 0; y < GridHeight; ++y)
for (int32 x = 0; x < GridWidth; ++x)
{
const float XPos = (y%2) ? x*HOffset+OddOff : x*HOffset;
const float YPos = y * VOffset;
const float Dist = FVector2D::Distance({XPos,YPos}, Center);
if (Dist > MaxDist * 1.05f) continue; // island mask
// 3-layer blend: shape(0.8x) 70% + detail(4x) 30%
const float Large = Noise->GetNoise2D(XPos*.8f+S, YPos*.8f+S);
const float Detail = Noise->GetNoise2D(XPos*4.f+DS, YPos*4.f+DS);
const float Blend = Large*.7f + Detail*.3f;
const float Fall = FMath::Clamp(1.f-(Dist/MaxDist),0.f,1.f);
float H = (Blend*.8f + Fall*.3f) * HeightStrength;
H = FMath::RoundToFloat(H/50.f)*50.f; // voxel step
// grass above sea, water below — one HISM per biome
((H >= 0.f) ? GrassMesh : WaterMesh)->AddInstance(
FTransform(FVector(XPos, YPos, H)));
}
Props cluster around a central tile; a line trace snaps each to terrain geometry. 25% chance applies the glitch material and tilts the prop — intentionally broken, corporate-simulation aesthetic.
for (int32 j = 0; j < ClusterSize; ++j)
{
FVector Loc = ClusterCenter
+ FMath::VRand() * FMath::RandRange(80.f,150.f)
+ FVector(0,0, HeightOff);
const bool bGlitch = FMath::FRand() < 0.25f;
if (bGlitch) { Loc.Z -= 50.f; Rot.Pitch += Rand(-30,30); }
// Snap to terrain via line trace
FHitResult Hit;
if (World->LineTraceSingleByChannel(Hit,
Loc+FVector(0,0,500), Loc-FVector(0,0,1000),
ECC_WorldStatic))
{
FRotator SurfRot = Hit.ImpactNormal.Rotation();
FRotator YawRot(0, FMath::FRandRange(0.f,360.f), 0);
Rot = (SurfRot.Quaternion() * YawRot.Quaternion()).Rotator();
Rot.Pitch *= .5f; Rot.Roll *= .5f; // keep props upright-ish
Loc = Hit.ImpactPoint;
}
if (AActor* A = World->SpawnActor<AActor>(Data.Class, Loc, Rot))
{
SpawnedActors.Add(A);
if (bGlitch && GlitchMat)
for (UStaticMeshComponent* M :
TComponentRange<UStaticMeshComponent>(A))
M->SetMaterial(0, GlitchMat);
}
}