Skip to content

Commit

Permalink
Reworking attacks
Browse files Browse the repository at this point in the history
  • Loading branch information
hubol committed Aug 13, 2024
1 parent 56b08e7 commit a875aaa
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 80 deletions.
10 changes: 8 additions & 2 deletions src/igua/mixins/mxn-enemy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { RpgLoot } from "../rpg/rpg-loot";
import { RpgEnemy } from "../rpg/rpg-enemy";
import { objLootDrop } from "../objects/obj-loot-drop";
import { layers } from "../globals";
import { RpgFaction } from "../rpg/rpg-faction";
import { RpgAttack } from "../rpg/rpg-attack";

interface MxnEnemyArgs {
hurtboxes: DisplayObject[];
Expand All @@ -21,6 +23,10 @@ export function mxnEnemy(obj: DisplayObject, args: MxnEnemyArgs) {
level: 0,
max: 100,
value: 0,
},
faction: RpgFaction.Enemy,
quirks: {
emotionalDamageIsFatal: false,
}
};

Expand Down Expand Up @@ -57,8 +63,8 @@ export function mxnEnemy(obj: DisplayObject, args: MxnEnemyArgs) {
.merge({
// TODO needs other damage types!!
// Maybe it's time for a RpgAttack.Model ?!
strikePlayer(damage: number) {
RpgEnemy.Methods.strikePlayer(enemy, 0, damage, 0);
strikePlayer(attack: RpgAttack.Model) {
RpgEnemy.Methods.strikePlayer(enemy, attack);
}
});

Expand Down
27 changes: 27 additions & 0 deletions src/igua/mixins/mxn-projectile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { DisplayObject } from "pixi.js";
import { Instances } from "../../lib/game-engine/instances";
import { mxnRpgStatus } from "./mxn-rpg-status";
import { RpgAttack } from "../rpg/rpg-attack";
import { RpgEnemy } from "../rpg/rpg-enemy";

interface MxnProjectileArgs {
attack: RpgAttack.Model;
enemy?: RpgEnemy.Model;
}

export function mxnProjectile(obj: DisplayObject, args: MxnProjectileArgs) {
return obj
.dispatches<'hit'>()
.step(self => {
for (const instance of Instances(mxnRpgStatus)) {
// TODO filter by faction here pls
if (obj.collidesOne(instance.hurtboxes)) {
const result = instance.damage(args.attack);
if (!result.rejected)
self.dispatch('hit');
if (self.destroyed)
return;
}
}
})
}
13 changes: 7 additions & 6 deletions src/igua/mixins/mxn-rpg-status.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DisplayObject } from "pixi.js";
import { RpgStatus } from "../rpg/rpg-status";
import { RpgAttack } from "../rpg/rpg-attack";

interface MxnRpgStatusArgs {
status: RpgStatus.Model;
Expand All @@ -14,18 +15,18 @@ export function mxnRpgStatus(obj: DisplayObject, args: MxnRpgStatusArgs) {
.track(mxnRpgStatus)
.merge({ hurtboxes: args.hurtboxes })
.merge({
damage(amount: number) {
RpgStatus.Methods.damage(args.status, args.effects, amount);
damage(attack: RpgAttack.Model) {
const result = RpgStatus.Methods.damage(args.status, args.effects, attack);
// TODO feels weird, should maybe be part of return value of damage?
if (args.status.health === 0)
// Or should be part of effects, I think!
if (!result.rejected && result.died)
rpgStatusObj.dispatch('rpgStatus.died');

return result;
},
heal(amount: number) {
RpgStatus.Methods.heal(args.status, args.effects, amount);
},
poison(amount: number) {
RpgStatus.Methods.poison(args.status, args.effects, amount);
}
})
.dispatches<'rpgStatus.died'>()
.step(() => {
Expand Down
10 changes: 8 additions & 2 deletions src/igua/objects/enemies/obj-angel-bouncing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import { mxnPhysics } from "../../mixins/mxn-physics";
import { vnew } from "../../../lib/math/vector-type";
import { playerObj } from "../obj-player";
import { mxnEnemy } from "../../mixins/mxn-enemy";
import { RpgPlayer } from "../../rpg/rpg-player";
import { RpgAttack } from "../../rpg/rpg-attack";

const clownTxs = Tx.Enemy.CommonClown.split({ count: 2 });

const atkSpikeBall = RpgAttack.create({
physical: 10,
})

export function objAngelBouncing() {
// const obj = merge(new Container(), { hspeed, vspeed: 0, portal, dangerous, bounceAgainstWall, limitedRangeEnabled });
// container.ext.isHatParent = true;
Expand Down Expand Up @@ -138,9 +144,9 @@ export function objAngelBouncing() {
})
.step(self => {
if (playerObj.collides(mask))
self.damage(10);
self.damage(RpgPlayer.MeleeAttack);
else if (playerObj.collides(spikeBall))
self.strikePlayer(10);
self.strikePlayer(atkSpikeBall);

}, 1001)

Expand Down
24 changes: 11 additions & 13 deletions src/igua/objects/obj-water-drip-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { Tx } from "../../assets/textures";
import { mxnPhysics } from "../mixins/mxn-physics";
import { sleep } from "../../lib/game-engine/promise/sleep";
import { Rng } from "../../lib/math/rng";
import { Instances } from "../../lib/game-engine/instances";
import { mxnRpgStatus } from "../mixins/mxn-rpg-status";
import { RpgAttack } from "../rpg/rpg-attack";
import { RpgFaction } from "../rpg/rpg-faction";
import { mxnProjectile } from "../mixins/mxn-projectile";

interface ObjWaterDripSourceArgs {
delayMin: number;
Expand All @@ -24,24 +25,21 @@ export function objWaterDripSource({ delayMin, delayMax }: ObjWaterDripSourceArg
})
}

const atkPoisonDrip = RpgAttack.create({
poison: 5,
versus: RpgFaction.Anyone,
});

function objWaterDrip(poison: boolean) {
const obj = Sprite.from(poison ? Tx.Effects.PoisonDripSmall : Tx.Effects.WaterDripSmall)
.mixin(mxnPhysics, { gravity: 0.05, physicsRadius: 4, physicsOffset: [0, -2], onMove: (ev) => {
if (poison) {
// TODO should be a more terse way to accomplish this!
for (const instance of Instances(mxnRpgStatus)) {
if (obj.collidesOne(instance.hurtboxes)) {
instance.poison(5);
// TODO sfx
return obj.destroy();
}
}
}
if (ev.hitGround) {
obj.destroy();
// TODO drip sfx
}
} });
} })
.mixin(mxnProjectile, { attack: atkPoisonDrip })
.handles('hit', self => self.destroy());

return obj;
}
20 changes: 20 additions & 0 deletions src/igua/rpg/rpg-attack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Integer } from "../../lib/math/number-alias-types";
import { RpgFaction } from "./rpg-faction";

export namespace RpgAttack {
export interface Model {
physical: Integer;
emotional: Integer;
poison: Integer;
versus: RpgFaction;
}

export function create(model: Partial<Model>): Model {
return {
physical: model.physical ?? 0,
emotional: model.emotional ?? 0,
poison: model.poison ?? 0,
versus: model.versus ?? RpgFaction.Player,
}
}
}
18 changes: 5 additions & 13 deletions src/igua/rpg/rpg-enemy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Integer } from "../../lib/math/number-alias-types";
import { playerObj } from "../objects/obj-player";
import { RpgAttack } from "./rpg-attack";
import { RpgPlayer } from "./rpg-player";

export namespace RpgEnemy {
Expand All @@ -10,23 +11,14 @@ export namespace RpgEnemy {
}

export const Methods = {
strikePlayer(model: Model, poison: Integer, physical: Integer, emotional: Integer) {
strikePlayer(model: Model, attack: RpgAttack.Model) {
if (!playerObj)
return;

// TODO not sure if shameCount should increase when player is invulnerable
// Or if a "slow poison" should increase the shameCount
// Maybe shameCount should only increase when the player was previously vulnerable and becomes invulnerable
// But capture that in a cooler way
// TODO not sure if a "slow poison" should increase the shameCount

// TODO feels bad!!! Fix!!!
const wasInvulnerable = RpgPlayer.Model.invulnerable > 0;

// TODO use poison, physical, emotional
playerObj.damage(physical);

// TODO feels bad!!!! Should come from result of damage, I think!!!
if (!wasInvulnerable && RpgPlayer.Model.invulnerable > 0)
const result = playerObj.damage(attack);
if (!result.rejected && result.damaged)
model.shameCount++;
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/igua/rpg/rpg-faction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum RpgFaction {
Player,
Enemy,
Anyone,
}
16 changes: 15 additions & 1 deletion src/igua/rpg/rpg-player.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { RpgAttack } from "./rpg-attack";
import { RpgFaction } from "./rpg-faction";
import { RpgProgress } from "./rpg-progress";
import { RpgStatus } from "./rpg-status";

Expand Down Expand Up @@ -34,12 +36,24 @@ export const RpgPlayer = {
set value(value) {
RpgProgress.character.status.poison.value = value;
}
}
},
faction: RpgFaction.Player,
quirks: {
emotionalDamageIsFatal: true,
},
} satisfies RpgStatus.Model,
get WalkingTopSpeed() {
let speed = 2.5;
speed += 0.75 * Math.min(1, RpgProgress.character.status.poison.level);
speed += 0.5 * Math.max(0, RpgProgress.character.status.poison.level - 1);
return speed
},
MeleeAttack: {
emotional: 0,
get physical() {
return 5 + RpgProgress.character.attributes.strength * 5;
},
poison: 0,
versus: RpgFaction.Enemy,
} satisfies RpgAttack.Model,
}
1 change: 1 addition & 0 deletions src/igua/rpg/rpg-progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function getInitialRpgProgress() {
attributes: {
health: 1,
intelligence: 0,
strength: 1,
},
looks: getDefaultLooks(),
position: {
Expand Down
Loading

0 comments on commit a875aaa

Please sign in to comment.