Add Ground Zero terrain pipeline and playable assets
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import unreal
|
||||
|
||||
|
||||
MAP_PATH = "/Game/ThirdPerson/Lvl_ThirdPerson"
|
||||
CHARACTER_CLASS_PATH = "/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter"
|
||||
RABBIT_LABEL = "AGR_RabbitWildlife_01"
|
||||
|
||||
|
||||
def get_actor_label(actor):
|
||||
try:
|
||||
return actor.get_actor_label()
|
||||
except Exception:
|
||||
return actor.get_name()
|
||||
|
||||
|
||||
def load_blueprint_class(path):
|
||||
generated_class = unreal.EditorAssetLibrary.load_blueprint_class(path)
|
||||
if not generated_class:
|
||||
raise RuntimeError(f"Could not load Blueprint class: {path}")
|
||||
return generated_class
|
||||
|
||||
|
||||
def find_actor_by_label(label):
|
||||
for actor in unreal.EditorLevelLibrary.get_all_level_actors():
|
||||
if get_actor_label(actor) == label:
|
||||
return actor
|
||||
return None
|
||||
|
||||
|
||||
def enum_name(value):
|
||||
return str(value).split(".")[-1].lower()
|
||||
|
||||
|
||||
def get_bool_property(actor, *property_names):
|
||||
for property_name in property_names:
|
||||
try:
|
||||
return bool(actor.get_editor_property(property_name))
|
||||
except Exception:
|
||||
continue
|
||||
raise RuntimeError(f"Could not read any bool property from {property_names}")
|
||||
|
||||
|
||||
def main():
|
||||
if not unreal.EditorLevelLibrary.load_level(MAP_PATH):
|
||||
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
||||
|
||||
character_class = load_blueprint_class(CHARACTER_CLASS_PATH)
|
||||
rabbit = find_actor_by_label(RABBIT_LABEL)
|
||||
if not rabbit:
|
||||
raise RuntimeError(f"Could not find placed rabbit wildlife: {RABBIT_LABEL}")
|
||||
|
||||
character = unreal.AgrarianEditorAutomationLibrary.spawn_actor_in_editor_world(
|
||||
character_class,
|
||||
unreal.Vector(500.0, 320.0, 180.0),
|
||||
unreal.Rotator(0.0, 0.0, 0.0),
|
||||
"AGR_AutomationWildlifeCharacter",
|
||||
)
|
||||
if not character:
|
||||
raise RuntimeError("Could not spawn automation character")
|
||||
|
||||
inventory = character.get_component_by_class(unreal.AgrarianInventoryComponent)
|
||||
if not inventory:
|
||||
raise RuntimeError("Automation character is missing AgrarianInventoryComponent")
|
||||
|
||||
starting_health = float(rabbit.get_editor_property("health"))
|
||||
max_health = float(rabbit.get_editor_property("max_health"))
|
||||
if starting_health <= 0.0 or max_health <= 0.0:
|
||||
raise RuntimeError(f"Rabbit starts invalid health={starting_health}, max_health={max_health}")
|
||||
|
||||
rabbit.apply_wildlife_damage(1.0, character)
|
||||
damaged_health = float(rabbit.get_editor_property("health"))
|
||||
damaged_state = enum_name(rabbit.get_editor_property("wildlife_state"))
|
||||
if not damaged_health < starting_health:
|
||||
raise RuntimeError(f"Rabbit non-lethal damage did not reduce health: {starting_health} -> {damaged_health}")
|
||||
if "fleeing" not in damaged_state:
|
||||
raise RuntimeError(f"Rabbit expected fleeing after non-lethal damage, got {damaged_state}")
|
||||
|
||||
rabbit.apply_wildlife_damage(max_health + 10.0, character)
|
||||
dead_health = float(rabbit.get_editor_property("health"))
|
||||
dead_state = enum_name(rabbit.get_editor_property("wildlife_state"))
|
||||
if dead_health != 0.0:
|
||||
raise RuntimeError(f"Rabbit lethal damage expected health 0, got {dead_health}")
|
||||
if "dead" not in dead_state:
|
||||
raise RuntimeError(f"Rabbit expected dead after lethal damage, got {dead_state}")
|
||||
if not rabbit.can_interact(character):
|
||||
raise RuntimeError("Rabbit should be harvestable after death")
|
||||
|
||||
meat_before = inventory.get_item_count("meat")
|
||||
hide_before = inventory.get_item_count("hide")
|
||||
rabbit.interact(character)
|
||||
meat_after = inventory.get_item_count("meat")
|
||||
hide_after = inventory.get_item_count("hide")
|
||||
if meat_after <= meat_before:
|
||||
raise RuntimeError(f"Rabbit harvest did not add meat: {meat_before} -> {meat_after}")
|
||||
if hide_after <= hide_before:
|
||||
raise RuntimeError(f"Rabbit harvest did not add hide: {hide_before} -> {hide_after}")
|
||||
if not get_bool_property(rabbit, "b_harvested", "harvested"):
|
||||
raise RuntimeError("Rabbit harvest did not set bHarvested")
|
||||
if rabbit.can_interact(character):
|
||||
raise RuntimeError("Rabbit should not be harvestable twice")
|
||||
|
||||
unreal.EditorLevelLibrary.destroy_actor(character)
|
||||
unreal.log(
|
||||
"PASS: wildlife damage/death/harvest verified "
|
||||
f"health {starting_health}->{damaged_health}->0, "
|
||||
f"meat {meat_before}->{meat_after}, hide {hide_before}->{hide_after}"
|
||||
)
|
||||
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user