Add readable MVP survival object proxies

This commit is contained in:
2026-05-19 10:42:06 -07:00
parent bc7617b08b
commit 63f48bcadf
15 changed files with 623 additions and 1 deletions
+1 -1
View File
@@ -821,7 +821,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
- [x] Make startup credits, character selection, server/join, loading, pause, save, and quit feel like separate intentional segments, with no impression that gameplay has started underneath the UI. Switched startup/menu control to UI-only input, added explicit segment labels for character selection, server join, loading, pause, and saving, and made Save & Quit transition through a dedicated saving screen before issuing save/quit. - [x] Make startup credits, character selection, server/join, loading, pause, save, and quit feel like separate intentional segments, with no impression that gameplay has started underneath the UI. Switched startup/menu control to UI-only input, added explicit segment labels for character selection, server join, loading, pause, and saving, and made Save & Quit transition through a dedicated saving screen before issuing save/quit.
- [x] Add a visually verified packaged-client startup test using Sunshine/Moonlight or another real GPU desktop capture path, because QEMU guest-agent screenshots cannot validate the interactive rendered desktop. Added a packaged-client GPU startup visual test runbook, a Windows helper that checks the packaged demo and Sunshine service before capture, and verifier coverage requiring Moonlight/Sunshine evidence instead of QEMU guest-agent screenshots. - [x] Add a visually verified packaged-client startup test using Sunshine/Moonlight or another real GPU desktop capture path, because QEMU guest-agent screenshots cannot validate the interactive rendered desktop. Added a packaged-client GPU startup visual test runbook, a Windows helper that checks the packaged demo and Sunshine service before capture, and verifier coverage requiring Moonlight/Sunshine evidence instead of QEMU guest-agent screenshots.
- [x] Add first realistic playable character proxies for the selected young adult male and female archetypes, replacing the default mannequin/dummy presentation for investor builds. Added selected male/female MVP proxy application to the player controller, workwear material generation, cook coverage for Agrarian character assets, documentation, and verification so the menu-selected archetype changes the possessed pawn instead of leaving one default dummy presentation. - [x] Add first realistic playable character proxies for the selected young adult male and female archetypes, replacing the default mannequin/dummy presentation for investor builds. Added selected male/female MVP proxy application to the player controller, workwear material generation, cook coverage for Agrarian character assets, documentation, and verification so the menu-selected archetype changes the possessed pawn instead of leaving one default dummy presentation.
- [ ] Replace box/sphere/cylinder survival objects with readable MVP meshes for campfires, primitive shelter pieces, resource pickups, water sources, wildlife, and gathered items. - [x] Replace box/sphere/cylinder survival objects with readable MVP meshes for campfires, primitive shelter pieces, resource pickups, water sources, wildlife, and gathered items. Added composed native proxy visuals for campfires, primitive shelters, pickups, resource nodes, water sources, and wildlife using cooked Agrarian placeholder mesh assets plus Ground Zero materials, with child visuals set to no collision so gameplay behavior remains unchanged while investor builds read as intentional objects instead of primitive debug shapes.
- [ ] Replace the placeholder Ground Zero environment presentation with investor-facing biome dressing: believable terrain material, grass, brush, shrubs, bushes, trees, rocks, water visuals, and local coastal-scrub color variation. - [ ] Replace the placeholder Ground Zero environment presentation with investor-facing biome dressing: believable terrain material, grass, brush, shrubs, bushes, trees, rocks, water visuals, and local coastal-scrub color variation.
- [ ] Add a real water-source visual pass with surface material, edge treatment, scale, and placement that reads as collectable freshwater instead of a placeholder plane. - [ ] Add a real water-source visual pass with surface material, edge treatment, scale, and placement that reads as collectable freshwater instead of a placeholder plane.
- [ ] Add density and sightline tuning so grasses, shrubs, trees, and resource clusters are visible enough to sell the world without hiding gameplay-critical objects. - [ ] Add density and sightline tuning so grasses, shrubs, trees, and resource clusters are visible enough to sell the world without hiding gameplay-critical objects.
@@ -0,0 +1,31 @@
# MVP Readable Survival Object Proxies
The 0.1.O investor visual pass replaces primitive single-shape survival object
presentation with composed, readable MVP proxy silhouettes. These are not final
art assets, but they are intentional enough for investor builds to communicate
what the player is looking at before final production meshes arrive.
Covered native actors:
- `AAgrarianCampfire`: stone/ash base, stacked log proxies, ember proxy, existing
smoke and light behavior.
- `AAgrarianShelterActor`: floor, rear wall, sloped roof panels, and frame posts.
- `AAgrarianItemPickup`: bundled pickup body, strap, and marker so loose gathered
items no longer read as a single debug cube.
- `AAgrarianResourceNode`: harvestable cluster and marker layered onto the
existing interactable node.
- `AAgrarianWaterSource`: stone bank, water surface, and collect marker.
- `AAgrarianWildlifeBase`: small animal body, head, ears, and tail proxy suitable
for the MVP rabbit/wildlife prototype.
Implementation notes:
- The existing root meshes remain responsible for actor transform, interaction,
collision, save/load, replication, and blueprint compatibility.
- Added child mesh proxies use no collision and no overlap generation so they do
not change gameplay behavior.
- The pass uses already-cooked Agrarian placeholder mesh assets and Ground Zero
material assets so packaged investor builds do not depend on uncooked editor
content.
- Final realistic art should replace these proxies without changing survival,
inventory, shelter, water, or wildlife gameplay contracts.
@@ -0,0 +1,120 @@
#!/usr/bin/env python3
"""Verify 0.1.O readable survival-object proxy coverage."""
from __future__ import annotations
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REQUIRED_SNIPPETS = {
"Source/AgrarianGame/AgrarianCampfire.h": [
"StoneRingProxy",
"LogProxyA",
"LogProxyB",
"LogProxyC",
"EmberProxy",
],
"Source/AgrarianGame/AgrarianCampfire.cpp": [
"SM_AGR_Placeholder_Cylinder",
"M_AGR_GZ_Wood_Resource",
"M_AGR_GZ_Stone_Sandstone",
"ConfigureCampfireProxyComponent",
"LogProxyA->SetRelativeRotation",
],
"Source/AgrarianGame/AgrarianShelterActor.h": [
"FloorProxy",
"BackWallProxy",
"LeftRoofProxy",
"RightRoofProxy",
"FrameProxyA",
"FrameProxyB",
],
"Source/AgrarianGame/AgrarianShelterActor.cpp": [
"SM_AGR_Placeholder_ChamferCube",
"M_AGR_GZ_Fiber_Resource",
"LeftRoofProxy->SetRelativeRotation",
"ConfigureShelterProxyComponent",
],
"Source/AgrarianGame/AgrarianWaterSource.h": [
"WaterSurfaceProxy",
"StoneBankProxy",
"CollectMarkerProxy",
],
"Source/AgrarianGame/AgrarianWaterSource.cpp": [
"SM_AGR_Placeholder_Plane",
"M_AGR_GZ_FreshWater",
"WaterSurfaceProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision)",
"StoneBankProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision)",
],
"Source/AgrarianGame/AgrarianItemPickup.h": [
"BundleProxy",
"StrapProxy",
"ItemMarkerProxy",
],
"Source/AgrarianGame/AgrarianItemPickup.cpp": [
"BundleProxy->SetRelativeRotation",
"StrapProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision)",
"ItemMarkerProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision)",
],
"Source/AgrarianGame/AgrarianResourceNode.h": [
"ResourceClusterProxy",
"HarvestableMarkerProxy",
],
"Source/AgrarianGame/AgrarianResourceNode.cpp": [
"ResourceClusterProxy->SetRelativeRotation",
"HarvestableMarkerProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision)",
"Mesh->SetVisibility(RemainingHarvests > 0, true)",
],
"Source/AgrarianGame/AgrarianWildlifeBase.h": [
"WildlifeBodyProxy",
"WildlifeHeadProxy",
"WildlifeEarProxyA",
"WildlifeEarProxyB",
"WildlifeTailProxy",
],
"Source/AgrarianGame/AgrarianWildlifeBase.cpp": [
"WildlifeBodyProxy->SetupAttachment(RootComponent)",
"WildlifeHeadProxy->SetupAttachment(WildlifeBodyProxy)",
"WildlifeTailProxy->SetRelativeRotation",
"ConfigureWildlifeProxyComponent",
],
"Docs/CharactersAndObjects/MvpReadableSurvivalObjectProxies.md": [
"MVP Readable Survival Object Proxies",
"no collision",
"Final realistic art should replace these proxies",
],
"AGRARIAN_DEVELOPMENT_ROADMAP.md": [
"- [x] Replace box/sphere/cylinder survival objects with readable MVP meshes",
"Added composed native proxy visuals for campfires, primitive shelters, pickups, resource nodes, water sources, and wildlife",
],
}
def main() -> int:
missing: list[str] = []
for relative_path, snippets in REQUIRED_SNIPPETS.items():
path = ROOT / relative_path
if not path.exists():
missing.append(f"{relative_path}: file missing")
continue
text = path.read_text(encoding="utf-8")
for snippet in snippets:
if snippet not in text:
missing.append(f"{relative_path}: missing {snippet!r}")
if missing:
print("Readable survival-object proxy verification failed:")
for item in missing:
print(f"- {item}")
return 1
print("Readable survival-object proxy verification passed.")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+75
View File
@@ -9,8 +9,33 @@
#include "Particles/ParticleSystemComponent.h" #include "Particles/ParticleSystemComponent.h"
#include "Components/PointLightComponent.h" #include "Components/PointLightComponent.h"
#include "Components/StaticMeshComponent.h" #include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Materials/MaterialInterface.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
#include "UObject/ConstructorHelpers.h"
namespace
{
void ConfigureCampfireProxyComponent(UStaticMeshComponent* Component, UStaticMesh* MeshAsset, UMaterialInterface* MaterialAsset)
{
if (!Component)
{
return;
}
Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Component->SetGenerateOverlapEvents(false);
if (MeshAsset)
{
Component->SetStaticMesh(MeshAsset);
}
if (MaterialAsset)
{
Component->SetMaterial(0, MaterialAsset);
}
}
}
AAgrarianCampfire::AAgrarianCampfire() AAgrarianCampfire::AAgrarianCampfire()
{ {
@@ -20,6 +45,56 @@ AAgrarianCampfire::AAgrarianCampfire()
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh")); Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
RootComponent = Mesh; RootComponent = Mesh;
Mesh->SetCollisionProfileName(TEXT("BlockAll"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> ChamferCubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_ChamferCube.SM_AGR_Placeholder_ChamferCube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cube.SM_AGR_Placeholder_Cube"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> StoneMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Stone_Sandstone.M_AGR_GZ_Stone_Sandstone"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WoodMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Wood_Resource.M_AGR_GZ_Wood_Resource"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> FiberMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Fiber_Resource.M_AGR_GZ_Fiber_Resource"));
if (CylinderMesh.Succeeded())
{
Mesh->SetStaticMesh(CylinderMesh.Object);
Mesh->SetRelativeScale3D(FVector(0.72f, 0.72f, 0.08f));
}
if (StoneMaterial.Succeeded())
{
Mesh->SetMaterial(0, StoneMaterial.Object);
}
StoneRingProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StoneRingProxy"));
StoneRingProxy->SetupAttachment(RootComponent);
ConfigureCampfireProxyComponent(StoneRingProxy, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, StoneMaterial.Succeeded() ? StoneMaterial.Object : nullptr);
StoneRingProxy->SetRelativeScale3D(FVector(1.05f, 1.05f, 0.12f));
LogProxyA = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LogProxyA"));
LogProxyA->SetupAttachment(RootComponent);
ConfigureCampfireProxyComponent(LogProxyA, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
LogProxyA->SetRelativeLocation(FVector(0.0f, -12.0f, 18.0f));
LogProxyA->SetRelativeRotation(FRotator(0.0f, 90.0f, 90.0f));
LogProxyA->SetRelativeScale3D(FVector(0.16f, 0.16f, 0.72f));
LogProxyB = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LogProxyB"));
LogProxyB->SetupAttachment(RootComponent);
ConfigureCampfireProxyComponent(LogProxyB, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
LogProxyB->SetRelativeLocation(FVector(-12.0f, 10.0f, 20.0f));
LogProxyB->SetRelativeRotation(FRotator(0.0f, 28.0f, 90.0f));
LogProxyB->SetRelativeScale3D(FVector(0.16f, 0.16f, 0.68f));
LogProxyC = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LogProxyC"));
LogProxyC->SetupAttachment(RootComponent);
ConfigureCampfireProxyComponent(LogProxyC, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
LogProxyC->SetRelativeLocation(FVector(12.0f, 10.0f, 22.0f));
LogProxyC->SetRelativeRotation(FRotator(0.0f, -28.0f, 90.0f));
LogProxyC->SetRelativeScale3D(FVector(0.16f, 0.16f, 0.68f));
EmberProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("EmberProxy"));
EmberProxy->SetupAttachment(RootComponent);
ConfigureCampfireProxyComponent(EmberProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : (CubeMesh.Succeeded() ? CubeMesh.Object : nullptr), FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
EmberProxy->SetRelativeLocation(FVector(0.0f, 0.0f, 13.0f));
EmberProxy->SetRelativeScale3D(FVector(0.38f, 0.38f, 0.09f));
FireLight = CreateDefaultSubobject<UPointLightComponent>(TEXT("FireLight")); FireLight = CreateDefaultSubobject<UPointLightComponent>(TEXT("FireLight"));
FireLight->SetupAttachment(RootComponent); FireLight->SetupAttachment(RootComponent);
+15
View File
@@ -28,6 +28,21 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire")
TObjectPtr<UStaticMeshComponent> Mesh; TObjectPtr<UStaticMeshComponent> Mesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
TObjectPtr<UStaticMeshComponent> StoneRingProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
TObjectPtr<UStaticMeshComponent> LogProxyA;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
TObjectPtr<UStaticMeshComponent> LogProxyB;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
TObjectPtr<UStaticMeshComponent> LogProxyC;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire|Visuals")
TObjectPtr<UStaticMeshComponent> EmberProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Fire")
TObjectPtr<UPointLightComponent> FireLight; TObjectPtr<UPointLightComponent> FireLight;
@@ -5,6 +5,9 @@
#include "AgrarianInventoryComponent.h" #include "AgrarianInventoryComponent.h"
#include "AgrarianItemDefinitionAsset.h" #include "AgrarianItemDefinitionAsset.h"
#include "Components/StaticMeshComponent.h" #include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"
#include "Materials/MaterialInterface.h"
#include "UObject/ConstructorHelpers.h"
AAgrarianItemPickup::AAgrarianItemPickup() AAgrarianItemPickup::AAgrarianItemPickup()
{ {
@@ -15,6 +18,68 @@ AAgrarianItemPickup::AAgrarianItemPickup()
RootComponent = Mesh; RootComponent = Mesh;
Mesh->SetCollisionProfileName(TEXT("BlockAll")); Mesh->SetCollisionProfileName(TEXT("BlockAll"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> ChamferCubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_ChamferCube.SM_AGR_Placeholder_ChamferCube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cube.SM_AGR_Placeholder_Cube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WoodMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Wood_Resource.M_AGR_GZ_Wood_Resource"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> FiberMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Fiber_Resource.M_AGR_GZ_Fiber_Resource"));
if (ChamferCubeMesh.Succeeded())
{
Mesh->SetStaticMesh(ChamferCubeMesh.Object);
Mesh->SetRelativeScale3D(FVector(0.42f, 0.32f, 0.2f));
}
if (WoodMaterial.Succeeded())
{
Mesh->SetMaterial(0, WoodMaterial.Object);
}
BundleProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BundleProxy"));
BundleProxy->SetupAttachment(RootComponent);
BundleProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
BundleProxy->SetGenerateOverlapEvents(false);
if (CylinderMesh.Succeeded())
{
BundleProxy->SetStaticMesh(CylinderMesh.Object);
}
if (WoodMaterial.Succeeded())
{
BundleProxy->SetMaterial(0, WoodMaterial.Object);
}
BundleProxy->SetRelativeLocation(FVector(0.0f, 0.0f, 16.0f));
BundleProxy->SetRelativeRotation(FRotator(0.0f, 90.0f, 90.0f));
BundleProxy->SetRelativeScale3D(FVector(0.12f, 0.12f, 0.58f));
StrapProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StrapProxy"));
StrapProxy->SetupAttachment(RootComponent);
StrapProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
StrapProxy->SetGenerateOverlapEvents(false);
if (CubeMesh.Succeeded())
{
StrapProxy->SetStaticMesh(CubeMesh.Object);
}
if (FiberMaterial.Succeeded())
{
StrapProxy->SetMaterial(0, FiberMaterial.Object);
}
StrapProxy->SetRelativeLocation(FVector(0.0f, 0.0f, 18.0f));
StrapProxy->SetRelativeScale3D(FVector(0.08f, 0.54f, 0.08f));
ItemMarkerProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ItemMarkerProxy"));
ItemMarkerProxy->SetupAttachment(RootComponent);
ItemMarkerProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
ItemMarkerProxy->SetGenerateOverlapEvents(false);
if (CubeMesh.Succeeded())
{
ItemMarkerProxy->SetStaticMesh(CubeMesh.Object);
}
if (FiberMaterial.Succeeded())
{
ItemMarkerProxy->SetMaterial(0, FiberMaterial.Object);
}
ItemMarkerProxy->SetRelativeLocation(FVector(0.0f, -18.0f, 26.0f));
ItemMarkerProxy->SetRelativeScale3D(FVector(0.16f, 0.04f, 0.16f));
PickupStack.ItemId = TEXT("wood"); PickupStack.ItemId = TEXT("wood");
PickupStack.DisplayName = FText::FromString(TEXT("Wood")); PickupStack.DisplayName = FText::FromString(TEXT("Wood"));
PickupStack.Quantity = 1; PickupStack.Quantity = 1;
+9
View File
@@ -23,6 +23,15 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Pickup") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Pickup")
TObjectPtr<UStaticMeshComponent> Mesh; TObjectPtr<UStaticMeshComponent> Mesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Pickup|Visuals")
TObjectPtr<UStaticMeshComponent> BundleProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Pickup|Visuals")
TObjectPtr<UStaticMeshComponent> StrapProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Pickup|Visuals")
TObjectPtr<UStaticMeshComponent> ItemMarkerProxy;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Pickup") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Pickup")
FAgrarianItemStack PickupStack; FAgrarianItemStack PickupStack;
@@ -6,8 +6,11 @@
#include "AgrarianItemDefinitionAsset.h" #include "AgrarianItemDefinitionAsset.h"
#include "AgrarianSaveGame.h" #include "AgrarianSaveGame.h"
#include "Components/StaticMeshComponent.h" #include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"
#include "Materials/MaterialInterface.h"
#include "TimerManager.h" #include "TimerManager.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
#include "UObject/ConstructorHelpers.h"
AAgrarianResourceNode::AAgrarianResourceNode() AAgrarianResourceNode::AAgrarianResourceNode()
{ {
@@ -18,6 +21,52 @@ AAgrarianResourceNode::AAgrarianResourceNode()
RootComponent = Mesh; RootComponent = Mesh;
Mesh->SetCollisionProfileName(TEXT("BlockAll")); Mesh->SetCollisionProfileName(TEXT("BlockAll"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> ChamferCubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_ChamferCube.SM_AGR_Placeholder_ChamferCube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WoodMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Wood_Resource.M_AGR_GZ_Wood_Resource"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> FiberMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Fiber_Resource.M_AGR_GZ_Fiber_Resource"));
if (ChamferCubeMesh.Succeeded())
{
Mesh->SetStaticMesh(ChamferCubeMesh.Object);
Mesh->SetRelativeScale3D(FVector(0.8f, 0.58f, 0.44f));
}
if (WoodMaterial.Succeeded())
{
Mesh->SetMaterial(0, WoodMaterial.Object);
}
ResourceClusterProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ResourceClusterProxy"));
ResourceClusterProxy->SetupAttachment(RootComponent);
ResourceClusterProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
ResourceClusterProxy->SetGenerateOverlapEvents(false);
if (CylinderMesh.Succeeded())
{
ResourceClusterProxy->SetStaticMesh(CylinderMesh.Object);
}
if (WoodMaterial.Succeeded())
{
ResourceClusterProxy->SetMaterial(0, WoodMaterial.Object);
}
ResourceClusterProxy->SetRelativeLocation(FVector(0.0f, -18.0f, 28.0f));
ResourceClusterProxy->SetRelativeRotation(FRotator(0.0f, 90.0f, 90.0f));
ResourceClusterProxy->SetRelativeScale3D(FVector(0.12f, 0.12f, 0.7f));
HarvestableMarkerProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("HarvestableMarkerProxy"));
HarvestableMarkerProxy->SetupAttachment(RootComponent);
HarvestableMarkerProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
HarvestableMarkerProxy->SetGenerateOverlapEvents(false);
if (ChamferCubeMesh.Succeeded())
{
HarvestableMarkerProxy->SetStaticMesh(ChamferCubeMesh.Object);
}
if (FiberMaterial.Succeeded())
{
HarvestableMarkerProxy->SetMaterial(0, FiberMaterial.Object);
}
HarvestableMarkerProxy->SetRelativeLocation(FVector(0.0f, 22.0f, 36.0f));
HarvestableMarkerProxy->SetRelativeScale3D(FVector(0.28f, 0.18f, 0.22f));
YieldItem.ItemId = TEXT("wood"); YieldItem.ItemId = TEXT("wood");
YieldItem.DisplayName = FText::FromString(TEXT("Wood")); YieldItem.DisplayName = FText::FromString(TEXT("Wood"));
YieldItem.Quantity = 1; YieldItem.Quantity = 1;
@@ -27,6 +27,12 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Resource") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Resource")
TObjectPtr<UStaticMeshComponent> Mesh; TObjectPtr<UStaticMeshComponent> Mesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Resource|Visuals")
TObjectPtr<UStaticMeshComponent> ResourceClusterProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Resource|Visuals")
TObjectPtr<UStaticMeshComponent> HarvestableMarkerProxy;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Resource") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Resource")
FAgrarianItemStack YieldItem; FAgrarianItemStack YieldItem;
@@ -4,7 +4,32 @@
#include "AgrarianPersistentActorComponent.h" #include "AgrarianPersistentActorComponent.h"
#include "Components/BoxComponent.h" #include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h" #include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"
#include "Materials/MaterialInterface.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
#include "UObject/ConstructorHelpers.h"
namespace
{
void ConfigureShelterProxyComponent(UStaticMeshComponent* Component, UStaticMesh* MeshAsset, UMaterialInterface* MaterialAsset)
{
if (!Component)
{
return;
}
Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Component->SetGenerateOverlapEvents(false);
if (MeshAsset)
{
Component->SetStaticMesh(MeshAsset);
}
if (MaterialAsset)
{
Component->SetMaterial(0, MaterialAsset);
}
}
}
AAgrarianShelterActor::AAgrarianShelterActor() AAgrarianShelterActor::AAgrarianShelterActor()
{ {
@@ -13,6 +38,63 @@ AAgrarianShelterActor::AAgrarianShelterActor()
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh")); Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
RootComponent = Mesh; RootComponent = Mesh;
Mesh->SetCollisionProfileName(TEXT("BlockAll"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cube.SM_AGR_Placeholder_Cube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> ChamferCubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_ChamferCube.SM_AGR_Placeholder_ChamferCube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WoodMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Wood_Resource.M_AGR_GZ_Wood_Resource"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> FiberMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Fiber_Resource.M_AGR_GZ_Fiber_Resource"));
if (CubeMesh.Succeeded())
{
Mesh->SetStaticMesh(CubeMesh.Object);
Mesh->SetRelativeScale3D(FVector(3.2f, 2.6f, 0.08f));
}
if (WoodMaterial.Succeeded())
{
Mesh->SetMaterial(0, WoodMaterial.Object);
}
FloorProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FloorProxy"));
FloorProxy->SetupAttachment(RootComponent);
ConfigureShelterProxyComponent(FloorProxy, CubeMesh.Succeeded() ? CubeMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
FloorProxy->SetRelativeLocation(FVector(0.0f, 0.0f, 10.0f));
FloorProxy->SetRelativeScale3D(FVector(3.0f, 2.4f, 0.08f));
BackWallProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BackWallProxy"));
BackWallProxy->SetupAttachment(RootComponent);
ConfigureShelterProxyComponent(BackWallProxy, CubeMesh.Succeeded() ? CubeMesh.Object : nullptr, FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
BackWallProxy->SetRelativeLocation(FVector(-140.0f, 0.0f, 105.0f));
BackWallProxy->SetRelativeScale3D(FVector(0.14f, 2.2f, 1.5f));
LeftRoofProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LeftRoofProxy"));
LeftRoofProxy->SetupAttachment(RootComponent);
ConfigureShelterProxyComponent(LeftRoofProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : (CubeMesh.Succeeded() ? CubeMesh.Object : nullptr), FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
LeftRoofProxy->SetRelativeLocation(FVector(8.0f, -82.0f, 168.0f));
LeftRoofProxy->SetRelativeRotation(FRotator(0.0f, 0.0f, -24.0f));
LeftRoofProxy->SetRelativeScale3D(FVector(3.1f, 0.16f, 1.45f));
RightRoofProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RightRoofProxy"));
RightRoofProxy->SetupAttachment(RootComponent);
ConfigureShelterProxyComponent(RightRoofProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : (CubeMesh.Succeeded() ? CubeMesh.Object : nullptr), FiberMaterial.Succeeded() ? FiberMaterial.Object : nullptr);
RightRoofProxy->SetRelativeLocation(FVector(8.0f, 82.0f, 168.0f));
RightRoofProxy->SetRelativeRotation(FRotator(0.0f, 0.0f, 24.0f));
RightRoofProxy->SetRelativeScale3D(FVector(3.1f, 0.16f, 1.45f));
FrameProxyA = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FrameProxyA"));
FrameProxyA->SetupAttachment(RootComponent);
ConfigureShelterProxyComponent(FrameProxyA, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
FrameProxyA->SetRelativeLocation(FVector(95.0f, -94.0f, 96.0f));
FrameProxyA->SetRelativeRotation(FRotator(0.0f, 0.0f, -12.0f));
FrameProxyA->SetRelativeScale3D(FVector(0.12f, 0.12f, 1.92f));
FrameProxyB = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FrameProxyB"));
FrameProxyB->SetupAttachment(RootComponent);
ConfigureShelterProxyComponent(FrameProxyB, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, WoodMaterial.Succeeded() ? WoodMaterial.Object : nullptr);
FrameProxyB->SetRelativeLocation(FVector(95.0f, 94.0f, 96.0f));
FrameProxyB->SetRelativeRotation(FRotator(0.0f, 0.0f, 12.0f));
FrameProxyB->SetRelativeScale3D(FVector(0.12f, 0.12f, 1.92f));
ProtectionVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("ProtectionVolume")); ProtectionVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("ProtectionVolume"));
ProtectionVolume->SetupAttachment(RootComponent); ProtectionVolume->SetupAttachment(RootComponent);
@@ -28,6 +28,24 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter")
TObjectPtr<UStaticMeshComponent> Mesh; TObjectPtr<UStaticMeshComponent> Mesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter|Visuals")
TObjectPtr<UStaticMeshComponent> FloorProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter|Visuals")
TObjectPtr<UStaticMeshComponent> BackWallProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter|Visuals")
TObjectPtr<UStaticMeshComponent> LeftRoofProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter|Visuals")
TObjectPtr<UStaticMeshComponent> RightRoofProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter|Visuals")
TObjectPtr<UStaticMeshComponent> FrameProxyA;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter|Visuals")
TObjectPtr<UStaticMeshComponent> FrameProxyB;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Shelter")
TObjectPtr<UBoxComponent> ProtectionVolume; TObjectPtr<UBoxComponent> ProtectionVolume;
@@ -5,6 +5,9 @@
#include "AgrarianGameCharacter.h" #include "AgrarianGameCharacter.h"
#include "AgrarianSurvivalComponent.h" #include "AgrarianSurvivalComponent.h"
#include "Components/StaticMeshComponent.h" #include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"
#include "Materials/MaterialInterface.h"
#include "UObject/ConstructorHelpers.h"
AAgrarianWaterSource::AAgrarianWaterSource() AAgrarianWaterSource::AAgrarianWaterSource()
{ {
@@ -15,6 +18,66 @@ AAgrarianWaterSource::AAgrarianWaterSource()
RootComponent = Mesh; RootComponent = Mesh;
Mesh->SetCollisionProfileName(TEXT("BlockAll")); Mesh->SetCollisionProfileName(TEXT("BlockAll"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> PlaneMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Plane.SM_AGR_Placeholder_Plane"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cube.SM_AGR_Placeholder_Cube"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WaterMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_FreshWater.M_AGR_GZ_FreshWater"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> StoneMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Stone_Sandstone.M_AGR_GZ_Stone_Sandstone"));
if (CylinderMesh.Succeeded())
{
Mesh->SetStaticMesh(CylinderMesh.Object);
Mesh->SetRelativeScale3D(FVector(2.4f, 1.7f, 0.08f));
}
if (StoneMaterial.Succeeded())
{
Mesh->SetMaterial(0, StoneMaterial.Object);
}
WaterSurfaceProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WaterSurfaceProxy"));
WaterSurfaceProxy->SetupAttachment(RootComponent);
WaterSurfaceProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
WaterSurfaceProxy->SetGenerateOverlapEvents(false);
if (PlaneMesh.Succeeded())
{
WaterSurfaceProxy->SetStaticMesh(PlaneMesh.Object);
}
if (WaterMaterial.Succeeded())
{
WaterSurfaceProxy->SetMaterial(0, WaterMaterial.Object);
}
WaterSurfaceProxy->SetRelativeLocation(FVector(0.0f, 0.0f, 8.0f));
WaterSurfaceProxy->SetRelativeScale3D(FVector(2.15f, 1.45f, 1.0f));
StoneBankProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StoneBankProxy"));
StoneBankProxy->SetupAttachment(RootComponent);
StoneBankProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
StoneBankProxy->SetGenerateOverlapEvents(false);
if (CylinderMesh.Succeeded())
{
StoneBankProxy->SetStaticMesh(CylinderMesh.Object);
}
if (StoneMaterial.Succeeded())
{
StoneBankProxy->SetMaterial(0, StoneMaterial.Object);
}
StoneBankProxy->SetRelativeScale3D(FVector(2.55f, 1.85f, 0.05f));
CollectMarkerProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CollectMarkerProxy"));
CollectMarkerProxy->SetupAttachment(RootComponent);
CollectMarkerProxy->SetCollisionEnabled(ECollisionEnabled::NoCollision);
CollectMarkerProxy->SetGenerateOverlapEvents(false);
if (CubeMesh.Succeeded())
{
CollectMarkerProxy->SetStaticMesh(CubeMesh.Object);
}
if (WaterMaterial.Succeeded())
{
CollectMarkerProxy->SetMaterial(0, WaterMaterial.Object);
}
CollectMarkerProxy->SetRelativeLocation(FVector(0.0f, -84.0f, 24.0f));
CollectMarkerProxy->SetRelativeScale3D(FVector(0.22f, 0.08f, 0.32f));
DisplayName = FText::FromString(TEXT("Fresh Water")); DisplayName = FText::FromString(TEXT("Fresh Water"));
} }
@@ -20,6 +20,15 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Water") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Water")
TObjectPtr<UStaticMeshComponent> Mesh; TObjectPtr<UStaticMeshComponent> Mesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Water|Visuals")
TObjectPtr<UStaticMeshComponent> WaterSurfaceProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Water|Visuals")
TObjectPtr<UStaticMeshComponent> StoneBankProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Water|Visuals")
TObjectPtr<UStaticMeshComponent> CollectMarkerProxy;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Water", meta = (ClampMin = "0")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Water", meta = (ClampMin = "0"))
float WaterRestoreAmount = 45.0f; float WaterRestoreAmount = 45.0f;
@@ -4,11 +4,37 @@
#include "AgrarianGameCharacter.h" #include "AgrarianGameCharacter.h"
#include "AgrarianInventoryComponent.h" #include "AgrarianInventoryComponent.h"
#include "AIController.h" #include "AIController.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/StaticMesh.h"
#include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/CharacterMovementComponent.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Materials/MaterialInterface.h"
#include "Navigation/PathFollowingComponent.h" #include "Navigation/PathFollowingComponent.h"
#include "NavigationSystem.h" #include "NavigationSystem.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
#include "UObject/ConstructorHelpers.h"
namespace
{
void ConfigureWildlifeProxyComponent(UStaticMeshComponent* Component, UStaticMesh* MeshAsset, UMaterialInterface* MaterialAsset)
{
if (!Component)
{
return;
}
Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Component->SetGenerateOverlapEvents(false);
if (MeshAsset)
{
Component->SetStaticMesh(MeshAsset);
}
if (MaterialAsset)
{
Component->SetMaterial(0, MaterialAsset);
}
}
}
AAgrarianWildlifeBase::AAgrarianWildlifeBase() AAgrarianWildlifeBase::AAgrarianWildlifeBase()
{ {
@@ -22,6 +48,44 @@ AAgrarianWildlifeBase::AAgrarianWildlifeBase()
GetCharacterMovement()->bOrientRotationToMovement = true; GetCharacterMovement()->bOrientRotationToMovement = true;
bUseControllerRotationYaw = false; bUseControllerRotationYaw = false;
static ConstructorHelpers::FObjectFinder<UStaticMesh> ChamferCubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_ChamferCube.SM_AGR_Placeholder_ChamferCube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cube.SM_AGR_Placeholder_Cube"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMesh(TEXT("/Game/Agrarian/Environment/PlaceholderMeshes/SM_AGR_Placeholder_Cylinder.SM_AGR_Placeholder_Cylinder"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> FurMaterial(TEXT("/Game/Agrarian/Materials/M_AGR_GZ_Fiber_Resource.M_AGR_GZ_Fiber_Resource"));
WildlifeBodyProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WildlifeBodyProxy"));
WildlifeBodyProxy->SetupAttachment(RootComponent);
ConfigureWildlifeProxyComponent(WildlifeBodyProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : nullptr, FurMaterial.Succeeded() ? FurMaterial.Object : nullptr);
WildlifeBodyProxy->SetRelativeLocation(FVector(10.0f, 0.0f, -42.0f));
WildlifeBodyProxy->SetRelativeScale3D(FVector(0.62f, 0.32f, 0.24f));
WildlifeHeadProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WildlifeHeadProxy"));
WildlifeHeadProxy->SetupAttachment(WildlifeBodyProxy);
ConfigureWildlifeProxyComponent(WildlifeHeadProxy, ChamferCubeMesh.Succeeded() ? ChamferCubeMesh.Object : nullptr, FurMaterial.Succeeded() ? FurMaterial.Object : nullptr);
WildlifeHeadProxy->SetRelativeLocation(FVector(42.0f, 0.0f, 20.0f));
WildlifeHeadProxy->SetRelativeScale3D(FVector(0.46f, 0.34f, 0.36f));
WildlifeEarProxyA = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WildlifeEarProxyA"));
WildlifeEarProxyA->SetupAttachment(WildlifeHeadProxy);
ConfigureWildlifeProxyComponent(WildlifeEarProxyA, CubeMesh.Succeeded() ? CubeMesh.Object : nullptr, FurMaterial.Succeeded() ? FurMaterial.Object : nullptr);
WildlifeEarProxyA->SetRelativeLocation(FVector(4.0f, -12.0f, 28.0f));
WildlifeEarProxyA->SetRelativeRotation(FRotator(0.0f, 0.0f, -10.0f));
WildlifeEarProxyA->SetRelativeScale3D(FVector(0.08f, 0.08f, 0.38f));
WildlifeEarProxyB = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WildlifeEarProxyB"));
WildlifeEarProxyB->SetupAttachment(WildlifeHeadProxy);
ConfigureWildlifeProxyComponent(WildlifeEarProxyB, CubeMesh.Succeeded() ? CubeMesh.Object : nullptr, FurMaterial.Succeeded() ? FurMaterial.Object : nullptr);
WildlifeEarProxyB->SetRelativeLocation(FVector(4.0f, 12.0f, 28.0f));
WildlifeEarProxyB->SetRelativeRotation(FRotator(0.0f, 0.0f, 10.0f));
WildlifeEarProxyB->SetRelativeScale3D(FVector(0.08f, 0.08f, 0.38f));
WildlifeTailProxy = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WildlifeTailProxy"));
WildlifeTailProxy->SetupAttachment(WildlifeBodyProxy);
ConfigureWildlifeProxyComponent(WildlifeTailProxy, CylinderMesh.Succeeded() ? CylinderMesh.Object : nullptr, FurMaterial.Succeeded() ? FurMaterial.Object : nullptr);
WildlifeTailProxy->SetRelativeLocation(FVector(-42.0f, 0.0f, 10.0f));
WildlifeTailProxy->SetRelativeRotation(FRotator(0.0f, 90.0f, 90.0f));
WildlifeTailProxy->SetRelativeScale3D(FVector(0.12f, 0.12f, 0.24f));
DisplayName = FText::FromString(TEXT("Wildlife")); DisplayName = FText::FromString(TEXT("Wildlife"));
} }
@@ -9,6 +9,7 @@
#include "AgrarianWildlifeBase.generated.h" #include "AgrarianWildlifeBase.generated.h"
class AAgrarianGameCharacter; class AAgrarianGameCharacter;
class UStaticMeshComponent;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAgrarianWildlifeStateChangedSignature, EAgrarianWildlifeState, NewState); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAgrarianWildlifeStateChangedSignature, EAgrarianWildlifeState, NewState);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAgrarianWildlifeHealthChangedSignature, float, Health, float, MaxHealth); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAgrarianWildlifeHealthChangedSignature, float, Health, float, MaxHealth);
@@ -30,6 +31,21 @@ public:
UPROPERTY(BlueprintAssignable, Category = "Agrarian|Wildlife") UPROPERTY(BlueprintAssignable, Category = "Agrarian|Wildlife")
FAgrarianWildlifeHealthChangedSignature OnWildlifeHealthChanged; FAgrarianWildlifeHealthChangedSignature OnWildlifeHealthChanged;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Wildlife|Visuals")
TObjectPtr<UStaticMeshComponent> WildlifeBodyProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Wildlife|Visuals")
TObjectPtr<UStaticMeshComponent> WildlifeHeadProxy;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Wildlife|Visuals")
TObjectPtr<UStaticMeshComponent> WildlifeEarProxyA;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Wildlife|Visuals")
TObjectPtr<UStaticMeshComponent> WildlifeEarProxyB;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Wildlife|Visuals")
TObjectPtr<UStaticMeshComponent> WildlifeTailProxy;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Wildlife") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Wildlife")
FName WildlifeId = TEXT("wildlife"); FName WildlifeId = TEXT("wildlife");