Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/nikolaj-lat/World-Puppeteer --skill triggers명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
| name | triggers |
| description | Schema and rules for creating triggers |
| context | fork |
| agent | triggers |
Edit tabs/triggers.json.
| Field | Requirement |
|---|---|
name | Must match object key exactly |
conditions | Array of TriggerCondition objects (see format below) |
effects | Array of TriggerEffect objects (see format below) |
| Field | When to Include |
|---|---|
recurring | Set to true only when trigger should fire every turn conditions are met |
scope | Set to 'player' only when effects should target the specific players who satisfy the conditions (multiplayer). Omit for normal party-wide triggers |
script | Only when declarative conditions/effects can't express the logic (branching, derived math, cross-trigger coordination). See trigger-scripts-reference.md |
Trigger-script gotchas: a story effect on tick 0 does not change the opening — put opening narration in the story-start text or fire at tick >= 1. Scripts go only in the top-level script field; never invent JS condition/effect types. Full details in the reference.
Omit these fields (auto-set or unused):
embeddingId (auto-generated for semantic conditions)All conditions in a trigger must pass for effects to fire.
| Type | Description | Required Fields |
|---|---|---|
story | Query matches recent story narrative | query |
action | Query matches player's current action | query |
Format: { type: 'story' | 'action', query: 'natural language description' }
String conditions (party-realm, party-region, party-location, party-area, story-text, action-text):
{ type: '...', operator: 'equals' | 'notEquals' | 'contains' | 'notContains' | 'regex', value: 'string' }
Number conditions (player-level, game-tick, player-resource):
{ type: '...', operator: 'equals' | 'notEquals' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual', value: number }
// For player-resource, also include: resource: 'resourceName'
Boolean conditions (known-entity):
{ type: 'known-entity', operator: 'equals' | 'notEquals', value: boolean, entity: 'entityName' }
Array conditions (player-traits, quests-completed):
{ type: '...', operator: 'contains' | 'notContains', value: 'string' }
Read conditions (read-string, read-number, read-boolean, read-array):
{ type: '...', key: 'triggerWritableKey', operator: '...', value: '...' }
Status conditions (quest-status, narrative-event-status):
{ type: 'quest-status', questId: 'questKey', operator: 'equals' | 'notEquals' | 'contains' | 'notContains' | 'regex', value: 'string' }
// Quest statuses: hidden | available | expired | accepted | completed | abandoned | rejected
// questId resolves by quest key first, then by unique quest name
{ type: 'narrative-event-status', eventId: 'eventKey', operator: 'equals' | 'notEquals' | 'contains' | 'notContains' | 'regex', value: 'string' }
// Event statuses: inactive | active | stopped | completed
{ type: 'story', instruction: 'Text injected into story generation' }
{ type: 'quest-progress', questId: 'questKey' } // Marks main objective satisfied, shows a status line
{ type: 'quest-complete', questId: 'questKey' } // Same, but silent — no player-visible status line
{ type: 'quest-init', operator: 'set', value: 'Quest Name' } // Makes quest available
{ type: 'quest-objective-reveal', questId: 'questKey', objectiveId: 'objectiveKey' } // Activates an authored objective, makes it the active objective
{ type: 'quest-objective-complete', questId: 'questKey', objectiveId: 'objectiveKey' } // Completes the objective, advances next step
{ type: 'quest-next-step-set', questId: 'questKey', text: 'guidance', source: 'objective' | 'narrative-event' }
{ type: 'quest-next-step-clear', questId: 'questKey' }
{ type: 'party-next-step-set', text: 'guidance', source: 'objective' | 'narrative-event' } // Party-wide guidance shown when no quest is active
{ type: 'party-next-step-clear' }
{ type: 'narrative-event-start', eventId: 'eventKey' } // Starts (or resumes) a narrative event; ignored if another event is active
{ type: 'party-realm' | 'party-region' | 'party-location' | 'party-area', operator: 'set', value: 'name' }
{ type: 'player-resource', resource: 'resourceName', operator: 'set' | 'add' | 'subtract' | 'multiply' | 'divide', value: number }
// Optional: target: 'allPlayers' | 'satisfyingPlayers' — which players the effect applies to
{ type: 'known-entity', entity: 'entityName', operator: 'set' | 'toggle', value?: boolean }
{ type: 'player-traits', operator: 'set' | 'add' | 'remove', value: 'traitName' | ['trait1', 'trait2'] }
// Optional: target: 'allPlayers' | 'satisfyingPlayers' — which players the effect applies to
{ type: 'write-string' | 'write-number' | 'write-boolean' | 'write-array', key: 'keyName', operator: '...', value: '...' }
Triggers evaluate in exactly one phase based on conditions:
Has action or action-text condition? | Phase |
|---|---|
| Yes | Planning (before story) |
| No | State (after story) |
Omitting scope (or setting 'party') keeps the legacy behavior: effects apply to every player. With scope: 'player':
player-level, player-resource, player-traits); for semantic conditions the AI attributes which players the story text supportsplayer-resource / player-traits effects apply only to those players (unless target: 'allPlayers' is set); story effects address them by nameFiring itself is unchanged: a mechanical player condition still fires when at least one player satisfies it.
story effects on tick 0 do NOT affect initial story. Use storyStart text or tick 1+ triggersrecurring: true, triggers fire only once everinterface Trigger {
name: string
conditions: TriggerCondition[]
effects: TriggerEffect[]
recurring?: boolean
scope?: 'party' | 'player'
script?: string
}
For detailed documentation, see triggers-reference.md.
SOC 직업 분류 기준