Add Ground Zero water source
This commit is contained in:
@@ -427,7 +427,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
|||||||
- [x] Add foliage pass.
|
- [x] Add foliage pass.
|
||||||
- [~] Add resource nodes.
|
- [~] Add resource nodes.
|
||||||
- [x] Add biome-appropriate natural resources based on Ground Zero.
|
- [x] Add biome-appropriate natural resources based on Ground Zero.
|
||||||
- [ ] Add water source.
|
- [x] Add water source.
|
||||||
- [ ] Add weather exposure zones if needed.
|
- [ ] Add weather exposure zones if needed.
|
||||||
- [ ] Add landmark or ruin placeholder.
|
- [ ] Add landmark or ruin placeholder.
|
||||||
- [ ] Add spawn area.
|
- [ ] Add spawn area.
|
||||||
@@ -1402,4 +1402,4 @@ Next version .01 priorities:
|
|||||||
|
|
||||||
Immediate next item:
|
Immediate next item:
|
||||||
|
|
||||||
- [ ] Add water source.
|
- [ ] Add weather exposure zones if needed.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,27 @@
|
|||||||
|
# Ground Zero Freshwater Source
|
||||||
|
|
||||||
|
The Ground Zero map now has a first-pass gameplay freshwater source.
|
||||||
|
|
||||||
|
## Placement
|
||||||
|
|
||||||
|
- Actor label: `AGR_GZ_FreshWaterSource_01`
|
||||||
|
- Blueprint: `/Game/Agrarian/Blueprints/World/BP_FreshWaterSource`
|
||||||
|
- Placement intent: drainage-candidate area identified during the landform pass.
|
||||||
|
|
||||||
|
The previous water/shoreline analysis found no ocean, lake, or confirmed stream
|
||||||
|
inside the current 1 km tile. This actor is therefore a gameplay MVP freshwater
|
||||||
|
source, not a confirmed hydrography feature.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
|
||||||
|
The water source is an interactable actor. On server-authoritative interaction,
|
||||||
|
it restores thirst through `UAgrarianSurvivalComponent::AddWater`.
|
||||||
|
|
||||||
|
- Restore amount: `45`
|
||||||
|
- Interaction text: `Drink from Fresh Water Spring`
|
||||||
|
|
||||||
|
## Follow-Up
|
||||||
|
|
||||||
|
Later hydrography work should validate this drainage candidate against USGS NHD
|
||||||
|
or equivalent data. If a confirmed stream or spring is available, replace this
|
||||||
|
placeholder with the real watercourse location and geometry.
|
||||||
@@ -179,6 +179,17 @@ BIOME_RESOURCE_ACTORS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
WATER_SOURCE_ACTORS = [
|
||||||
|
{
|
||||||
|
"label": "AGR_GZ_FreshWaterSource_01",
|
||||||
|
"class_path": "/Game/Agrarian/Blueprints/World/BP_FreshWaterSource",
|
||||||
|
"location_xy": unreal.Vector(-7200.0, 10400.0, 0.0),
|
||||||
|
"z_offset": 36.0,
|
||||||
|
"rotation": unreal.Rotator(0.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
FOLIAGE_ZONES = {
|
FOLIAGE_ZONES = {
|
||||||
"trees": {
|
"trees": {
|
||||||
"count": 42,
|
"count": 42,
|
||||||
@@ -395,6 +406,7 @@ def main():
|
|||||||
|
|
||||||
labels = {spec["label"] for spec in DEMO_ACTORS}
|
labels = {spec["label"] for spec in DEMO_ACTORS}
|
||||||
labels.update(spec["label"] for spec in BIOME_RESOURCE_ACTORS)
|
labels.update(spec["label"] for spec in BIOME_RESOURCE_ACTORS)
|
||||||
|
labels.update(spec["label"] for spec in WATER_SOURCE_ACTORS)
|
||||||
labels.add(FOLIAGE_LABEL)
|
labels.add(FOLIAGE_LABEL)
|
||||||
remove_existing_demo_actors(labels)
|
remove_existing_demo_actors(labels)
|
||||||
|
|
||||||
@@ -402,6 +414,8 @@ def main():
|
|||||||
spawn_foliage_actor(height_values)
|
spawn_foliage_actor(height_values)
|
||||||
for spec in BIOME_RESOURCE_ACTORS:
|
for spec in BIOME_RESOURCE_ACTORS:
|
||||||
spawn_demo_actor(spec, height_values)
|
spawn_demo_actor(spec, height_values)
|
||||||
|
for spec in WATER_SOURCE_ACTORS:
|
||||||
|
spawn_demo_actor(spec, height_values)
|
||||||
for spec in DEMO_ACTORS:
|
for spec in DEMO_ACTORS:
|
||||||
spawn_demo_actor(spec, height_values)
|
spawn_demo_actor(spec, height_values)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ BLUEPRINT_ROOT = "/Game/Agrarian/Blueprints"
|
|||||||
RESOURCE_FOLDER = f"{BLUEPRINT_ROOT}/Resources"
|
RESOURCE_FOLDER = f"{BLUEPRINT_ROOT}/Resources"
|
||||||
STRUCTURE_FOLDER = f"{BLUEPRINT_ROOT}/Structures"
|
STRUCTURE_FOLDER = f"{BLUEPRINT_ROOT}/Structures"
|
||||||
WILDLIFE_FOLDER = f"{BLUEPRINT_ROOT}/Wildlife"
|
WILDLIFE_FOLDER = f"{BLUEPRINT_ROOT}/Wildlife"
|
||||||
|
WORLD_FOLDER = f"{BLUEPRINT_ROOT}/World"
|
||||||
|
|
||||||
WOOD_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Wood"
|
WOOD_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Wood"
|
||||||
FIBER_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Fiber"
|
FIBER_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Fiber"
|
||||||
@@ -62,6 +63,17 @@ BLUEPRINTS = [
|
|||||||
"mesh": MESH_CYLINDER_PATH,
|
"mesh": MESH_CYLINDER_PATH,
|
||||||
"scale": unreal.Vector(1.3, 1.3, 0.25),
|
"scale": unreal.Vector(1.3, 1.3, 0.25),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"asset": "BP_FreshWaterSource",
|
||||||
|
"folder": WORLD_FOLDER,
|
||||||
|
"parent": unreal.AgrarianWaterSource,
|
||||||
|
"defaults": {
|
||||||
|
"water_restore_amount": 45.0,
|
||||||
|
"display_name": "Fresh Water Spring",
|
||||||
|
},
|
||||||
|
"mesh": MESH_CYLINDER_PATH,
|
||||||
|
"scale": unreal.Vector(2.2, 2.2, 0.12),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"asset": "BP_PrimitiveShelter",
|
"asset": "BP_PrimitiveShelter",
|
||||||
"folder": STRUCTURE_FOLDER,
|
"folder": STRUCTURE_FOLDER,
|
||||||
@@ -165,7 +177,7 @@ def apply_defaults(blueprint, config):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
for folder in (RESOURCE_FOLDER, STRUCTURE_FOLDER, WILDLIFE_FOLDER):
|
for folder in (RESOURCE_FOLDER, STRUCTURE_FOLDER, WILDLIFE_FOLDER, WORLD_FOLDER):
|
||||||
unreal.EditorAssetLibrary.make_directory(folder)
|
unreal.EditorAssetLibrary.make_directory(folder)
|
||||||
|
|
||||||
for config in BLUEPRINTS:
|
for config in BLUEPRINTS:
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import unreal
|
||||||
|
|
||||||
|
|
||||||
|
MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test"
|
||||||
|
WATER_SOURCE_LABEL = "AGR_GZ_FreshWaterSource_01"
|
||||||
|
EXPECTED_WATER_RESTORE = 45.0
|
||||||
|
|
||||||
|
|
||||||
|
def nearly_equal(left, right, tolerance=0.001):
|
||||||
|
return abs(float(left) - float(right)) <= tolerance
|
||||||
|
|
||||||
|
|
||||||
|
def get_actor_label(actor):
|
||||||
|
try:
|
||||||
|
return actor.get_actor_label()
|
||||||
|
except Exception:
|
||||||
|
return actor.get_name()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not unreal.EditorLevelLibrary.load_level(MAP_PATH):
|
||||||
|
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
||||||
|
|
||||||
|
actors = unreal.EditorLevelLibrary.get_all_level_actors()
|
||||||
|
water_sources = [actor for actor in actors if get_actor_label(actor) == WATER_SOURCE_LABEL]
|
||||||
|
if len(water_sources) != 1:
|
||||||
|
raise RuntimeError(f"Expected exactly one {WATER_SOURCE_LABEL}, found {len(water_sources)}")
|
||||||
|
|
||||||
|
water_source = water_sources[0]
|
||||||
|
actual_restore = water_source.get_editor_property("water_restore_amount")
|
||||||
|
if not nearly_equal(actual_restore, EXPECTED_WATER_RESTORE):
|
||||||
|
raise RuntimeError(f"Water restore expected {EXPECTED_WATER_RESTORE}, got {actual_restore}")
|
||||||
|
|
||||||
|
if not isinstance(water_source, unreal.AgrarianWaterSource):
|
||||||
|
raise RuntimeError(f"{WATER_SOURCE_LABEL} is not an AgrarianWaterSource")
|
||||||
|
|
||||||
|
unreal.log(
|
||||||
|
"Ground Zero water source verification complete: "
|
||||||
|
f"{WATER_SOURCE_LABEL}, restore={actual_restore}."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -30,6 +30,11 @@ EXPECTED = {
|
|||||||
"warmth_per_second": 0.03,
|
"warmth_per_second": 0.03,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/Game/Agrarian/Blueprints/World/BP_FreshWaterSource": {
|
||||||
|
"properties": {
|
||||||
|
"water_restore_amount": 45.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
"/Game/Agrarian/Blueprints/Structures/BP_PrimitiveShelter": {
|
"/Game/Agrarian/Blueprints/Structures/BP_PrimitiveShelter": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"weather_protection": 0.7,
|
"weather_protection": 0.7,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright Pacificao. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "AgrarianWaterSource.h"
|
||||||
|
|
||||||
|
#include "AgrarianGameCharacter.h"
|
||||||
|
#include "AgrarianSurvivalComponent.h"
|
||||||
|
#include "Components/StaticMeshComponent.h"
|
||||||
|
|
||||||
|
AAgrarianWaterSource::AAgrarianWaterSource()
|
||||||
|
{
|
||||||
|
bReplicates = true;
|
||||||
|
|
||||||
|
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||||
|
RootComponent = Mesh;
|
||||||
|
Mesh->SetCollisionProfileName(TEXT("BlockAll"));
|
||||||
|
|
||||||
|
DisplayName = FText::FromString(TEXT("Fresh Water"));
|
||||||
|
}
|
||||||
|
|
||||||
|
FText AAgrarianWaterSource::GetInteractionText_Implementation(const AAgrarianGameCharacter* Interactor) const
|
||||||
|
{
|
||||||
|
return FText::Format(NSLOCTEXT("AgrarianWaterSource", "DrinkFromWaterSource", "Drink from {0}"), DisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AAgrarianWaterSource::CanInteract_Implementation(const AAgrarianGameCharacter* Interactor) const
|
||||||
|
{
|
||||||
|
return Interactor != nullptr && Interactor->GetSurvivalComponent() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AAgrarianWaterSource::Interact_Implementation(AAgrarianGameCharacter* Interactor)
|
||||||
|
{
|
||||||
|
if (!HasAuthority() || !Interactor)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UAgrarianSurvivalComponent* SurvivalComponent = Interactor->GetSurvivalComponent())
|
||||||
|
{
|
||||||
|
SurvivalComponent->AddWater(WaterRestoreAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright Pacificao. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "AgrarianInteractable.h"
|
||||||
|
#include "AgrarianWaterSource.generated.h"
|
||||||
|
|
||||||
|
class UStaticMeshComponent;
|
||||||
|
|
||||||
|
UCLASS(Blueprintable)
|
||||||
|
class AGRARIANGAME_API AAgrarianWaterSource : public AActor, public IAgrarianInteractable
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AAgrarianWaterSource();
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Water")
|
||||||
|
TObjectPtr<UStaticMeshComponent> Mesh;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Water", meta = (ClampMin = "0"))
|
||||||
|
float WaterRestoreAmount = 45.0f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Water")
|
||||||
|
FText DisplayName;
|
||||||
|
|
||||||
|
virtual FText GetInteractionText_Implementation(const AAgrarianGameCharacter* Interactor) const override;
|
||||||
|
virtual bool CanInteract_Implementation(const AAgrarianGameCharacter* Interactor) const override;
|
||||||
|
virtual void Interact_Implementation(AAgrarianGameCharacter* Interactor) override;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user