programming-game
Version:
The client for programming game, an mmorpg that you interact with entirely through code.
238 lines (230 loc) • 5.23 kB
text/typescript
import { OffhandEquipmentType, WeaponType } from "./items";
import { AppliesMechanics, ClientSideUnit, StatusEffectName } from "./types";
export type WeaponSkill =
// 1h sword skills
| "doubleSlash"
// bow skills
| "pinningShot"
| "misdirectingShot"
// unarmed skills
| "combo"
| "haymaker"
| "headbutt"
// 2h sword skills
| "charge"
| "powerSlash"
// shield skills
| "shieldCharge"
// generic skills
| "threaten";
type Exchange<T extends ClientSideUnit> = T["id"];
// exchange any fields of T that extend ClientSideUnit with their 'id' field
type ClientSideUnitExchange<T> = {
[K in keyof T]: T[K] extends ClientSideUnit ? Exchange<T[K]> : T[K];
};
type T = ClientSideUnitExchange<{
to: ClientSideUnit;
}>;
type WeaponSkillOptions<S extends WeaponSkill, ClientOptions, ServerOptions> = {
client: {
skill: S;
target: ClientSideUnit;
options?: ClientOptions;
} & (ClientOptions extends undefined
? {
options?: undefined;
}
: {
options: ClientOptions;
});
server: {
skill: S;
target: string;
options?: ServerOptions;
} & (ServerOptions extends undefined
? {
options?: undefined;
}
: {
options: ServerOptions;
});
};
export type WeaponSkillSpecifics = {
misdirectingShot: WeaponSkillOptions<
"misdirectingShot",
{
to: ClientSideUnit;
},
{
to: string;
}
>;
doubleSlash: WeaponSkillOptions<"doubleSlash", undefined, undefined>;
powerSlash: WeaponSkillOptions<"powerSlash", undefined, undefined>;
pinningShot: WeaponSkillOptions<"pinningShot", undefined, undefined>;
combo: WeaponSkillOptions<"combo", undefined, undefined>;
haymaker: WeaponSkillOptions<"haymaker", undefined, undefined>;
headbutt: WeaponSkillOptions<"headbutt", undefined, undefined>;
charge: WeaponSkillOptions<"charge", undefined, undefined>;
shieldCharge: WeaponSkillOptions<"shieldCharge", undefined, undefined>;
threaten: WeaponSkillOptions<"threaten", undefined, undefined>;
};
type t = WeaponSkillSpecifics["misdirectingShot"]["server"];
export type WeaponSkillDefinition = {
id: WeaponSkill;
name: string;
tpCost: number;
weaponType?: WeaponType | OffhandEquipmentType | "unarmed";
target?: string;
minRange?: number;
maxRange?: number;
mechanics?: {
damageMultiplier?: number;
attackMultiplier?: number;
threat?: number;
};
selfEffects?: {
duration: number;
effect: StatusEffectName;
mechanics: AppliesMechanics;
};
targetEffects?: {
duration: number;
effect: StatusEffectName;
mechanics: AppliesMechanics;
};
};
export const weaponSkills: Record<WeaponSkill, WeaponSkillDefinition> = {
doubleSlash: {
id: "doubleSlash",
name: "Double Slash",
tpCost: 10,
weaponType: "oneHandedSword",
mechanics: {
damageMultiplier: 1,
attackMultiplier: 2,
},
},
misdirectingShot: {
id: "misdirectingShot",
name: "Misdirecting Shot",
tpCost: 15,
weaponType: "bow",
mechanics: {},
},
pinningShot: {
id: "pinningShot",
name: "Pinning Shot",
tpCost: 30,
weaponType: "bow",
mechanics: {
damageMultiplier: 1,
attackMultiplier: 1,
},
targetEffects: {
duration: 3_000,
effect: "pinningShot",
mechanics: {
snare: true,
},
},
},
// unarmed skills
combo: {
id: "combo",
name: "Combo",
tpCost: 30,
weaponType: "unarmed",
mechanics: {
damageMultiplier: 1,
attackMultiplier: 3,
},
},
haymaker: {
id: "haymaker",
name: "Haymaker",
tpCost: 30,
weaponType: "unarmed",
mechanics: {
damageMultiplier: 5,
attackMultiplier: 1,
},
},
headbutt: {
id: "headbutt",
name: "Headbutt",
tpCost: 40,
weaponType: "unarmed",
targetEffects: {
duration: 500,
effect: "headbutt",
mechanics: {
stun: true,
},
},
},
// two handed sword skills
charge: {
id: "charge",
name: "Charge",
tpCost: 20,
weaponType: "twoHandedSword",
maxRange: 7,
mechanics: {
damageMultiplier: 1.5,
},
selfEffects: {
duration: 3_000,
effect: "charge",
mechanics: {
movementMultiplier: 2.5,
},
},
},
powerSlash: {
id: "powerSlash",
name: "Power Slash",
tpCost: 20,
weaponType: "twoHandedSword",
mechanics: {
damageMultiplier: 2,
attackMultiplier: 1,
},
},
// shield skills
shieldCharge: {
id: "shieldCharge",
name: "Shield Charge",
tpCost: 20,
weaponType: "shield",
maxRange: 7,
mechanics: {
damageMultiplier: 1.5,
},
selfEffects: {
duration: 3_000,
effect: "shieldCharge",
mechanics: {
movementMultiplier: 2.5,
stats: {},
},
},
targetEffects: {
duration: 3_000,
effect: "stunned",
mechanics: {
stun: true,
},
},
},
threaten: {
name: "Threaten",
id: "threaten",
tpCost: 15,
weaponType: undefined,
mechanics: {
attackMultiplier: 0, // threaten does not attack, it just applies threat
threat: 30,
},
},
};