Update Healer Man server
This commit is contained in:
1 parent
4c768fbec6
commit
b16821e92e
330 files changed
+35406
-1760
No files matched your search
@@ -0,0 +1,110 @@
|
||||
import type { AbilityEffect } from "./abilityCatalog";
|
||||
import type { ActiveAura, AuraDefinition } from "./combatAuras";
|
||||
|
||||
/** Current CoA Mage/Druid Green Guardian stack behavior (skill 494331). */
|
||||
export const ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID = 494331;
|
||||
export const ROM_MAGE_DRUID_GREEN_GUARDIAN_MAX_STACKS = 20;
|
||||
export const ROM_MAGE_DRUID_GREEN_GUARDIAN_GAIN_INTERVAL_MS = 1_000;
|
||||
export const ROM_MAGE_DRUID_GREEN_GUARDIAN_MOVEMENT_SPEED_PERCENT_PER_STACK = 1;
|
||||
export const ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG = "rom-mage-druid-green-guardian";
|
||||
export const ROM_MAGE_DRUID_GREEN_GUARDIAN_DESCRIPTION = "While standing still, gain one Green Guardian stack each second, up to 20. Each stack grants 1% movement speed. Moving pauses stack generation. Current CoA also describes an MP restore when a stack is lost, but the loss trigger and percentage basis are unspecified, so that clause is not implemented.";
|
||||
|
||||
export function romMageDruidGreenGuardianAuraDefinition(): AuraDefinition {
|
||||
return {
|
||||
id: "rom:mage-druid:green-guardian",
|
||||
name: "Green Guardian",
|
||||
description: ROM_MAGE_DRUID_GREEN_GUARDIAN_DESCRIPTION,
|
||||
disposition: "buff",
|
||||
durationMs: null,
|
||||
maxStacks: ROM_MAGE_DRUID_GREEN_GUARDIAN_MAX_STACKS,
|
||||
stackBehavior: "replace",
|
||||
utilityTags: [ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG],
|
||||
modifiers: [{
|
||||
kind: "stat",
|
||||
stat: "movement-speed",
|
||||
operation: "percent",
|
||||
value: ROM_MAGE_DRUID_GREEN_GUARDIAN_MOVEMENT_SPEED_PERCENT_PER_STACK / 100,
|
||||
perStack: true,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
export function romMageDruidGreenGuardianAuraEffect(): Extract<AbilityEffect, { kind: "apply-aura" }> {
|
||||
return {
|
||||
kind: "apply-aura",
|
||||
recipient: "caster",
|
||||
aura: romMageDruidGreenGuardianAuraDefinition(),
|
||||
sourceEffectType: -1,
|
||||
sourceAuraType: -1,
|
||||
miscValue: 0,
|
||||
triggerSpellId: ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID,
|
||||
};
|
||||
}
|
||||
|
||||
export function isRomMageDruidPair(row: {
|
||||
readonly classId?: string;
|
||||
readonly secondaryClassId?: string | null;
|
||||
}): boolean {
|
||||
return row.classId === "rom-mage" && row.secondaryClassId === "rom-druid";
|
||||
}
|
||||
|
||||
function boundedStacks(stacks: number): number {
|
||||
if (!Number.isFinite(stacks)) return 0;
|
||||
return Math.max(0, Math.min(ROM_MAGE_DRUID_GREEN_GUARDIAN_MAX_STACKS, Math.floor(stacks)));
|
||||
}
|
||||
|
||||
/** Apply one source-described stack gain after an eligible second spent standing still. */
|
||||
export function romMageDruidGreenGuardianStacksAfterStationarySecond(stacks: number): number {
|
||||
return Math.min(ROM_MAGE_DRUID_GREEN_GUARDIAN_MAX_STACKS, boundedStacks(stacks) + 1);
|
||||
}
|
||||
|
||||
/** Percentage points of movement speed granted by the current stack count. */
|
||||
export function romMageDruidGreenGuardianMovementSpeedPercent(stacks: number): number {
|
||||
return boundedStacks(stacks) * ROM_MAGE_DRUID_GREEN_GUARDIAN_MOVEMENT_SPEED_PERCENT_PER_STACK;
|
||||
}
|
||||
|
||||
export function romMageDruidGreenGuardianMovementSpeedMultiplier(
|
||||
auras: readonly ActiveAura[],
|
||||
targetId: string,
|
||||
now: number,
|
||||
): number {
|
||||
const stacks = auras
|
||||
.filter((aura) => aura.targetId === targetId
|
||||
&& aura.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG)
|
||||
&& (aura.expiresAt === null || aura.expiresAt > now))
|
||||
.reduce((total, aura) => total + boundedStacks(aura.stacks), 0);
|
||||
return 1 + romMageDruidGreenGuardianMovementSpeedPercent(stacks) / 100;
|
||||
}
|
||||
|
||||
export interface RomMageDruidGreenGuardianStationaryProgress {
|
||||
readonly position: readonly [number, number, number];
|
||||
readonly stationaryMs: number;
|
||||
}
|
||||
|
||||
export interface RomMageDruidGreenGuardianStationaryAdvance {
|
||||
readonly progress: RomMageDruidGreenGuardianStationaryProgress;
|
||||
readonly stacksGained: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance one simulator tick. Any observed position change resets progress;
|
||||
* this is the documented one-full-stationary-second approximation for CoA's
|
||||
* unspecific “brief” movement pause. It does not remove existing stacks.
|
||||
*/
|
||||
export function romMageDruidGreenGuardianAdvanceStationaryProgress(
|
||||
previous: RomMageDruidGreenGuardianStationaryProgress | undefined,
|
||||
position: readonly [number, number, number],
|
||||
deltaMs: number,
|
||||
): RomMageDruidGreenGuardianStationaryAdvance {
|
||||
const safeDelta = Math.max(0, Number.isFinite(deltaMs) ? deltaMs : 0);
|
||||
if (!previous) return { progress: { position, stationaryMs: 0 }, stacksGained: 0 };
|
||||
const moved = (position[0] - previous.position[0]) ** 2
|
||||
+ (position[1] - previous.position[1]) ** 2
|
||||
+ (position[2] - previous.position[2]) ** 2 > 1e-8;
|
||||
if (moved) return { progress: { position, stationaryMs: 0 }, stacksGained: 0 };
|
||||
const total = Math.max(0, previous.stationaryMs) + safeDelta;
|
||||
return {
|
||||
progress: { position, stationaryMs: total % ROM_MAGE_DRUID_GREEN_GUARDIAN_GAIN_INTERVAL_MS },
|
||||
stacksGained: Math.floor(total / ROM_MAGE_DRUID_GREEN_GUARDIAN_GAIN_INTERVAL_MS),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user