feat(quests): seed Trouble Beyond the Gate and the South Gate Warden
The demo character no longer starts with a free Basic Hide Bag: the bagless HIDE capacity of 1 is what the quest chain exists to teach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,10 @@ import { EquipmentSlot } from '../../items/equipment-slot.enum';
|
||||
import { ItemDefinition } from '../../items/entities/item-definition.entity';
|
||||
import { LootTableEntry } from '../../loot/entities/loot-table-entry.entity';
|
||||
import { LootTable } from '../../loot/entities/loot-table.entity';
|
||||
import { CharacterLootBag } from '../../loot-bags/entities/character-loot-bag.entity';
|
||||
import { LootBagDefinition } from '../../loot-bags/entities/loot-bag-definition.entity';
|
||||
import { NpcQuestAssignment } from '../../quests/entities/npc-quest-assignment.entity';
|
||||
import { QuestDefinition } from '../../quests/entities/quest-definition.entity';
|
||||
import { QuestObjective } from '../../quests/entities/quest-objective.entity';
|
||||
import { EncounterType } from '../../monsters/entities/encounter-type.enum';
|
||||
import { MonsterCategory } from '../../monsters/monster-category.enum';
|
||||
import { LocationMonster } from '../../monsters/entities/location-monster.entity';
|
||||
@@ -43,7 +45,12 @@ import {
|
||||
BURNED_ROAD_LOCAL_CONTENT,
|
||||
SOUTH_GATE_LOCAL_CONTENT,
|
||||
} from './local-location.content';
|
||||
import { BASIC_HIDE_BAG_ID, LOOT_BAG_DEFINITIONS } from './loot-bag-content';
|
||||
import { LOOT_BAG_DEFINITIONS } from './loot-bag-content';
|
||||
import {
|
||||
NPC_QUEST_ASSIGNMENTS,
|
||||
QUEST_DEFINITIONS,
|
||||
QUEST_OBJECTIVES,
|
||||
} from './quest-content';
|
||||
import { REPUTATION_FACTIONS } from './reputation-content';
|
||||
import {
|
||||
DIALOGUE_NODES,
|
||||
@@ -88,6 +95,10 @@ export async function seedVisibleVerticalSlice(
|
||||
const npcExchangeProfileRepository =
|
||||
dataSource.getRepository(NpcExchangeProfile);
|
||||
const exchangeRuleRepository = dataSource.getRepository(ExchangeRule);
|
||||
const questDefinitionRepository = dataSource.getRepository(QuestDefinition);
|
||||
const questObjectiveRepository = dataSource.getRepository(QuestObjective);
|
||||
const npcQuestAssignmentRepository =
|
||||
dataSource.getRepository(NpcQuestAssignment);
|
||||
|
||||
const locations = [
|
||||
{
|
||||
@@ -358,28 +369,14 @@ export async function seedVisibleVerticalSlice(
|
||||
});
|
||||
}
|
||||
|
||||
// ASSUMPTION (Slice 0.8.5 decision): the demo character keeps the Hide Bag
|
||||
// and no longer starts with the Trophy Pouch.
|
||||
// The demo character starts with no loot bag at all (Slice 0.9 decision D5).
|
||||
//
|
||||
// The pouch is now a reputation-gated offer (0.8.5 §4) and handing it over
|
||||
// for free would make the slice's own showcase pointless. The Hide Bag stays
|
||||
// until Slice 0.9 grants it through the warden's referral -- removing both
|
||||
// now would drop HIDE capacity to the bagless default of 1 with no way to
|
||||
// raise it, and the hunting loop would be unplayable in between.
|
||||
//
|
||||
// Delete this block once 0.9 hands the Hide Bag over in the quest.
|
||||
const characterLootBagRepository = dataSource.getRepository(CharacterLootBag);
|
||||
const existingBag = await characterLootBagRepository.findOneBy({
|
||||
characterId: DEMO_CHARACTER_ID,
|
||||
lootBagDefinitionId: BASIC_HIDE_BAG_ID,
|
||||
});
|
||||
if (!existingBag) {
|
||||
await characterLootBagRepository.insert({
|
||||
characterId: DEMO_CHARACTER_ID,
|
||||
lootBagDefinitionId: BASIC_HIDE_BAG_ID,
|
||||
active: true,
|
||||
});
|
||||
}
|
||||
// Slice 0.8.5 left the Hide Bag here as a stopgap, with a note to remove it
|
||||
// "once 0.9 hands the Hide Bag over in the quest". This is that moment: the
|
||||
// bagless HIDE capacity of 1 is what the first quest is built to teach
|
||||
// (0.9 §4), and a free bag would hide the lesson entirely. The quest's step
|
||||
// at Borin grants the bag instead, and the migration clears the row from
|
||||
// databases that were seeded before this change.
|
||||
|
||||
// NPC content (NPC Specification V1 §32; Playable Slice 0.8).
|
||||
//
|
||||
@@ -401,6 +398,16 @@ export async function seedVisibleVerticalSlice(
|
||||
]);
|
||||
}
|
||||
|
||||
// Quest content (Playable Slice 0.9 §10; NPC spec §14).
|
||||
//
|
||||
// After the NPC upsert, because an assignment points at an NPC id. Objectives
|
||||
// and assignments conflict on `id` rather than on a natural key: an
|
||||
// objective's key is unique only within its quest, and an assignment has no
|
||||
// natural key at all beyond the triple its unique index already covers.
|
||||
await questDefinitionRepository.upsert(QUEST_DEFINITIONS, ['key']);
|
||||
await questObjectiveRepository.upsert(QUEST_OBJECTIVES, ['id']);
|
||||
await npcQuestAssignmentRepository.upsert(NPC_QUEST_ASSIGNMENTS, ['id']);
|
||||
|
||||
await dialogueNodeRepository.upsert(DIALOGUE_NODES, ['npcId', 'key']);
|
||||
await npcShopRepository.upsert(NPC_SHOPS, ['key']);
|
||||
// By id, not by (shop, item): an offer may now sell a bag instead of an
|
||||
|
||||
Reference in New Issue
Block a user