Added AWQ Articles
This commit is contained in:
86
content/awq/articles/anatomy-of-a-player-character.mdoc
Normal file
86
content/awq/articles/anatomy-of-a-player-character.mdoc
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
title: Anatomy of a Player Character
|
||||||
|
path: awq
|
||||||
|
cover:
|
||||||
|
showInHeader: false
|
||||||
|
meta:
|
||||||
|
publicationDate: 2025-10-08T08:43:00.000Z
|
||||||
|
status: draft
|
||||||
|
isFeatured: false
|
||||||
|
tags: []
|
||||||
|
seo:
|
||||||
|
noIndex: false
|
||||||
|
---
|
||||||
|
Every model shares some common abilities
|
||||||
|
|
||||||
|
## Main Characteristics
|
||||||
|
Characteristics define the innate abilities of a model, and each characteristic has two skills associated with it
|
||||||
|
- **Weapon Skill (WS):** Aptitude in landing and avoiding blows in close combat; governs _Melee_ and _Defence_
|
||||||
|
- **Ballistic Skill (BS):** Capability of Hand-Eye-Coordination; governs _Skirmish_ and _Evasion_
|
||||||
|
- **Strength (S):** Used for brute force, stamina and might; governs _Brawn_ and _Toil_
|
||||||
|
- **Toughness (T):** Resistance to physical Trauma; governs _Consume Alcohol_ and _Endurance_
|
||||||
|
- **Initiative(I):** Reflects speed of thought and perception; governs _Perception_ and _Outdoor Survival_
|
||||||
|
- **Dexterity (Dex):** Affinity for performing fine and delicate manual tasks; governs _Skullduggery_ and _Tradecraft_
|
||||||
|
- **Agility (Ag):** Physical coordination and natural athleticism; governs _Stealth_ and _Athletics_
|
||||||
|
- **Intelligence (Int):** Power of thought, analysis, and understanding; governs _Intuition_ and _Education_
|
||||||
|
- **Willpower (WP):** General strength if mind; governs _Cool_ and _Animal Handling_
|
||||||
|
- **Fellowship (Fel):** Ability to get on with people; governs _Leadership_ and _Charm_
|
||||||
|
|
||||||
|
## Secondary Characteristics
|
||||||
|
- **Corruption Threshold (CT):[^*]** Ability to withstand _Mutation_
|
||||||
|
- **Insanity Threshold (IT):[^*]** Ability to withstand _Insanity_
|
||||||
|
- **Wounds (W):** Number of wounds a model can endure before _out of play_
|
||||||
|
- **Movement (M):** Indicator of how far a model can move under normal conditionsA
|
||||||
|
- **Fate Points (FP):[^*]** Can be used to avoid certain death and dark fates
|
||||||
|
- **Luck Points (LP):[^*]** Used for Re-rolls
|
||||||
|
- **Attacks (A):** Indicator of the numbers of attacks a character can make in a single round
|
||||||
|
- **Magic (Mag):** Denotes the Model's Wizard Level
|
||||||
|
|
||||||
|
## Skills
|
||||||
|
Used in _Checks_
|
||||||
|
- **Melee (WS):** Used to make _Melee Attack_ actions
|
||||||
|
- **Defense (WS):** Used to defend against a model's _Melee Attack_ action
|
||||||
|
- **Shooting (BS):** Used to make _Ranged Attack_ actions with _Missile_ weapons
|
||||||
|
- **Throwing (BS):** Used to make _Ranged Attack_ actions with _Throwing_ weapons
|
||||||
|
- **Brawn (S):** Used for immediate feats of strength
|
||||||
|
- **Toil (T):** Used for prolonged manual labor
|
||||||
|
- **Consume Alcohol (T):** Used for resisting short-term hazards like alcohol and poison
|
||||||
|
- **Endurance (T):** Used to endure hardship, withstand deprivation, and survive harsh environments
|
||||||
|
- **Perception (I):** Used to notice things
|
||||||
|
- **Dodge (I):** Used to evade attacks and immediate hazards, e.g. Traps
|
||||||
|
- **Stealth (Ag):** Used for moving quietly and concealing
|
||||||
|
- **Athletics (Ag):** Used for running, jumping, climbing, and swimming
|
||||||
|
- **Streetwise (Dex):** Used for picking locks or pockets, disarming traps and other feats of Sleight of Hand
|
||||||
|
- **Crafting (Dex):** Used when crafting trappings
|
||||||
|
- **Intuition (Int):** Used for detecting subterfuge and determining value of objects
|
||||||
|
- **Education (Int):** Used for recalling relevant information
|
||||||
|
- **Cool (WP):** Used to remain calm under stress, resisting fear, and psychological coercion
|
||||||
|
- **Animal Handling (WP):** Used to charm, train, and care for animals
|
||||||
|
- **Leadership (Fel):** Used for intimidation, command, and coercing obedience; often resisted by _Discipline_
|
||||||
|
- **Charm (Fel):** Used for deceiving, blathering, haggling, gossiping; usually resisted by _Intuition_
|
||||||
|
|
||||||
|
## Traits
|
||||||
|
Inherent abilities often based on Species, examples include Flier (for flying Monsters), Dark Vision, Mutation, and so on
|
||||||
|
|
||||||
|
## Lore[^*]
|
||||||
|
Define what a character knows and specialist skills and come in the following categories
|
||||||
|
- _Academic:_ Represent various academic fields like Accountancy, Anatomy, History and Law
|
||||||
|
- _Cultural:_ Represent the knowledge of social groups and language
|
||||||
|
- _Enemy:_ Represent the knowledge of adversaries and how to effectively combat them
|
||||||
|
- _Environment:_ Represent the knowledge of surviving in various hazardous environment
|
||||||
|
- _Magic Lores:_ Represent the knowledge of the various forms of magic and enables casting spells from them+
|
||||||
|
- _Specialist Weapon Groups:_ Represent training with special weapons like Polearms, Two-Handed Swords, Blackpowder Guns
|
||||||
|
- _Trade Lores:_ Represent the knowledge and ability to create certain trappings or work in certain fields, example Blacksmith, Weaver, Engineer, Artist
|
||||||
|
- _Vehicle Lores:_ Represent knowledge in operating vehicles and mounts
|
||||||
|
|
||||||
|
## Talents[^*]
|
||||||
|
Represent certain knacks, tricks and innate abilities a character has, examples would be Ambidextrous, Aetheric Attunement, Menacing or Acute Senses
|
||||||
|
|
||||||
|
## Maneuvers[^*]
|
||||||
|
Represent special combat actions and tactics a character can employ during combat, examples include Formation Fighting, Disarm, and Shield Bash
|
||||||
|
|
||||||
|
## Careers[^*]
|
||||||
|
Represent building blocks of a character, that provide certain skills, lores, talents, maneuvers, etc.
|
||||||
|
|
||||||
|
|
||||||
|
[^*]: Only applicable for _Player Characters_
|
||||||
@@ -10,7 +10,7 @@ cover:
|
|||||||
meta:
|
meta:
|
||||||
publicationDate: 2025-10-01T10:30:00.000Z
|
publicationDate: 2025-10-01T10:30:00.000Z
|
||||||
status: draft
|
status: draft
|
||||||
isFeatured: true
|
isFeatured: false
|
||||||
tags:
|
tags:
|
||||||
- how-and-what
|
- how-and-what
|
||||||
author: dave-damage
|
author: dave-damage
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import AuthorsCollection from '@/keystatic/collections/taxonomy/authors';
|
|||||||
import TagsCollection from '@/keystatic/collections/taxonomy/tags';
|
import TagsCollection from '@/keystatic/collections/taxonomy/tags';
|
||||||
import MetaPostsCollection from '@/keystatic/collections/meta/article';
|
import MetaPostsCollection from '@/keystatic/collections/meta/article';
|
||||||
|
|
||||||
|
import AWQColletions from '@/keystatic/collections/awq';
|
||||||
|
import awqCollections from '@/keystatic/collections/awq';
|
||||||
|
|
||||||
export default config({
|
export default config({
|
||||||
storage: {
|
storage: {
|
||||||
kind: 'local',
|
kind: 'local',
|
||||||
@@ -14,5 +17,6 @@ export default config({
|
|||||||
authors: AuthorsCollection,
|
authors: AuthorsCollection,
|
||||||
tags: TagsCollection,
|
tags: TagsCollection,
|
||||||
meta_posts: MetaPostsCollection,
|
meta_posts: MetaPostsCollection,
|
||||||
|
...awqCollections,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
14
src/keystatic/collections/awq/article.ts
Normal file
14
src/keystatic/collections/awq/article.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { collection } from '@keystatic/core';
|
||||||
|
|
||||||
|
import { createArticleField } from '@/keystatic/fields/article';
|
||||||
|
|
||||||
|
export default collection({
|
||||||
|
label: 'AWQ - Posts',
|
||||||
|
slugField: 'title',
|
||||||
|
path: 'content/awq/articles/*',
|
||||||
|
format: { contentField: 'content' },
|
||||||
|
entryLayout: 'content',
|
||||||
|
schema: {
|
||||||
|
...createArticleField('awq/articles', 'awq'),
|
||||||
|
},
|
||||||
|
});
|
||||||
7
src/keystatic/collections/awq/index.ts
Normal file
7
src/keystatic/collections/awq/index.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import posts from '@/keystatic/collections/awq/article';
|
||||||
|
|
||||||
|
const awqCollections = {
|
||||||
|
awq_posts: posts,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default awqCollections;
|
||||||
@@ -1,12 +1,17 @@
|
|||||||
import { fields } from '@keystatic/core';
|
import { fields } from '@keystatic/core';
|
||||||
|
|
||||||
import { createContentField } from '@/keystatic/fields/content';
|
import { createContentField } from '@/keystatic/fields/content';
|
||||||
|
import { createPathField } from '@/keystatic/fields/general';
|
||||||
import { createSEOField } from '@/keystatic/fields/seo';
|
import { createSEOField } from '@/keystatic/fields/seo';
|
||||||
import { createMetaField } from '@/keystatic/fields/meta';
|
import { createMetaField } from '@/keystatic/fields/meta';
|
||||||
|
|
||||||
export const createArticleField = (imageSubfolder: string) => ({
|
export const createArticleField = (
|
||||||
|
imageSubfolder: string,
|
||||||
|
defaultPath: string = ''
|
||||||
|
) => ({
|
||||||
title: fields.slug({ name: { label: 'Title' } }),
|
title: fields.slug({ name: { label: 'Title' } }),
|
||||||
summary: fields.text({ label: 'Summary', multiline: true }),
|
summary: fields.text({ label: 'Summary', multiline: true }),
|
||||||
|
path: createPathField(defaultPath),
|
||||||
cover: fields.object({
|
cover: fields.object({
|
||||||
src: fields.image({
|
src: fields.image({
|
||||||
label: 'Cover Image',
|
label: 'Cover Image',
|
||||||
|
|||||||
304
src/keystatic/fields/awq/general.ts
Normal file
304
src/keystatic/fields/awq/general.ts
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
import { type ComponentSchema, fields } from '@keystatic/core';
|
||||||
|
import { createOperatorField } from '@/keystatic/fields/general';
|
||||||
|
|
||||||
|
export const createCharacteristicReferenceField = (): ComponentSchema =>
|
||||||
|
fields.select({
|
||||||
|
label: 'Characteristic',
|
||||||
|
options: [
|
||||||
|
{ label: 'Weapon Skill', value: 'ws' },
|
||||||
|
{ label: 'Ballistic Skill', value: 'bs' },
|
||||||
|
{ label: 'Strength', value: 's' },
|
||||||
|
{ label: 'Toughness', value: 't' },
|
||||||
|
{ label: 'Initiative', value: 'i' },
|
||||||
|
{ label: 'Dexterity', value: 'dex' },
|
||||||
|
{ label: 'Agility', value: 'ag' },
|
||||||
|
{ label: 'Intelligence', value: 'int' },
|
||||||
|
{ label: 'Willpower', value: 'wp' },
|
||||||
|
{ label: 'Fellowship', value: 'fel' },
|
||||||
|
],
|
||||||
|
defaultValue: 'ws',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createSkillReferenceField = (): ComponentSchema =>
|
||||||
|
fields.select({
|
||||||
|
label: 'Skill',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Melee',
|
||||||
|
value: 'melee',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Defence',
|
||||||
|
value: 'defence',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Shooting',
|
||||||
|
value: 'shooting',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Throwing',
|
||||||
|
value: 'throwing',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Brawn',
|
||||||
|
value: 'brawn',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Toil',
|
||||||
|
value: 'toil',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Consume Alcohol',
|
||||||
|
value: 'consume-alcohol',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Endurance',
|
||||||
|
value: 'endurance',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Perception',
|
||||||
|
value: 'perception',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Dodge',
|
||||||
|
value: 'dodge',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Skullduggery',
|
||||||
|
value: 'skullduggery',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Tradecraft',
|
||||||
|
value: 'tradecraft',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Stealth',
|
||||||
|
value: 'stealth',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Athletics',
|
||||||
|
value: 'athletics',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Intuition',
|
||||||
|
value: 'intuition',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Education',
|
||||||
|
value: 'education',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Discipline',
|
||||||
|
value: 'discipline',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Animal Handling',
|
||||||
|
value: 'animal-handling',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Leadership',
|
||||||
|
value: 'leadership',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Charm',
|
||||||
|
value: 'charm',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: 'melee',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createSizeReferenceField = (): ComponentSchema =>
|
||||||
|
fields.select({
|
||||||
|
label: 'Size',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Tiny',
|
||||||
|
value: 'tiny',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Little',
|
||||||
|
value: 'little',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Small',
|
||||||
|
value: 'small',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Average',
|
||||||
|
value: 'average',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Large',
|
||||||
|
value: 'large',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Enormous',
|
||||||
|
value: 'enormous',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Monstrous',
|
||||||
|
value: 'monstrous',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: 'average',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createPsychologyReferenceField = (): ComponentSchema =>
|
||||||
|
fields.object({
|
||||||
|
type: fields.select({
|
||||||
|
label: 'Psychology Type',
|
||||||
|
defaultValue: 'animosity',
|
||||||
|
options: [
|
||||||
|
{ label: 'Animosity', value: 'animosity' },
|
||||||
|
{ label: 'Fear', value: 'fear' },
|
||||||
|
{ label: 'Frenzy', value: 'frenzy' },
|
||||||
|
{ label: 'Hatred', value: 'hatred' },
|
||||||
|
{ label: 'Prejudice', value: 'prejudice' },
|
||||||
|
{ label: 'Terror', value: 'terror' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
target: fields.text({
|
||||||
|
label: 'Target',
|
||||||
|
description: 'e.g. Elves, Undead, Chaos',
|
||||||
|
}),
|
||||||
|
rating: fields.number({
|
||||||
|
label: 'Rating',
|
||||||
|
description: 'Fear/Terror Only',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createRequirementsField = () =>
|
||||||
|
fields.blocks(
|
||||||
|
{
|
||||||
|
characteristic: {
|
||||||
|
label: 'Characteristic',
|
||||||
|
schema: fields.object({
|
||||||
|
characteristic: createCharacteristicReferenceField(),
|
||||||
|
operator: createOperatorField(),
|
||||||
|
value: fields.number({ label: 'Value', defaultValue: 3 }),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
skill: {
|
||||||
|
label: 'Skill',
|
||||||
|
schema: fields.object({
|
||||||
|
skill: createSkillReferenceField(),
|
||||||
|
operator: createOperatorField(),
|
||||||
|
value: fields.number({ label: 'Value', defaultValue: 3 }),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
label: 'Status',
|
||||||
|
schema: fields.multiselect({
|
||||||
|
label: 'Status Tier',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: 'copper',
|
||||||
|
label: 'Copper',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'silver',
|
||||||
|
label: 'Silver',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'gold',
|
||||||
|
label: 'gold',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: ['copper'],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
talent: {
|
||||||
|
label: 'Talent',
|
||||||
|
schema: fields.relationship({
|
||||||
|
label: 'Talent',
|
||||||
|
collection: 'awq_talents',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
lore: {
|
||||||
|
label: 'Lore',
|
||||||
|
schema: fields.relationship({
|
||||||
|
label: 'Lore',
|
||||||
|
collection: 'awq_lores',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ label: 'Requirements' }
|
||||||
|
);
|
||||||
|
|
||||||
|
export const createTraitsField = (): ComponentSchema =>
|
||||||
|
fields.array(
|
||||||
|
fields.object({
|
||||||
|
name: fields.text({
|
||||||
|
label: 'Trait name',
|
||||||
|
}),
|
||||||
|
description: fields.text({
|
||||||
|
label: 'Description',
|
||||||
|
multiline: true,
|
||||||
|
}),
|
||||||
|
grants: fields.blocks(
|
||||||
|
{
|
||||||
|
talent: {
|
||||||
|
label: 'Talent',
|
||||||
|
schema: fields.relationship({
|
||||||
|
label: 'Talent',
|
||||||
|
collection: 'awq_talents',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
talent_options: {
|
||||||
|
label: 'Talent Options',
|
||||||
|
schema: fields.object({
|
||||||
|
choices: fields.number({
|
||||||
|
label: 'Number to choose',
|
||||||
|
defaultValue: 1,
|
||||||
|
}),
|
||||||
|
options: fields.array(
|
||||||
|
fields.relationship({
|
||||||
|
label: 'Talent Options',
|
||||||
|
collection: 'awq_talents',
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
talent_random: {
|
||||||
|
label: 'Random Talent',
|
||||||
|
schema: fields.object({
|
||||||
|
rolls: fields.number({
|
||||||
|
label: 'Rolls',
|
||||||
|
defaultValue: 1,
|
||||||
|
}),
|
||||||
|
table: fields.array(
|
||||||
|
fields.object({
|
||||||
|
roll: fields.object({
|
||||||
|
min: fields.number({ label: 'Min' }),
|
||||||
|
max: fields.number({ label: 'Max' }),
|
||||||
|
}),
|
||||||
|
talent: fields.relationship({
|
||||||
|
label: 'Talent',
|
||||||
|
collection: 'awq_talents',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
psychology: {
|
||||||
|
label: 'Psychology',
|
||||||
|
schema: createPsychologyReferenceField(),
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
label: 'Custom Effect',
|
||||||
|
schema: fields.text({
|
||||||
|
label: 'Custom Effect',
|
||||||
|
multiline: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Trait Grants',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
label: 'Traits',
|
||||||
|
itemLabel: (props) => props.fields.name.value || 'Unnamed Trait',
|
||||||
|
}
|
||||||
|
);
|
||||||
21
src/keystatic/fields/general.ts
Normal file
21
src/keystatic/fields/general.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentSchema, fields } from '@keystatic/core';
|
||||||
|
|
||||||
|
export const createOperatorField = (): ComponentSchema =>
|
||||||
|
fields.select({
|
||||||
|
label: 'Operator',
|
||||||
|
options: [
|
||||||
|
{ label: '>=', value: 'gte' },
|
||||||
|
{ label: '>', value: 'gt' },
|
||||||
|
{ label: '=', value: 'eq' },
|
||||||
|
{ label: '<', value: 'lt' },
|
||||||
|
{ label: '<=', value: 'lte' },
|
||||||
|
],
|
||||||
|
defaultValue: 'eq',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createPathField = (defaultValue: string): ComponentSchema =>
|
||||||
|
fields.text({
|
||||||
|
label: 'Path',
|
||||||
|
description: 'Path on the website',
|
||||||
|
defaultValue: defaultValue,
|
||||||
|
});
|
||||||
@@ -39,6 +39,5 @@ export const createMetaField = (): ComponentSchema =>
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Meta Information',
|
label: 'Meta Information',
|
||||||
layout: [4, 4, 4, 12, 12, 12],
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user