Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creature delay bugfix and refactor, closes #2158 #2275 #2426

Merged
merged 11 commits into from
Jul 18, 2023
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@babel/preset-typescript": "^7.21.4",
"@types/jest": "^29.5.0",
"@types/jquery": "^3.5.9",
"@types/underscore": "^1.11.5",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.1",
"babel-jest": "^29.5.0",
Expand Down
162 changes: 157 additions & 5 deletions src/__tests__/creature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { jest, expect, describe, test, beforeEach } from '@jest/globals';

describe('Creature', () => {
describe('creature.id', () => {
let game;
let game: Game;
// @ts-ignore
beforeEach(() => (game = getGameMock()));

test('"materialized" creatures are automatically assigned separate ids', () => {
Expand Down Expand Up @@ -46,6 +47,151 @@ describe('Creature', () => {
expect(game.creatures.filter((c) => c)[0]).toStrictEqual(creatureNotTemp);
});
});

describe('Creature materializes in which queue?', () => {
test('a new Creature normally materializes in next queue, not current', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
expect(creature.isInCurrentQueue).toBe(false);
expect(creature.isInNextQueue).toBe(true);
});
test('a new Priest materializes in current queue', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
obj.type = '--';
// @ts-ignore
const creature = new Creature(obj, game);
expect(creature.isDarkPriest()).toBe(true);
expect(creature.isInCurrentQueue).toBe(true);
expect(creature.isInNextQueue).toBe(true);
});
test('a creature without materialization sickness materializes in current queue', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
obj.materializationSickness = false;
// @ts-ignore
const creature = new Creature(obj, game);
expect(creature.isDarkPriest()).toBe(false);
expect(creature.isInCurrentQueue).toBe(true);
expect(creature.isInNextQueue).toBe(true);
});
});

describe('creature.canWait()', () => {
test('a new Creature can wait', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
creature.activate();
expect(creature.canWait).toBe(true);
});
test('a waiting Creature cannot wait', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
creature.activate();
creature.wait();
expect(creature.canWait).toBe(false);
});
test('a hindered Creature cannot wait', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
creature.activate();
creature.hinder();
expect(creature.canWait).toBe(false);
});
});

describe('creature.wait()', () => {
test('a creature that has waited is delayed', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
creature.activate();
expect(creature.isDelayed).toBe(false);
expect(creature.canWait).toBe(true);
creature.wait();
expect(creature.isDelayed).toBe(true);
});
test('when a round is over, a waited creature is no longer delayed', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
creature.activate();
expect(creature.isDelayed).toBe(false);
expect(creature.canWait).toBe(true);
creature.wait();
expect(creature.isWaiting).toBe(true);
creature.deactivate('turn-end');
expect(creature.isDelayed).toBe(false);
});
});

describe('creature.hinder()', () => {
test('a hindered creature is delayed', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
expect(creature.isHindered).toBe(false);
expect(creature.isDelayed).toBe(false);
creature.hinder();
expect(creature.isHindered).toBe(true);
expect(creature.isDelayed).toBe(true);
});
test('a creature can be hindered', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
expect(creature.isHindered).toBe(false);
creature.hinder();
expect(creature.isHindered).toBe(true);
});
test('a creature whose turn is over, who is then hindered, will be delayed the next round', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
creature.displayHealthStats = () => undefined;

creature.activate();
creature.deactivate('turn-end');
expect(creature.isHindered).toBe(false);
creature.hinder();
expect(creature.isHindered).toBe(true);
creature.activate();
expect(creature.isHindered).toBe(true);
creature.deactivate('turn-end');
expect(creature.isHindered).toBe(false);
});
test('a creature whose turn is not over, who is then hindered, will not be delayed the next round from that hinder()', () => {
const game = getGameMock();
const obj = getCreatureObjMock();
// @ts-ignore
const creature = new Creature(obj, game);
expect(creature.isWaiting).toBe(false);
expect(creature.isDelayed).toBe(false);
creature.hinder();
expect(creature.isWaiting).toBe(false);
expect(creature.isHindered).toBe(true);
expect(creature.isDelayed).toBe(true);
creature.activate();
creature.deactivate('turn-end');
expect(creature.isWaiting).toBe(false);
expect(creature.isHindered).toBe(false);
expect(creature.isDelayed).toBe(false);
});
});
});

jest.mock('../ability');
Expand All @@ -71,9 +217,11 @@ const getCreatureObjMock = () => {
return {
stats: {
health: 10,
movement: 10,
},
temp: false,
team: 0,
materializationSickness: true,
type: getRandomString(5),
display: {
'offset-x': true,
Expand All @@ -100,15 +248,14 @@ const getHexesMock = () => {
};

import data from '../data/units.json';
import Game from '../game';

const getGameMock = () => {
const self = {
turn: 0,
creatures: [],
players: [],
queue: {
addByInitiative: jest.fn(),
removeTempCreature: jest.fn(),
},
queue: { update: jest.fn() },
updateQueueDisplay: jest.fn(),
grid: {
orderCreatureZ: jest.fn(),
Expand All @@ -130,6 +277,11 @@ const getGameMock = () => {
},
},
plasma_amount: 10,
onReset: jest.fn(),
onStartPhase: jest.fn(),
onEndPhase: jest.fn(),
log: jest.fn(),
onHeal: jest.fn(),
};
self.players = [getPlayerMock(), getPlayerMock()];
return self;
Expand Down
8 changes: 0 additions & 8 deletions src/abilities/Dark-Priest.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,6 @@ export default (G) => {
const creatureHasMaterializationSickness =
dpriest.player.summonCreaturesWithMaterializationSickness;

// Removes temporary Creature from queue when Player chooses a
// different Creature to materialize
G.queue.removeTempCreature();

// Create full temporary Creature with placeholder position to show in queue
crea = $j.extend(
crea,
Expand All @@ -284,11 +280,7 @@ export default (G) => {
// Make temporary Creature invisible
fullCrea.sprite.alpha = 0;

// Provide full Creature to Queue
G.queue.tempCreature = fullCrea;

// Show temporary Creature in queue
G.queue.addByInitiative(fullCrea, !creatureHasMaterializationSickness);
G.updateQueueDisplay();

G.grid.forEachHex(function (hex) {
Expand Down
2 changes: 1 addition & 1 deletion src/abilities/Knightmare.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export default (G) => {
return;
}

target.delay();
target.hinder();
},
},

Expand Down
5 changes: 2 additions & 3 deletions src/abilities/Stomper.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ export default (G) => {
target.status.dizzy = true;
target.removeEffect('Earth Shaker');
} else {
target.delay(false);
target.hinder();
target.addEffect(
new Effect(
'Earth Shaker', // Name
Expand All @@ -524,8 +524,7 @@ export default (G) => {
{
// disable the ability to delay this unit as it has already been delayed
effectFn: () => {
target.delayed = true;
target.delayable = false;
target.hinder();
},
deleteTrigger: 'onEndPhase',
turnLifetime: 1,
Expand Down
1 change: 0 additions & 1 deletion src/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ export class Ability {
}
game.signals.creature.dispatch('abilityend', { creature: this.creature });
game.UI.btnDelay.changeState('disabled');
game.activeCreature.delayable = false;
game.UI.selectAbility(-1);

if (this.getTrigger() === 'onQuery' && !deferredEnding) {
Expand Down
Loading
Loading