Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 41 additions & 11 deletions src/workshop/BaseCharacter.tsx
Original file line number Diff line number Diff line change
@@ -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;
}
}
106 changes: 9 additions & 97 deletions src/workshop/Characters.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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);
}
}
103 changes: 88 additions & 15 deletions src/workshop/Weapons.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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<IceAmmo> {
name = 'Blasting Wand';
projectiles: IceAmmo[] = [];
damage: 0 = 0;

constructor() {
this.projectiles = new Array(3).fill(new Mana());
}
}

export class LichBane implements IRangedWeapon<IceAmmo> {
name = 'Lich Bane';
projectiles: IceAmmo[] = [];
damage: 0 = 0;

constructor() {
this.projectiles = new Array(10).fill(new IceAmmo());
}
}

// ITEM VAULT
Expand All @@ -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
];
}
}