Added pinned effect, to prevent ships from moving
This commit is contained in:
parent
f7d0d066c0
commit
7d586d5a2b
1
TODO.md
1
TODO.md
|
@ -75,7 +75,6 @@ Ships models and actions
|
||||||
* Add damage on collisions (when two ships are moved to the same place)
|
* Add damage on collisions (when two ships are moved to the same place)
|
||||||
* Add hull points to drones and make them take area damage
|
* Add hull points to drones and make them take area damage
|
||||||
* Allow to customize effects based on whether a target is enemy, allied or self
|
* Allow to customize effects based on whether a target is enemy, allied or self
|
||||||
* Add anchored effect (cannot be moved)
|
|
||||||
* Add a reflect damage effect
|
* Add a reflect damage effect
|
||||||
* Add untargettable effect (can only be targetted with area effects)
|
* Add untargettable effect (can only be targetted with area effects)
|
||||||
* Add damage modifier (to change the options of incoming damage or outgoing damage)
|
* Add damage modifier (to change the options of incoming damage or outgoing damage)
|
||||||
|
|
BIN
data/stage2/image/action/pin.png
Normal file
BIN
data/stage2/image/action/pin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
data/stage2/image/action/shieldbash.png
Normal file
BIN
data/stage2/image/action/shieldbash.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
File diff suppressed because it is too large
Load diff
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 165 KiB |
|
@ -136,15 +136,15 @@ module TK.SpaceTac.Specs {
|
||||||
|
|
||||||
test.case("lists active effects", check => {
|
test.case("lists active effects", check => {
|
||||||
let ship = new Ship();
|
let ship = new Ship();
|
||||||
check.equals(imaterialize(ship.ieffects()), []);
|
check.equals(ship.getEffects(), []);
|
||||||
|
|
||||||
let effect1 = new AttributeEffect("evasion", 4);
|
let effect1 = new AttributeEffect("evasion", 4);
|
||||||
check.patch(ship.model, "getEffects", () => [effect1]);
|
check.patch(ship.model, "getEffects", () => [effect1]);
|
||||||
check.equals(imaterialize(ship.ieffects()), [effect1]);
|
check.equals(ship.getEffects(), [effect1]);
|
||||||
|
|
||||||
let effect2 = new AttributeLimitEffect("evasion", 2);
|
let effect2 = new AttributeLimitEffect("evasion", 2);
|
||||||
ship.active_effects.add(new StickyEffect(effect2, 4));
|
ship.active_effects.add(new StickyEffect(effect2, 4));
|
||||||
check.equals(imaterialize(ship.ieffects()), [effect1, effect2]);
|
check.equals(ship.getEffects(), [effect1, effect2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.case("gets a textual description of an attribute", check => {
|
test.case("gets a textual description of an attribute", check => {
|
||||||
|
|
|
@ -331,7 +331,7 @@ module TK.SpaceTac {
|
||||||
keys(this.attributes).forEach(attr => this.attributes[attr].reset());
|
keys(this.attributes).forEach(attr => this.attributes[attr].reset());
|
||||||
|
|
||||||
// Apply attribute effects
|
// Apply attribute effects
|
||||||
iforeach(this.ieffects(), effect => {
|
this.getEffects().forEach(effect => {
|
||||||
if (effect instanceof AttributeEffect) {
|
if (effect instanceof AttributeEffect) {
|
||||||
this.attributes[effect.attrcode].addModifier(effect.value);
|
this.attributes[effect.attrcode].addModifier(effect.value);
|
||||||
} else if (effect instanceof AttributeMultiplyEffect) {
|
} else if (effect instanceof AttributeMultiplyEffect) {
|
||||||
|
@ -371,10 +371,9 @@ module TK.SpaceTac {
|
||||||
*
|
*
|
||||||
* This combines the permanent effects from ship model, with sticky and area effects.
|
* This combines the permanent effects from ship model, with sticky and area effects.
|
||||||
*/
|
*/
|
||||||
ieffects(): Iterator<BaseEffect> {
|
getEffects(): BaseEffect[] {
|
||||||
return ichain(
|
return this.getModelEffects().concat(
|
||||||
iarray(this.getModelEffects()),
|
this.active_effects.list().map(effect => (effect instanceof StickyEffect) ? effect.base : effect)
|
||||||
imap(this.active_effects.iterator(), effect => (effect instanceof StickyEffect) ? effect.base : effect)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,9 @@ module TK.SpaceTac {
|
||||||
// Action is overheated
|
// Action is overheated
|
||||||
OVERHEATED = "Overheated",
|
OVERHEATED = "Overheated",
|
||||||
// Vigilance is activated
|
// Vigilance is activated
|
||||||
VIGILANCE = "In vigilance"
|
VIGILANCE = "In vigilance",
|
||||||
|
// Ship is pinned
|
||||||
|
PINNED = "Pinned",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -67,6 +67,11 @@ module TK.SpaceTac {
|
||||||
return ActionUnavailability.VIGILANCE;
|
return ActionUnavailability.VIGILANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check pinned status
|
||||||
|
if (any(ship.getEffects(), effect => effect instanceof PinnedEffect)) {
|
||||||
|
return ActionUnavailability.PINNED;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ module TK.SpaceTac {
|
||||||
})
|
})
|
||||||
|
|
||||||
test.case("builds a textual description", check => {
|
test.case("builds a textual description", check => {
|
||||||
check.equals(new CooldownEffect(0, 0).getDescription(), "Full cooling (all equipments)");
|
check.equals(new CooldownEffect(0, 0).getDescription(), "full cooling (all equipments)");
|
||||||
check.equals(new CooldownEffect(1, 1).getDescription(), "1 cooling (1 equipment)");
|
check.equals(new CooldownEffect(1, 1).getDescription(), "1 cooling (1 equipment)");
|
||||||
check.equals(new CooldownEffect(2, 2).getDescription(), "2 cooling (2 equipments)");
|
check.equals(new CooldownEffect(2, 2).getDescription(), "2 cooling (2 equipments)");
|
||||||
})
|
})
|
||||||
|
|
|
@ -34,7 +34,7 @@ module TK.SpaceTac {
|
||||||
}
|
}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
return `${this.cooling ? this.cooling : "Full"} cooling (${this.maxcount ? this.maxcount : "all"} equipment${this.maxcount != 1 ? "s" : ""})`;
|
return `${this.cooling ? this.cooling : "full"} cooling (${this.maxcount ? this.maxcount : "all"} equipment${this.maxcount != 1 ? "s" : ""})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
62
src/core/effects/PinnedEffect.spec.ts
Normal file
62
src/core/effects/PinnedEffect.spec.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
module TK.SpaceTac.Specs {
|
||||||
|
testing("PinnedEffect", test => {
|
||||||
|
test.case("shows a textual description", check => {
|
||||||
|
check.equals(new PinnedEffect().getDescription(), "pinned");
|
||||||
|
check.equals(new PinnedEffect(true).getDescription(), "anchored");
|
||||||
|
});
|
||||||
|
|
||||||
|
test.case("prevents a ship from using its engine", check => {
|
||||||
|
let ship = new Ship();
|
||||||
|
TestTools.setShipModel(ship, 1, 1, 1);
|
||||||
|
|
||||||
|
let engine = TestTools.addEngine(ship, 100);
|
||||||
|
check.equals(engine.checkCannotBeApplied(ship), null, "engine can initially be used");
|
||||||
|
|
||||||
|
let cases: [string, BaseEffect][] = [
|
||||||
|
["soft pin", new PinnedEffect()],
|
||||||
|
["hard pin", new PinnedEffect(true)],
|
||||||
|
["sticky soft pin", new StickyEffect(new PinnedEffect())],
|
||||||
|
["sticky hard pin", new StickyEffect(new PinnedEffect(true))],
|
||||||
|
];
|
||||||
|
cases.forEach(([title, effect]) => {
|
||||||
|
check.in(title, check => {
|
||||||
|
ship.active_effects.add(effect);
|
||||||
|
check.equals(engine.checkCannotBeApplied(ship), ActionUnavailability.PINNED, "engine cannot be used when pinned");
|
||||||
|
ship.active_effects.remove(effect);
|
||||||
|
check.equals(engine.checkCannotBeApplied(ship), null, "engine can be used again");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.case("prevents a ship from being moved by another effect, in hard mode", check => {
|
||||||
|
let battle = TestTools.createBattle();
|
||||||
|
let ship = battle.fleets[0].ships[0];
|
||||||
|
let enemy = battle.fleets[1].ships[0];
|
||||||
|
enemy.setArenaPosition(0, 500);
|
||||||
|
|
||||||
|
let effect = new RepelEffect(100);
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 1, "ship can initially be moved");
|
||||||
|
|
||||||
|
check.in("soft pin", check => {
|
||||||
|
let pin = enemy.active_effects.add(new PinnedEffect());
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 1, "ship can still be moved");
|
||||||
|
enemy.active_effects.remove(pin);
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 1, "ship can still be moved");
|
||||||
|
});
|
||||||
|
|
||||||
|
check.in("hard pin", check => {
|
||||||
|
let pin = enemy.active_effects.add(new PinnedEffect(true));
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 0, "ship cannot be moved");
|
||||||
|
enemy.active_effects.remove(pin);
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 1, "ship can be moved again");
|
||||||
|
});
|
||||||
|
|
||||||
|
check.in("sticky hard pin", check => {
|
||||||
|
let pin = enemy.active_effects.add(new StickyEffect(new PinnedEffect(true)));
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 0, "ship cannot be moved");
|
||||||
|
enemy.active_effects.remove(pin);
|
||||||
|
check.equals(effect.getOnDiffs(enemy, ship).length, 1, "ship can be moved again");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
22
src/core/effects/PinnedEffect.ts
Normal file
22
src/core/effects/PinnedEffect.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/// <reference path="BaseEffect.ts"/>
|
||||||
|
|
||||||
|
module TK.SpaceTac {
|
||||||
|
/**
|
||||||
|
* Pin a ship in space, preventing him from moving using its engine
|
||||||
|
*
|
||||||
|
* If hard pinned, the ship also may not be moved by another MoveEffect
|
||||||
|
*/
|
||||||
|
export class PinnedEffect extends BaseEffect {
|
||||||
|
constructor(readonly hard = false) {
|
||||||
|
super("pinned");
|
||||||
|
}
|
||||||
|
|
||||||
|
isBeneficial(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDescription(): string {
|
||||||
|
return this.hard ? "anchored" : "pinned";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ module TK.SpaceTac {
|
||||||
}
|
}
|
||||||
|
|
||||||
getOnDiffs(ship: Ship, source: Ship | Drone): BaseBattleDiff[] {
|
getOnDiffs(ship: Ship, source: Ship | Drone): BaseBattleDiff[] {
|
||||||
if (ship != source) {
|
if (ship != source && !any(ship.getEffects(), effect => effect instanceof PinnedEffect && effect.hard)) {
|
||||||
let angle = arenaAngle(source.location, ship.location);
|
let angle = arenaAngle(source.location, ship.location);
|
||||||
let destination = new ArenaLocation(ship.arena_x + Math.cos(angle) * this.value, ship.arena_y + Math.sin(angle) * this.value);
|
let destination = new ArenaLocation(ship.arena_x + Math.cos(angle) * this.value, ship.arena_y + Math.sin(angle) * this.value);
|
||||||
let exclusions = ExclusionAreas.fromShip(ship);
|
let exclusions = ExclusionAreas.fromShip(ship);
|
||||||
|
|
|
@ -12,7 +12,7 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Main Engine", {
|
||||||
distance_per_power: 420,
|
distance_per_power: 420,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,12 +23,19 @@ module TK.SpaceTac {
|
||||||
}, "powerdepleter");
|
}, "powerdepleter");
|
||||||
depleter.configureCooldown(1, 1);
|
depleter.configureCooldown(1, 1);
|
||||||
|
|
||||||
let gatling = new TriggerAction("Shield Basher", {
|
let shield_basher = new TriggerAction("Shield Basher", {
|
||||||
effects: [new DamageEffect(2, DamageEffectMode.SHIELD_ONLY, false)],
|
effects: [new DamageEffect(2, DamageEffectMode.SHIELD_ONLY, false)],
|
||||||
power: 3,
|
power: 3,
|
||||||
range: 300,
|
range: 300,
|
||||||
}, "submunitionmissile");
|
}, "shieldbash");
|
||||||
gatling.configureCooldown(2, 1);
|
shield_basher.configureCooldown(2, 1);
|
||||||
|
|
||||||
|
let engine_hijack = new TriggerAction("Engine Hijacking", {
|
||||||
|
effects: [new StickyEffect(new PinnedEffect(), 2)],
|
||||||
|
power: 2,
|
||||||
|
range: 400,
|
||||||
|
}, "pin");
|
||||||
|
engine_hijack.configureCooldown(1, 2);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -42,16 +49,20 @@ module TK.SpaceTac {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Main Engine",
|
code: engine.name,
|
||||||
actions: [engine]
|
actions: [engine]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Power Depleter",
|
code: depleter.name,
|
||||||
actions: [depleter]
|
actions: [depleter]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Gatling Gun",
|
code: shield_basher.name,
|
||||||
actions: [gatling]
|
actions: [shield_basher]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: engine_hijack.name,
|
||||||
|
actions: [engine_hijack]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue