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
31 changes: 25 additions & 6 deletions src/workshop/BaseCharacter.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,43 @@
import { CharacterClassName, ICharacter, ICharacterActionDecision } from "../off-limits/ICharacter";
import { IWeapon, IItem } from "../off-limits/IWeapons";
import { IWeapon, IItem, isMeleeWeapon } from "../off-limits/IWeapons";

//todo: use this base class somehow in Characters.tsx
export class Character implements ICharacter {
name: string = '';
_className: CharacterClassName;
health: number = 5;
position: number = 10;
weapons: IWeapon[] = [];
item?: IItem;

constructor(className: CharacterClassName) {
this._className = className;
}

classname(): CharacterClassName {
throw new Error("Method not implemented.");
if (this._className)
return this._className;
else
throw new Error("Character class name not set");
}
move(){
throw new Error("Method not implemented.");
if (this.weapons.some(x => isMeleeWeapon(x))){
this.position = Math.max(this.position - 5, 1);
}
}
chooseAction(): ICharacterActionDecision{
throw new Error("Method not implemented.");
if (this.health <= 3 && this.item)
return {
use: this.item
}
else
return {
attack: this.weapons[0]
}
}
getASCIIStatus(): string {
throw new Error("Method not implemented.");
if (this.health <= 0)
return 'X';
else
return this._className.toString().charAt(0);
}
}
108 changes: 10 additions & 98 deletions src/workshop/Characters.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ICharacter, CharacterClassName, equip, ICharacterActionDecision } from '../off-limits/ICharacter';
import { IWeapon, IItem, isMeleeWeapon } from '../off-limits/IWeapons';
import { equip } from '../off-limits/ICharacter';
import { Character } from './BaseCharacter';
import {
ClericStartItem,
Expand All @@ -8,116 +7,29 @@ import {
WarriorStartItem,
} from './Weapons';

//todo: too many duplicate classes in this file!
//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 Character {
constructor(public name: string, public key: number) {
super('Warrior');
equip(WarriorStartItem, this);
}
chooseAction(): ICharacterActionDecision {
return {
attack: this.weapons[0]
}
}
getASCIIStatus(): string {
return "@";
}
}

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 Character {
constructor(public name: string, public key: number) {
super('Cleric');
equip(ClericStartItem, this);
}
chooseAction(): ICharacterActionDecision {
return {
attack: this.weapons[0]
}
}
getASCIIStatus(): string {
return "@";
}
}

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 Character {
constructor(public name: string, public key: number) {
super('Mage');
equip(MageStartItem, this);
}
move(){
this.feet.move();
}
chooseAction(): ICharacterActionDecision {
return {
attack: this.weapons[0]
}
}
getASCIIStatus(): string {
return "@";
}
}

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 Character {
constructor(public name: string, public key: number) {
super('Thief');
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);
}
}
}
}
89 changes: 77 additions & 12 deletions src/workshop/Weapons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,99 @@ import { IWeapon, IItem, IMeleeWeapon, IRangedWeapon, IConsumableItem, IEnchante
// }

// WEAPON ARMORY
// todo: add more and better weapons!
export class Club implements IMeleeWeapon {
name = 'Club';
damage = 1;
meleeRange = 1;
}

export class Staff implements IMeleeWeapon {
name = 'Staff';
damage = 3;
meleeRange = 2;
}

export class ElvishSword implements IMeleeWeapon {
name = 'Sting'; //Bilbo's glowing sword in the Hobbit
damage = 6;
meleeRange = 1;
}

export class Mace implements IMeleeWeapon {
name = 'Spikey Ball on a Stick';
damage = 7;
meleeRange = 2;
}

export class Arrow implements IWeapon {
name = 'Arrow';
damage = 3;
}

export class Bow implements IRangedWeapon<Arrow> {
name = 'Bow and Arrow';
damage: 0 = 0;
quiverSize = 10;
projectiles: Arrow[] = [new Arrow(), new Arrow(), new Arrow(), new Arrow(), new Arrow(), new Arrow(), new Arrow(), new Arrow(), new Arrow(), new Arrow()];
}

export class Bolt implements IWeapon {
name = 'Bolt';
damage = 5;
}

export class Crossbow implements IRangedWeapon<Bolt> {
name = 'Crossbow';
damage: 0 = 0;
projectiles: Bolt[] = [new Bolt(), new Bolt(), new Bolt(), new Bolt(), new Bolt(), new Bolt(), new Bolt(), new Bolt(), new Bolt(), new Bolt()];
}

// ITEM VAULT
// todo: add more and better items!
export class UselessAmulet implements IItem {
name = 'Useless Amulet';
}

export class Ring implements IEnchantedItem {
name = 'Ring';
fireDamage = 2;
partyHealthBonus = 3;
}

export class Mirror implements IEnchantedItem {
name = 'Sarcastic Magic Mirror';
fireDamage = 4;
partyHealthBonus = 1;
}

export class Book implements IEnchantedItem {
name = 'Epic Tales of Times Past';
fireDamage = 5;
partyHealthBonus = 1;
}

export class Elixer implements IConsumableItem {
name = 'Guava Nectar';
healthBonus = 2;
}

export class Food implements IConsumableItem {
name = 'Krispy Kremes';
healthBonus = 1;
}


// 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 ElvishSword();
export const ClericStartItem: IItem|undefined = new Mace();
export const MageStartItem: IItem|undefined = new Crossbow();
export const ThiefStartItem: IItem|undefined = new Bow();

// TREASURE ASSIGNMENTS
// todo: assign treasure from chests
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 Elixer(), //this will be found by the warrior
new Book(), //this will be found by the cleric
new Mirror(), //this will be found by the mage
new Food(), //this will be found by the thief
];
}