feat(conditions): evaluate QUEST_ACTIVE and QUEST_COMPLETED
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,9 @@ import { Character } from '../characters/entities/character.entity';
|
||||
import { CharacterItem } from '../items/entities/character-item.entity';
|
||||
import { ItemDefinition } from '../items/entities/item-definition.entity';
|
||||
import { CharacterNpcState } from '../npcs/entities/character-npc-state.entity';
|
||||
import { CharacterQuest } from '../quests/entities/character-quest.entity';
|
||||
import { QuestDefinition } from '../quests/entities/quest-definition.entity';
|
||||
import { CharacterQuestStatus } from '../quests/quest.types';
|
||||
import { CharacterReputation } from '../reputation/entities/character-reputation.entity';
|
||||
import { ReputationFaction } from '../reputation/entities/reputation-faction.entity';
|
||||
import {
|
||||
@@ -124,11 +127,63 @@ export class GameConditionService {
|
||||
return this.evaluateFlag(context, condition, scope);
|
||||
case GameConditionType.HAS_ITEM:
|
||||
return this.evaluateHasItem(context, condition, scope);
|
||||
case GameConditionType.QUEST_ACTIVE:
|
||||
return this.evaluateQuestStatus(
|
||||
context,
|
||||
condition,
|
||||
scope,
|
||||
CharacterQuestStatus.ACTIVE,
|
||||
);
|
||||
case GameConditionType.QUEST_COMPLETED:
|
||||
return this.evaluateQuestStatus(
|
||||
context,
|
||||
condition,
|
||||
scope,
|
||||
CharacterQuestStatus.COMPLETED,
|
||||
);
|
||||
default:
|
||||
return { met: false, actual: null };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the character stands in a given place with a given quest (§19).
|
||||
*
|
||||
* Boolean-shaped like `FLAG_SET` rather than numeric: a quest is active or it
|
||||
* is not, so `actual` stays null -- reporting "Current: 0" for it would be a
|
||||
* lie about a boolean, and the shop view renders these outcomes as
|
||||
* player-facing requirements.
|
||||
*
|
||||
* `value: false` is how content asks for the negative. The warden's offer
|
||||
* line needs "not active and not completed", and this keeps that expressible
|
||||
* without adding a NOT to the condition vocabulary.
|
||||
*/
|
||||
private async evaluateQuestStatus(
|
||||
context: ConditionContext,
|
||||
condition: GameCondition,
|
||||
scope: RepositoryScope,
|
||||
status: CharacterQuestStatus,
|
||||
): Promise<ConditionEvaluation> {
|
||||
if (!condition.key) {
|
||||
return { met: false, actual: null };
|
||||
}
|
||||
|
||||
const quest = await scope
|
||||
.getRepository(QuestDefinition)
|
||||
.findOneBy({ key: condition.key, enabled: true });
|
||||
if (!quest) {
|
||||
return { met: false, actual: null };
|
||||
}
|
||||
|
||||
const row = await scope.getRepository(CharacterQuest).findOneBy({
|
||||
characterId: context.characterId,
|
||||
questId: quest.id,
|
||||
});
|
||||
|
||||
const expected = condition.value ?? true;
|
||||
return { met: (row?.status === status) === expected, actual: null };
|
||||
}
|
||||
|
||||
private async evaluateRegionReputation(
|
||||
context: ConditionContext,
|
||||
condition: GameCondition,
|
||||
|
||||
Reference in New Issue
Block a user