From 5f1913da6dce72d20669893da8e53233f845fb01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Thu, 22 Jan 2015 01:00:00 +0100 Subject: [PATCH] Added permanent effects on attributes for equipement --- src/scripts/game/Attribute.ts | 14 ++++- src/scripts/game/AttributeCollection.ts | 57 +++++++++++++++++++ src/scripts/game/Equipment.ts | 8 +++ src/scripts/game/Ship.ts | 48 +++++++++++++++- .../game/effects/AttributeMaxEffect.ts | 22 +++++++ src/scripts/game/effects/BaseEffect.ts | 15 +++++ src/scripts/game/specs/Attribute.spec.ts | 29 ++++++++++ .../game/specs/AttributeCollection.spec.ts | 29 ++++++++++ src/scripts/game/specs/Ship.spec.ts | 19 +++++++ 9 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 src/scripts/game/AttributeCollection.ts create mode 100644 src/scripts/game/effects/AttributeMaxEffect.ts create mode 100644 src/scripts/game/effects/BaseEffect.ts create mode 100644 src/scripts/game/specs/AttributeCollection.spec.ts diff --git a/src/scripts/game/Attribute.ts b/src/scripts/game/Attribute.ts index 11af208..1cd859c 100644 --- a/src/scripts/game/Attribute.ts +++ b/src/scripts/game/Attribute.ts @@ -39,15 +39,25 @@ module SpaceTac.Game { current: number; // Create an attribute - constructor(code: AttributeCode, maximal: number = 1, current: number = 0) { + constructor(code: AttributeCode = AttributeCode.Misc, maximal: number = null, current: number = 0) { this.code = code; this.maximal = maximal; this.current = current; } + // Iterator over each code + static forEachCode(callback: (code: AttributeCode) => void) { + for (var val in AttributeCode) { + if (!isNaN(val)) { + callback(parseInt(val, 10)); + } + } + } + // Set the maximal value setMaximal(value: number): void { this.maximal = value; + this.fix(); } // Set an absolute value @@ -70,7 +80,7 @@ module SpaceTac.Game { // Fix the value to remain lower than maximal, and positive private fix(): void { - if (this.current > this.maximal) { + if (this.maximal !== null && this.current > this.maximal) { this.current = this.maximal; } if (this.current < 0.0001) { diff --git a/src/scripts/game/AttributeCollection.ts b/src/scripts/game/AttributeCollection.ts new file mode 100644 index 0000000..87ada05 --- /dev/null +++ b/src/scripts/game/AttributeCollection.ts @@ -0,0 +1,57 @@ +module SpaceTac.Game { + "use strict"; + + // Collection of several attributes + export class AttributeCollection { + // Attributes + private attributes: Attribute[]; + + // Base constructor + constructor() { + this.attributes = []; + } + + // Get or create an attribute by its code + getRawAttr(code: AttributeCode): Attribute { + var attr = this.attributes[code]; + if (!attr) { + attr = new Attribute(code); + this.attributes[code] = attr; + } + return attr; + } + + // Get an attribute value + getValue(attrcode: AttributeCode): number { + var attr = this.getRawAttr(attrcode); + return attr.current; + } + + // Set an attribute value + setValue(attrcode: AttributeCode, value: number): number { + var attr = this.getRawAttr(attrcode); + attr.set(value); + return attr.current; + } + + // Add an offset to an attribute value + addValue(attrcode: AttributeCode, offset: number): number { + var attr = this.getRawAttr(attrcode); + attr.add(offset); + return attr.current; + } + + // Get an attribute maximum + getMaximum(attrcode: AttributeCode): number { + var attr = this.getRawAttr(attrcode); + return attr.maximal; + } + + // Set an attribute maximum + setMaximum(attrcode: AttributeCode, value: number): number { + var attr = this.getRawAttr(attrcode); + attr.setMaximal(value); + return attr.maximal; + } + } +} diff --git a/src/scripts/game/Equipment.ts b/src/scripts/game/Equipment.ts index ba0fd07..7f32c10 100644 --- a/src/scripts/game/Equipment.ts +++ b/src/scripts/game/Equipment.ts @@ -26,5 +26,13 @@ module SpaceTac.Game { // Action associated with this equipment action: BaseAction; + + // Permanent effects + permanent_effects: BaseEffect[]; + + // Basic constructor + constructor() { + this.permanent_effects = []; + } } } diff --git a/src/scripts/game/Ship.ts b/src/scripts/game/Ship.ts index 1711da6..f181328 100644 --- a/src/scripts/game/Ship.ts +++ b/src/scripts/game/Ship.ts @@ -46,14 +46,18 @@ module SpaceTac.Game { // List of slots, able to contain equipment slots: Slot[]; + // Collection of available attributes + attributes: AttributeCollection; + // Create a new ship inside a fleet constructor(fleet: Fleet = null, name: string = null) { + this.attributes = new AttributeCollection(); this.fleet = fleet; this.name = name; this.initiative_level = 1; - this.ap_current = new Attribute(AttributeCode.AP); - this.ap_initial = new Attribute(AttributeCode.AP_Initial); - this.ap_recover = new Attribute(AttributeCode.AP_Recovery); + this.ap_current = this.newAttribute(AttributeCode.AP); + this.ap_initial = this.newAttribute(AttributeCode.AP_Initial); + this.ap_recover = this.newAttribute(AttributeCode.AP_Recovery); this.movement_cost = 0.1; this.slots = []; @@ -62,6 +66,11 @@ module SpaceTac.Game { } } + // Create and register an attribute + newAttribute(code: AttributeCode): Attribute { + return this.attributes.getRawAttr(code); + } + // Set position in the arena // This does not consumes action points setArenaPosition(x: number, y: number) { @@ -207,5 +216,38 @@ module SpaceTac.Game { this.slots.push(result); return result; } + + // Update attributes, taking into account attached equipment and active effects + updateAttributes(): void { + // TODO Something more generic + + // Compute new maximal values for all attributes + var new_attrs = new AttributeCollection(); + this.collectEffects("attrmax").forEach((effect: AttributeMaxEffect) => { + new_attrs.addValue(effect.attrcode, effect.value); + }); + var old_attrs = this.attributes; + Attribute.forEachCode((code: AttributeCode) => { + old_attrs.setMaximum(code, new_attrs.getValue(code)); + }); + console.log(old_attrs, new_attrs); + } + + // Collect all effects to apply for updateAttributes + private collectEffects(code: string = null): BaseEffect[] { + var result: BaseEffect[] = []; + + this.slots.forEach((slot: Slot) => { + if (slot.attached) { + slot.attached.permanent_effects.forEach((effect: BaseEffect) => { + if (effect.code === code) { + result.push(effect); + } + }); + } + }); + + return result; + } } } diff --git a/src/scripts/game/effects/AttributeMaxEffect.ts b/src/scripts/game/effects/AttributeMaxEffect.ts new file mode 100644 index 0000000..5209e6a --- /dev/null +++ b/src/scripts/game/effects/AttributeMaxEffect.ts @@ -0,0 +1,22 @@ +/// + +module SpaceTac.Game { + "use strict"; + + // Effect on attribute maximum + // Typically, these effects are summed up to define an attribute maximum + export class AttributeMaxEffect extends BaseEffect { + // Affected attribute + attrcode: AttributeCode; + + // Value to add to the maximum + value: number; + + constructor(attrcode: AttributeCode, value: number) { + super("attrmax"); + + this.attrcode = attrcode; + this.value = value; + } + } +} diff --git a/src/scripts/game/effects/BaseEffect.ts b/src/scripts/game/effects/BaseEffect.ts new file mode 100644 index 0000000..0bb176c --- /dev/null +++ b/src/scripts/game/effects/BaseEffect.ts @@ -0,0 +1,15 @@ +module SpaceTac.Game { + "use strict"; + + // Base class for effects of actions + // Effects can be permanent or temporary (for a number of turns) + export class BaseEffect { + // Identifier code for the type of effect + code: string; + + // Base constructor + constructor(code: string) { + this.code = code; + } + } +} diff --git a/src/scripts/game/specs/Attribute.spec.ts b/src/scripts/game/specs/Attribute.spec.ts index dae0a0c..f15a5db 100644 --- a/src/scripts/game/specs/Attribute.spec.ts +++ b/src/scripts/game/specs/Attribute.spec.ts @@ -4,6 +4,29 @@ module SpaceTac.Game { "use strict"; describe("Attribute", function () { + it("is initially not limited", function () { + var attr = new Attribute(); + + attr.set(8888888); + expect(attr.current).toBe(8888888); + }); + + it("enumerates codes", function () { + var result = []; + Attribute.forEachCode((code: AttributeCode) => { + result.push(code); + }); + expect(result).toEqual([ + AttributeCode.Initiative, + AttributeCode.Hull, + AttributeCode.Shield, + AttributeCode.AP, + AttributeCode.AP_Recovery, + AttributeCode.AP_Initial, + AttributeCode.Misc + ]); + }); + it("applies minimal and maximal value", function () { var attr = new Attribute(AttributeCode.Misc, 100, 50); expect(attr.current).toBe(50); @@ -28,6 +51,12 @@ module SpaceTac.Game { attr.set(105); expect(attr.current).toBe(100); + + attr.setMaximal(50); + expect(attr.current).toBe(50); + + attr.setMaximal(80); + expect(attr.current).toBe(50); }); it("tells if value changed", function () { diff --git a/src/scripts/game/specs/AttributeCollection.spec.ts b/src/scripts/game/specs/AttributeCollection.spec.ts new file mode 100644 index 0000000..bb9a88e --- /dev/null +++ b/src/scripts/game/specs/AttributeCollection.spec.ts @@ -0,0 +1,29 @@ +/// + +module SpaceTac.Game { + "use strict"; + + describe("AttributeCollection", function () { + it("sets and gets an attribute value", function () { + var coll = new AttributeCollection(); + + coll.setValue(AttributeCode.Initiative, 5); + expect(coll.getValue(AttributeCode.Initiative)).toBe(5); + + expect(coll.getValue(AttributeCode.Hull)).toBe(0); + coll.setValue(AttributeCode.Hull, 2); + expect(coll.getValue(AttributeCode.Hull)).toBe(2); + }); + + it("sets and gets an attribute maximal", function () { + var coll = new AttributeCollection(); + + coll.setMaximum(AttributeCode.Initiative, 5); + expect(coll.getMaximum(AttributeCode.Initiative)).toBe(5); + + expect(coll.getMaximum(AttributeCode.Hull)).toBe(null); + coll.setMaximum(AttributeCode.Hull, 2); + expect(coll.getMaximum(AttributeCode.Hull)).toBe(2); + }); + }); +} diff --git a/src/scripts/game/specs/Ship.spec.ts b/src/scripts/game/specs/Ship.spec.ts index dea63ff..101586a 100644 --- a/src/scripts/game/specs/Ship.spec.ts +++ b/src/scripts/game/specs/Ship.spec.ts @@ -57,5 +57,24 @@ module SpaceTac.Game { expect(actions[0].code).toEqual("move"); expect(actions[1].code).toEqual("endturn"); }); + + it("applies permanent effects of equipments on attributes", function () { + var ship = new Ship(null, "Test"); + var slot: Slot; + var equipment: Equipment; + + slot = ship.addSlot(SlotType.Power); + equipment = new Equipment(); + equipment.permanent_effects.push(new AttributeMaxEffect(AttributeCode.AP, 4)); + slot.attach(equipment); + + slot = ship.addSlot(SlotType.Power); + equipment = new Equipment(); + equipment.permanent_effects.push(new AttributeMaxEffect(AttributeCode.AP, 5)); + slot.attach(equipment); + + ship.updateAttributes(); + expect(ship.ap_current.maximal).toBe(9); + }); }); }