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

203 lines
5.4 KiB
Markdown

---
title: NPC Objectives
type: docs
weight: 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:
```java
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:
```java
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
```yaml
# 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:
```java
ResourceType<EntityStore, KillTrackerResource> type =
NPCObjectivesPlugin.get().getKillTrackerResourceType();
```
### KillTrackerSystem
ECS system that monitors NPC deaths and notifies watching tasks:
```java
// 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
```java
// Completes a task when NPC interaction occurs
NPCPlugin.get().registerCoreComponentType("CompleteTask", BuilderActionCompleteTask::new);
```
### StartObjective Action
```java
// Starts an objective from NPC dialogue/interaction
NPCPlugin.get().registerCoreComponentType("StartObjective", BuilderActionStartObjective::new);
```
### HasTask Sensor
```java
// Sensor that checks if player has a specific task
NPCPlugin.get().registerCoreComponentType("HasTask", BuilderSensorHasTask::new);
```
## API Usage
### Check if Player Has Task
```java
boolean hasTask = NPCObjectivesPlugin.hasTask(playerUUID, npcId, "taskId");
```
### Update Task Completion
```java
String animationId = NPCObjectivesPlugin.updateTaskCompletion(
store, ref, playerRef, npcId, "taskId"
);
```
### Start Objective from NPC
```java
NPCObjectivesPlugin.startObjective(playerReference, "quest_id", store);
```
## Asset Loading Order
The plugin ensures proper asset loading order:
```java
AssetRegistry.getAssetStore(ObjectiveAsset.class).injectLoadsAfter(SpawnMarker.class);
AssetRegistry.getAssetStore(ObjectiveAsset.class).injectLoadsAfter(BeaconNPCSpawn.class);
AssetRegistry.getAssetStore(ObjectiveAsset.class).injectLoadsAfter(NPCGroup.class);
```