Android build v1.1.23
This commit is contained in:
+41
-16
@@ -13,6 +13,7 @@ import type {
|
||||
Iwt2PartyEntityId,
|
||||
Iwt2PartyEntityState,
|
||||
Iwt2ProjectileEntityState,
|
||||
Iwt2RoguelikePressureState,
|
||||
Iwt2StatusState,
|
||||
Iwt2Vec2,
|
||||
} from './types'
|
||||
@@ -22,6 +23,7 @@ import { separateCircles } from './collision'
|
||||
import { canPartyMemberHitTarget, tickPartyMember } from './partyAi'
|
||||
import { addFirePuddle, createHazardIndicators, tickGroundHazards } from './hazards'
|
||||
import { applyPartyDamageInShape } from './mechanics'
|
||||
import { tickRoguelikePressure } from './roguelikePressure'
|
||||
import {
|
||||
addVec2,
|
||||
clampVec2ToArena,
|
||||
@@ -62,6 +64,8 @@ export function createInitialIwt2ArenaState(
|
||||
bossId: Iwt2BossId = 'bulldrome',
|
||||
bossIds?: Iwt2BossId[],
|
||||
bossHealthScale = 1,
|
||||
partyDamageTakenScale = 1,
|
||||
roguelikePressure?: Iwt2RoguelikePressureState,
|
||||
): Iwt2ArenaState {
|
||||
const initialBossIds = bossIds?.length ? bossIds.slice(0, 2) : chooseInitialBossIds(bossId)
|
||||
const bosses = initialBossIds.map((id, index) => createBossEntity(id, index, bossHealthScale))
|
||||
@@ -69,11 +73,12 @@ export function createInitialIwt2ArenaState(
|
||||
schemaVersion: 1,
|
||||
time: 0,
|
||||
bounds: { width: DEFAULT_ARENA_WIDTH, height: DEFAULT_ARENA_HEIGHT },
|
||||
party: INITIAL_PARTY.map(createPartyMember),
|
||||
party: INITIAL_PARTY.map((member) => createPartyMember(member, partyDamageTakenScale)),
|
||||
projectiles: [],
|
||||
hostileAdds: [],
|
||||
hazards: [],
|
||||
indicators: [],
|
||||
roguelikePressure,
|
||||
boss: bosses[0],
|
||||
bosses,
|
||||
nextEventId: 1,
|
||||
@@ -216,8 +221,13 @@ export function tickIwt2Arena(state: Iwt2ArenaState, input: Iwt2ArenaInput, dt:
|
||||
party: projectileResult.party,
|
||||
time: separatedState.time,
|
||||
})
|
||||
const pressureResult = tickRoguelikePressure({
|
||||
party: hazardResult.party,
|
||||
pressure: separatedState.roguelikePressure,
|
||||
time: separatedState.time,
|
||||
})
|
||||
const damageResult = applyPartyAttacks(
|
||||
hazardResult.party,
|
||||
pressureResult.party,
|
||||
projectileResult.bosses,
|
||||
projectileResult.hostileAdds,
|
||||
separatedState.time,
|
||||
@@ -234,7 +244,7 @@ export function tickIwt2Arena(state: Iwt2ArenaState, input: Iwt2ArenaInput, dt:
|
||||
finalCollisionState,
|
||||
)
|
||||
const nextEvents = assignEventIds(
|
||||
[...bossResult.events, ...projectileResult.events, ...hazardResult.events, ...damageResult.events, ...hotResult.events],
|
||||
[...bossResult.events, ...projectileResult.events, ...hazardResult.events, ...pressureResult.events, ...damageResult.events, ...hotResult.events],
|
||||
state.nextEventId,
|
||||
)
|
||||
return {
|
||||
@@ -242,6 +252,7 @@ export function tickIwt2Arena(state: Iwt2ArenaState, input: Iwt2ArenaInput, dt:
|
||||
boss: getPrimaryBoss(damageResult.bosses),
|
||||
bosses: damageResult.bosses,
|
||||
indicators: [...bossResult.indicators, ...createHazardIndicators(hazardResult.hazards)],
|
||||
roguelikePressure: pressureResult.pressure,
|
||||
party: finalParty,
|
||||
hostileAdds: damageResult.hostileAdds,
|
||||
hazards: hazardResult.hazards,
|
||||
@@ -270,7 +281,10 @@ function tickPartyHotEffects(
|
||||
let nextTickInSeconds = effect.nextTickInSeconds - dt
|
||||
if (member.health > 0 && nextTickInSeconds <= 0) {
|
||||
const before = health
|
||||
health = Math.min(member.maxHealth, health + effect.power)
|
||||
const healingMultiplier = member.shield > 0
|
||||
? member.shieldedHotHealingMultiplier ?? 1
|
||||
: 1
|
||||
health = Math.min(member.maxHealth, health + effect.power * healingMultiplier)
|
||||
const healed = health - before
|
||||
if (healed > 0) {
|
||||
events.push({
|
||||
@@ -310,8 +324,9 @@ function regeneratePartyMana(party: Iwt2PartyEntityState[], dt: number): Iwt2Par
|
||||
})
|
||||
}
|
||||
|
||||
function createPartyMember(initial: InitialPartyMember): Iwt2PartyEntityState {
|
||||
function createPartyMember(initial: InitialPartyMember, damageTakenScale: number): Iwt2PartyEntityState {
|
||||
const metadata = IWT2_CLASS_METADATA[initial.classId]
|
||||
const safeDamageTakenScale = Number.isFinite(damageTakenScale) ? Math.max(0.01, damageTakenScale) : 1
|
||||
return {
|
||||
id: initial.id,
|
||||
kind: 'party',
|
||||
@@ -321,8 +336,16 @@ function createPartyMember(initial: InitialPartyMember): Iwt2PartyEntityState {
|
||||
velocity: { x: 0, y: 0 },
|
||||
facing: { x: 1, y: 0 },
|
||||
radius: metadata.radius,
|
||||
moveSpeed: metadata.moveSpeed,
|
||||
attackRange: metadata.attackRange,
|
||||
attackDamage: metadata.attackDamage,
|
||||
attackCooldown: metadata.attackCooldown,
|
||||
castTime: metadata.castTime,
|
||||
projectileSpeed: metadata.projectileSpeed,
|
||||
health: metadata.maxHealth,
|
||||
maxHealth: metadata.maxHealth,
|
||||
damageTakenScale: safeDamageTakenScale,
|
||||
stunTakenScale: 1,
|
||||
shield: 0,
|
||||
mana: initial.classId === 'healer' ? 100 : 0,
|
||||
maxMana: initial.classId === 'healer' ? 100 : 0,
|
||||
@@ -447,13 +470,15 @@ function separatePartyFromBosses(party: Iwt2PartyEntityState[], state: Iwt2Arena
|
||||
let position = member.position
|
||||
for (const boss of state.bosses) {
|
||||
if (boss.health <= 0) continue
|
||||
const overlapBeforeSeparation = circleOverlapAmount({ position, radius: member.radius }, boss)
|
||||
const separated = separateCircles(
|
||||
{ position, radius: member.radius },
|
||||
{ position: boss.position, radius: boss.radius },
|
||||
state.bounds,
|
||||
)
|
||||
position = wallClearance(separated, member, state) <= 2
|
||||
|| circleOverlapAmount({ position: separated, radius: member.radius }, boss) > 0.25
|
||||
const overlapAfterSeparation = circleOverlapAmount({ position: separated, radius: member.radius }, boss)
|
||||
position = overlapBeforeSeparation > 0.25
|
||||
&& (wallClearance(separated, member, state) <= 2 || overlapAfterSeparation > 0.25)
|
||||
? separateFromBossTowardCenter(member, boss, state)
|
||||
: separated
|
||||
}
|
||||
@@ -802,7 +827,7 @@ function applyPartyAttacks(
|
||||
if (!target) return member
|
||||
if (!canPartyMemberHitTarget(member, target.position, target.radius)) return member
|
||||
const metadata = IWT2_CLASS_METADATA[member.classId]
|
||||
if (metadata.projectileSpeed > 0) {
|
||||
if (member.projectileSpeed > 0) {
|
||||
if (!member.attackReady) return member
|
||||
const direction = normalizeVec2(subtractVec2(target.position, member.position))
|
||||
projectiles.push({
|
||||
@@ -810,29 +835,29 @@ function applyPartyAttacks(
|
||||
sourceId: member.id,
|
||||
owner: 'party',
|
||||
classId: member.classId,
|
||||
projectileKind: member.classId === 'mage' ? 'magic' : 'arrow',
|
||||
projectileKind: member.classId === 'mage' ? 'fireball' : 'arrow',
|
||||
color: metadata.accentColor,
|
||||
position: {
|
||||
x: member.position.x + direction.x * (member.radius + 4),
|
||||
y: member.position.y + direction.y * (member.radius + 4),
|
||||
},
|
||||
velocity: scaleVec2(direction, metadata.projectileSpeed),
|
||||
velocity: scaleVec2(direction, member.projectileSpeed),
|
||||
radius: member.classId === 'mage' ? 7 : 4,
|
||||
damage: metadata.attackDamage,
|
||||
damage: member.attackDamage,
|
||||
remainingSeconds: 1.2,
|
||||
})
|
||||
projectileId += 1
|
||||
return {
|
||||
...member,
|
||||
attackCooldownRemaining: metadata.attackCooldown,
|
||||
attackCooldownRemaining: member.attackCooldown,
|
||||
attackReady: false,
|
||||
}
|
||||
}
|
||||
if (member.attackCooldownRemaining > 0) return member
|
||||
let damage = Math.min(metadata.attackDamage, target.health)
|
||||
let damage = Math.min(member.attackDamage, target.health)
|
||||
let defeated = target.health - damage <= 0
|
||||
if (target.kind === 'boss') {
|
||||
const damageResult = applyDamageToBoss(target, metadata.attackDamage)
|
||||
const damageResult = applyDamageToBoss(target, member.attackDamage)
|
||||
damage = damageResult.healthDamage
|
||||
defeated = damageResult.boss.health <= 0
|
||||
nextBosses = nextBosses.map((boss) => boss.id === target.id
|
||||
@@ -862,13 +887,13 @@ function applyPartyAttacks(
|
||||
return {
|
||||
...member,
|
||||
damageDone: member.damageDone + damage,
|
||||
attackCooldownRemaining: metadata.attackCooldown,
|
||||
attackCooldownRemaining: member.attackCooldown,
|
||||
}
|
||||
}
|
||||
return {
|
||||
...member,
|
||||
damageDone: member.damageDone + damage,
|
||||
attackCooldownRemaining: metadata.attackCooldown,
|
||||
attackCooldownRemaining: member.attackCooldown,
|
||||
}
|
||||
})
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user