From 268a73a0afb5c26414dcd7598ef4750bf5124c41 Mon Sep 17 00:00:00 2001 From: Chris Pecson Date: Tue, 9 Nov 2021 23:46:13 +0800 Subject: [PATCH] Dragon has been slain --- src/workshop/BaseCharacter.tsx | 52 ++++++++++++---- src/workshop/Characters.tsx | 106 +++------------------------------ src/workshop/Weapons.tsx | 103 +++++++++++++++++++++++++++----- 3 files changed, 138 insertions(+), 123 deletions(-) diff --git a/src/workshop/BaseCharacter.tsx b/src/workshop/BaseCharacter.tsx index e79b5f2..bb0b962 100644 --- a/src/workshop/BaseCharacter.tsx +++ b/src/workshop/BaseCharacter.tsx @@ -1,24 +1,54 @@ -import { CharacterClassName, ICharacter, ICharacterActionDecision } from "../off-limits/ICharacter"; -import { IWeapon, IItem } from "../off-limits/IWeapons"; - +import { CharacterClassName, equip, ICharacter, ICharacterActionDecision } from "../off-limits/ICharacter"; +import { IWeapon, IItem, isMeleeWeapon, isWeapon } from "../off-limits/IWeapons"; //todo: use this base class somehow in Characters.tsx -export class Character implements ICharacter { +export class Champion implements ICharacter { name: string = ''; health: number = 5; position: number = 10; weapons: IWeapon[] = []; item?: IItem; - + + constructor( + private characterClassName: CharacterClassName, + private ascii: string, + private startItem: IItem | undefined + ) { + this.item = this.startItem; + equip(this.item, this); + } + classname(): CharacterClassName { - throw new Error("Method not implemented."); + return this.characterClassName; } - move(){ - throw new Error("Method not implemented."); + + move() { + if (this.weapons.some(x => isMeleeWeapon(x))) { + this.position = Math.max(this.position - 7, 1); + } } - chooseAction(): ICharacterActionDecision{ - throw new Error("Method not implemented."); + + chooseAction(): ICharacterActionDecision { + let action: ICharacterActionDecision; + if (this.isMinimumHealth && this.item) { + if (isWeapon(this.item)) { + action = { attack: this.item }; + } + action = { use: this.item }; + } else { + action = { attack: this.weapons[this.weapons.length - 1] }; + } + + return action; } + getASCIIStatus(): string { - throw new Error("Method not implemented."); + if (this.health > 0) { + return this.ascii; + } + return 'X'; + } + + private get isMinimumHealth() { + return this.health <= 1; } } \ No newline at end of file diff --git a/src/workshop/Characters.tsx b/src/workshop/Characters.tsx index 16ba4f4..6747cb0 100644 --- a/src/workshop/Characters.tsx +++ b/src/workshop/Characters.tsx @@ -1,6 +1,4 @@ -import { ICharacter, CharacterClassName, equip, ICharacterActionDecision } from '../off-limits/ICharacter'; -import { IWeapon, IItem, isMeleeWeapon } from '../off-limits/IWeapons'; -import { Character } from './BaseCharacter'; +import { Champion } from './BaseCharacter'; import { ClericStartItem, MageStartItem, @@ -12,112 +10,26 @@ import { //todo: customize the chooseAction() to better fight the dragon //todo: update the `getASCIIStatus` function(s) to return X when dead and a unique character per class -export class Warrior implements ICharacter { - health: number = 5; - position: number = 10; - weapons: IWeapon[] = []; - item?: IItem; - feet = new Feet(this); - classname(): CharacterClassName { - return 'Warrior'; - } - move(){ - this.feet.move(); - } +export class Warrior extends Champion { constructor(public name: string, public key: number) { - equip(WarriorStartItem, this); - } - chooseAction(): ICharacterActionDecision { - return { - attack: this.weapons[0] - } - } - getASCIIStatus(): string { - return "@"; + super('Warrior', '🦁', WarriorStartItem) } } -export class Cleric implements ICharacter{ - health: number = 5; - position: number = 10; - weapons: IWeapon[] = []; - item?: IItem; - feet = new Feet(this); - classname(): CharacterClassName { - return 'Cleric'; - } - move(){ - this.feet.move(); - } +export class Cleric extends Champion { constructor(public name: string, public key: number) { - equip(ClericStartItem, this); - } - chooseAction(): ICharacterActionDecision { - return { - attack: this.weapons[0] - } - } - getASCIIStatus(): string { - return "@"; + super('Cleric', '🐸', ClericStartItem) } } -export class Mage implements ICharacter { - health: number = 5; - position: number = 10; - weapons: IWeapon[] = []; - item?: IItem; - feet = new Feet(this); - classname(): CharacterClassName { - return 'Mage'; - } +export class Mage extends Champion { constructor(public name: string, public key: number) { - equip(MageStartItem, this); - } - move(){ - this.feet.move(); - } - chooseAction(): ICharacterActionDecision { - return { - attack: this.weapons[0] - } - } - getASCIIStatus(): string { - return "@"; + super('Mage', '🐱', MageStartItem) } } -export class Thief implements ICharacter { - health: number = 5; - position: number = 10; - weapons: IWeapon[] = []; - item?: IItem; - feet = new Feet(this); - move(){ - this.feet.move(); - } - classname(): CharacterClassName { - return 'Thief'; - } +export class Thief extends Champion { constructor(public name: string, public key: number) { - equip(ThiefStartItem, this); - } - chooseAction(): ICharacterActionDecision { - return { - attack: this.weapons[0] - } - } - getASCIIStatus(): string { - return "@"; - } -} - -//todo: something about this class is code smell... -export class Feet{ - constructor(private character: ICharacter){} - move(){ - if (this.character.weapons.some(x => isMeleeWeapon(x))){ - this.character.position = Math.max(this.character.position - 5, 1); - } + super('Thief', '🦊', ThiefStartItem); } } diff --git a/src/workshop/Weapons.tsx b/src/workshop/Weapons.tsx index 05e4f63..645a9b8 100644 --- a/src/workshop/Weapons.tsx +++ b/src/workshop/Weapons.tsx @@ -1,4 +1,4 @@ -import { IWeapon, IItem, IMeleeWeapon, IRangedWeapon, IConsumableItem, IEnchantedItem } from "../off-limits/IWeapons"; +import { IItem, IMeleeWeapon, IRangedWeapon, IConsumableItem, IEnchantedItem } from "../off-limits/IWeapons"; // INTERFACE QUICK REFERENCE // export interface IItem { @@ -24,10 +24,84 @@ import { IWeapon, IItem, IMeleeWeapon, IRangedWeapon, IConsumableItem, IEnchante // WEAPON ARMORY // todo: add more and better weapons! -export class Club implements IMeleeWeapon { - name = 'Club'; - damage = 1; +export class Mana implements IEnchantedItem { + fireDamage = 5; + damage = 6; + name = 'Mana'; +} +export class IceAmmo implements IEnchantedItem { + fireDamage = 10; + damage = 6; + name = 'Ice Ammo'; +} +export class MoonstoneRenewer implements IConsumableItem { + healthBonus = 1; + name: string = 'Moonstone Renewer'; +} +export class BiscuitOfEverlastingWill implements IConsumableItem { + healthBonus = 2; + name: string = 'Biscuit of Everlasting Will'; +} +export class Redemption implements IConsumableItem { + healthBonus = 2; + name: string = 'Redemption'; +} +export class LongSword implements IMeleeWeapon { + name = 'Long Sword'; meleeRange = 1; + damage = 6; +} +export class InfinityEdge implements IMeleeWeapon { + name = 'Infinity Edge'; + meleeRange = 3 + damage = 9; +} +export class BloodThirster implements IMeleeWeapon { + name = 'Blood Thirster'; + meleeRange = 2 + damage = 8; +} +export class MikaelsBlessing implements IEnchantedItem { + name: string; + fireDamage: number; + partyHealthBonus: number; + + constructor() { + this.fireDamage = 3; + this.partyHealthBonus = 10; + this.name = 'Mikael\'s Blessing'; + } +} +export class StarCaster implements IEnchantedItem { + name: string; + fireDamage: number; + partyHealthBonus: number; + + constructor() { + this.fireDamage = 3; + this.partyHealthBonus = 2; + this.name = 'Star Caster'; + } +} + +export class BlastingWand implements IRangedWeapon { + name = 'Blasting Wand'; + projectiles: IceAmmo[] = []; + damage: 0 = 0; + + constructor() { + this.projectiles = new Array(3).fill(new Mana()); + } +} + +export class LichBane implements IRangedWeapon { + name = 'Lich Bane'; + projectiles: IceAmmo[] = []; + damage: 0 = 0; + + constructor() { + this.projectiles = new Array(10).fill(new IceAmmo()); + } } // ITEM VAULT @@ -36,21 +110,20 @@ export class UselessAmulet implements IItem { name = 'Useless Amulet'; } - // ITEM ASSIGNMENTS // todo: assign starting items -export const WarriorStartItem: IItem|undefined = new Club(); -export const ClericStartItem: IItem|undefined = new Club(); -export const MageStartItem: IItem|undefined = undefined; -export const ThiefStartItem: IItem|undefined = new Club(); +export const WarriorStartItem: IItem|undefined = new MoonstoneRenewer(); +export const ClericStartItem: IItem|undefined = new BiscuitOfEverlastingWill(); +export const MageStartItem: IItem|undefined = new Redemption(); +export const ThiefStartItem: IItem|undefined = new MoonstoneRenewer(); // TREASURE ASSIGNMENTS // todo: assign treasure from chests -export function GetItemsInTreasureChests(): IItem[]{ +export function GetItemsInTreasureChests(): IItem[] { return [ - new UselessAmulet(), //this will be found by the warrior - new UselessAmulet(), //this will be found by the cleric - new UselessAmulet(), //this will be found by the mage - new UselessAmulet(), //this will be found by the thief + new InfinityEdge(), //this will be found by the warrior + new StarCaster(), //this will be found by the cleric + new LichBane(), //this will be found by the mage + new BloodThirster(), //this will be found by the thief ]; -} +} \ No newline at end of file