Files
Documentation/content/gameplay-systems/npc-objectives.en.md
2026-01-20 20:33:59 +01:00

5.4 KiB

title, type, weight
title type weight
NPC Objectives docs 3

The NPC objectives system extends the base objective system with combat-related tasks.

Package: com.hypixel.hytale.builtin.adventure.npcobjectives

Architecture

NPCObjectivesPlugin
├── Task Types
│   ├── KillSpawnBeaconObjectiveTask - Kill NPCs from spawn beacons
│   ├── KillSpawnMarkerObjectiveTask - Kill NPCs from spawn markers
│   ├── BountyObjectiveTask - Hunt specific NPC targets
│   └── KillNPCObjectiveTask - Kill NPCs by type/group
├── Resources
│   └── KillTrackerResource - Tracks kill counts
├── Systems
│   ├── KillTrackerSystem - Monitors NPC deaths
│   └── SpawnBeaconCheckRemovalSystem - Cleanup spawn beacons
└── NPC Actions
    ├── BuilderActionCompleteTask - Complete task on NPC
    ├── BuilderActionStartObjective - Start objective from NPC
    └── BuilderSensorHasTask - Check if player has task

Task Types

KillTask Interface

All kill-based tasks implement this interface:

public interface KillTask {
    void checkKilledEntity(
        Store<EntityStore> store,
        Ref<EntityStore> npcRef,
        Objective objective,
        NPCEntity npc,
        Damage damageInfo
    );
}

Registered Task Types

Type Task Asset Class Description
KillSpawnBeacon KillSpawnBeaconObjectiveTaskAsset Kill NPCs from beacons
KillSpawnMarker KillSpawnMarkerObjectiveTaskAsset Kill NPCs from markers
Bounty BountyObjectiveTaskAsset Hunt specific target
KillNPC KillObjectiveTaskAsset Kill NPCs by group

Bounty Task

Spawns a specific NPC and marks it as a bounty target:

public class BountyObjectiveTask extends ObjectiveTask implements KillTask {
    boolean completed;
    UUID entityUuid;  // Target NPC UUID

    // Spawns NPC at position and adds map marker
    protected TransactionRecord[] setup0(Objective objective, World world, Store<EntityStore> store) {
        // Get spawn position from asset configuration
        Vector3i spawnPosition = getAsset().getWorldLocationProvider()
            .runCondition(world, objectivePosition);

        // Spawn the bounty NPC
        Pair<Ref<EntityStore>, INonPlayerCharacter> npcPair =
            NPCPlugin.get().spawnNPC(store, getAsset().getNpcId(), null, spawnPosition, Vector3f.ZERO);

        // Add map marker for bounty
        addMarker(new MapMarker(
            getBountyMarkerIDFromUUID(npcUuid),
            "Bounty Target",
            "Home.png",
            transform
        ));

        // Register kill tracker
        store.getResource(KillTrackerResource.getResourceType()).watch(transaction);

        return transactionRecords;
    }

    @Override
    public void checkKilledEntity(Store<EntityStore> store, Ref<EntityStore> npcRef,
                                   Objective objective, NPCEntity npc, Damage damageInfo) {
        if (!this.entityUuid.equals(uuid)) return;
        this.completed = true;
        this.complete(objective, store);
        objective.checkTaskSetCompletion(store);
        this.removeMarker(getBountyMarkerIDFromUUID(uuid));
    }
}

Asset Configuration

# Objectives/bounty_quest.json
{
  "Id": "bounty_quest",
  "TaskSets": [
    {
      "Tasks": [
        {
          "Type": "Bounty",
          "NpcId": "bandit_leader",
          "WorldLocationProvider": {
            "Type": "LocationRadius",
            "Radius": 50
          }
        }
      ]
    }
  ]
}

Kill Tracker

KillTrackerResource

World resource that tracks NPC kills:

ResourceType<EntityStore, KillTrackerResource> type =
    NPCObjectivesPlugin.get().getKillTrackerResourceType();

KillTrackerSystem

ECS system that monitors NPC deaths and notifies watching tasks:

// Register transaction to watch for kills
KillTaskTransaction transaction = new KillTaskTransaction(task, objective, store);
store.getResource(KillTrackerResource.getResourceType()).watch(transaction);

NPC Actions

Registered as NPC core component types for AI integration:

CompleteTask Action

// Completes a task when NPC interaction occurs
NPCPlugin.get().registerCoreComponentType("CompleteTask", BuilderActionCompleteTask::new);

StartObjective Action

// Starts an objective from NPC dialogue/interaction
NPCPlugin.get().registerCoreComponentType("StartObjective", BuilderActionStartObjective::new);

HasTask Sensor

// Sensor that checks if player has a specific task
NPCPlugin.get().registerCoreComponentType("HasTask", BuilderSensorHasTask::new);

API Usage

Check if Player Has Task

boolean hasTask = NPCObjectivesPlugin.hasTask(playerUUID, npcId, "taskId");

Update Task Completion

String animationId = NPCObjectivesPlugin.updateTaskCompletion(
    store, ref, playerRef, npcId, "taskId"
);

Start Objective from NPC

NPCObjectivesPlugin.startObjective(playerReference, "quest_id", store);

Asset Loading Order

The plugin ensures proper asset loading order:

AssetRegistry.getAssetStore(ObjectiveAsset.class).injectLoadsAfter(SpawnMarker.class);
AssetRegistry.getAssetStore(ObjectiveAsset.class).injectLoadsAfter(BeaconNPCSpawn.class);
AssetRegistry.getAssetStore(ObjectiveAsset.class).injectLoadsAfter(NPCGroup.class);