forked from phenom/healer-man
Release Healer Man 0.1.36
This commit is contained in:
1 parent
40d9f346d8
commit
03a4e3f51c
22 files changed
+1389
-153
No files matched your search
+43
-34
@@ -27,7 +27,7 @@ import {
|
||||
sampleMobAnimation,
|
||||
} from "../game/mobAnimation";
|
||||
import type { MobAnimationState } from "../game/mobAnimation";
|
||||
import { useCombatStore } from "../game/combatStore";
|
||||
import { useCombatStore, type MobCombatState } from "../game/combatStore";
|
||||
import { PRIMARY_MOUSE_BUTTON } from "../game/inputManager";
|
||||
import { TimedEffectStrip } from "../ui/TimedEffectStrip";
|
||||
import { AuraStrip } from "../ui/AuraStrip";
|
||||
@@ -76,9 +76,10 @@ import {
|
||||
resolveMobAnimationInterval,
|
||||
} from "./mobAnimationCadence";
|
||||
import { useGameGLTF } from "./useGameGLTF";
|
||||
import { onlineSynchronizedMobTransform, requestOnlineInteraction } from "../game/onlineSessionRuntime";
|
||||
import { onlineSessionOwnsWorldSimulation, onlineSynchronizedMobTransform, requestOnlineInteraction } from "../game/onlineSessionRuntime";
|
||||
import { isMobAggroRangeVisible } from "./mobAggroRangeVisibility";
|
||||
import { DungeonOccludedHtml } from "./DungeonOccludedHtml";
|
||||
import { useMobNavigation } from "./mobNavigation";
|
||||
|
||||
const MOVEMENT_LOCKING_MOB_STATUSES: ReadonlySet<string> = new Set([
|
||||
"stun", "root", "sleep", "knockdown", "freeze", "charm", "confuse",
|
||||
@@ -119,8 +120,32 @@ function mobTargetPosition(
|
||||
playerPosition: MobVector3,
|
||||
): MobVector3 {
|
||||
if (!targetActorId || targetActorId === PLAYER_AGGRO_ID) return playerPosition;
|
||||
const summon = useCombatStore.getState().summons.find((candidate) => candidate.id === targetActorId);
|
||||
if (summon) return summon.position;
|
||||
return getPartyRuntimePosition(targetActorId) ?? playerPosition;
|
||||
}
|
||||
|
||||
function navigateMob(
|
||||
navigator: ReturnType<typeof useMobNavigation>, mob: MobCombatState,
|
||||
position: MutableMobVector3, target: MobVector3, home: MobVector3,
|
||||
maximumStep: number, active: boolean, nowMs: number, controlled = false,
|
||||
): void {
|
||||
const game = useGameStore.getState();
|
||||
const hostileRanges = mob.attacks.filter((attack) => attack.target === "primary"
|
||||
|| attack.target === "random-party" || attack.target === "nearby-party").map((attack) => attack.range);
|
||||
const result = navigator.step({
|
||||
id: mob.id, targetId: mob.targetActorId, position, target, home,
|
||||
phase: mob.combatPhase, health: mob.health, engaged: mob.engaged,
|
||||
active: active && onlineSessionOwnsWorldSimulation() && !game.paused && !game.mapOpen && !game.companionOpen,
|
||||
casting: mob.activeCast !== null, controlled,
|
||||
attackRange: hostileRanges.length ? Math.max(...hostileRanges) : mob.attackRange,
|
||||
leashRange: mob.leashRange, maximumStep, nowMs,
|
||||
});
|
||||
if (result === "reset" || result === "home") {
|
||||
useCombatStore.getState().resetMobForNavigation(mob.id,
|
||||
result === "home" || Math.hypot(position[0] - home[0], position[1] - home[1], position[2] - home[2]) <= 0.85, nowMs);
|
||||
}
|
||||
}
|
||||
const PROXIMITY_CHECK_INTERVAL = 0.3;
|
||||
const AGGRO_RANGE_VISIBILITY_CHECK_INTERVAL = 0.25;
|
||||
let preparedCreatureTemplates = new WeakMap<Object3D, Object3D>();
|
||||
@@ -771,23 +796,6 @@ function isPlayerOrPartyNear(points: readonly MobVector3[], maxDistance: number)
|
||||
});
|
||||
}
|
||||
|
||||
function stepToward(
|
||||
current: MutableMobVector3,
|
||||
target: MobVector3,
|
||||
maximumStep: number,
|
||||
): number {
|
||||
const dx = target[0] - current[0];
|
||||
const dy = target[1] - current[1];
|
||||
const dz = target[2] - current[2];
|
||||
const distance = Math.hypot(dx, dy, dz);
|
||||
if (distance <= 0.001) return 0;
|
||||
const step = Math.min(Math.max(0, maximumStep), distance);
|
||||
current[0] += dx / distance * step;
|
||||
current[1] += dy / distance * step;
|
||||
current[2] += dz / distance * step;
|
||||
return distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates content when the player or an autonomous party member approaches.
|
||||
* The stores are read
|
||||
@@ -1159,6 +1167,7 @@ function RoamingPack({
|
||||
useOriginalModels,
|
||||
allowedRuntimeIds,
|
||||
}: RoamingPackProps) {
|
||||
const navigator = useMobNavigation();
|
||||
const path = useMemo(() => createLoopedPath(definition.waypoints), [definition.waypoints]);
|
||||
const distanceRef = useRef(definition.startDistance ?? 0);
|
||||
const { scratchPositions, scratchForwards, chasePositions } = useMemo(() => {
|
||||
@@ -1277,7 +1286,7 @@ function RoamingPack({
|
||||
const maximumStep = Math.min(delta, 0.05)
|
||||
* mob!.moveSpeed
|
||||
* Math.max(0.1, 1 - slow);
|
||||
if (!movementLocked && feared) {
|
||||
if (active && !movementLocked && feared) {
|
||||
stepFearedMobAway(
|
||||
chasePosition,
|
||||
targetPosition,
|
||||
@@ -1286,19 +1295,16 @@ function RoamingPack({
|
||||
mob!.leashRange,
|
||||
chasePosition,
|
||||
);
|
||||
} else if (!movementLocked && mob!.combatPhase === "chasing") {
|
||||
stepToward(
|
||||
chasePosition,
|
||||
targetPosition,
|
||||
maximumStep,
|
||||
);
|
||||
}
|
||||
navigateMob(navigator, mob!, chasePosition, targetPosition,
|
||||
mob!.homePosition ?? patrolPosition, maximumStep, active, now, movementLocked || feared);
|
||||
position = chasePosition;
|
||||
const facingSign = feared && !movementLocked ? -1 : 1;
|
||||
forward[0] = (targetPosition[0] - position[0]) * facingSign;
|
||||
forward[2] = (targetPosition[2] - position[2]) * facingSign;
|
||||
} else if (mob?.combatPhase === "returning") {
|
||||
stepToward(chasePosition, patrolPosition, Math.min(delta, 0.05) * mob.moveSpeed * 1.25);
|
||||
navigateMob(navigator, mob, chasePosition, targetPosition,
|
||||
mob.homePosition ?? patrolPosition, Math.min(delta, 0.05) * mob.moveSpeed * 1.25, active, now);
|
||||
position = chasePosition;
|
||||
} else {
|
||||
chasePosition[0] = patrolPosition[0];
|
||||
@@ -1360,6 +1366,7 @@ interface StaticPopulationProps {
|
||||
}
|
||||
|
||||
function StaticPopulationMember({ spawn, entities, active, showLabels, useOriginalModels }: StaticPopulationProps) {
|
||||
const navigator = useMobNavigation();
|
||||
const entity = entities[spawn.entityId];
|
||||
const groupRef = useRef<Group>(null);
|
||||
const positionRef = useRef<MutableMobVector3>([...spawn.position]);
|
||||
@@ -1398,7 +1405,7 @@ function StaticPopulationMember({ spawn, entities, active, showLabels, useOrigin
|
||||
feared = mob.statuses.some((status) => status.endsAt > now && status.kind === "fear");
|
||||
const slow = mob.statuses.find((status) => status.endsAt > now && status.kind === "slow")?.magnitude ?? 0;
|
||||
const maximumStep = Math.min(delta, 0.05) * mob.moveSpeed * Math.max(0.1, 1 - slow);
|
||||
if (!movementLocked && feared) {
|
||||
if (active && !movementLocked && feared) {
|
||||
stepFearedMobAway(
|
||||
position,
|
||||
targetPosition,
|
||||
@@ -1407,11 +1414,12 @@ function StaticPopulationMember({ spawn, entities, active, showLabels, useOrigin
|
||||
mob.leashRange,
|
||||
position,
|
||||
);
|
||||
} else if (!movementLocked && mob.combatPhase === "chasing") {
|
||||
stepToward(position, targetPosition, maximumStep);
|
||||
}
|
||||
navigateMob(navigator, mob, position, targetPosition, mob.homePosition ?? spawn.position,
|
||||
maximumStep, active, now, movementLocked || feared);
|
||||
} else if (mob?.combatPhase === "returning") {
|
||||
stepToward(position, spawn.position, Math.min(delta, 0.05) * mob.moveSpeed * 1.25);
|
||||
navigateMob(navigator, mob, position, targetPosition, mob.homePosition ?? spawn.position,
|
||||
Math.min(delta, 0.05) * mob.moveSpeed * 1.25, active, now);
|
||||
} else {
|
||||
position[0] = spawn.position[0];
|
||||
position[1] = spawn.position[1];
|
||||
@@ -1500,6 +1508,7 @@ function SummonedPopulationMember({
|
||||
readonly active: boolean;
|
||||
readonly useOriginalModels: boolean;
|
||||
}) {
|
||||
const navigator = useMobNavigation();
|
||||
const groupRef = useRef<Group>(null);
|
||||
const initial = getMobRuntimeTransform(instanceId)?.position ?? [0, 0, 0];
|
||||
const positionRef = useRef<MutableMobVector3>([...initial]);
|
||||
@@ -1515,7 +1524,7 @@ function SummonedPopulationMember({
|
||||
const feared = mob.statuses.some((status) => status.endsAt > now && status.kind === "fear");
|
||||
const slow = mob.statuses.find((status) => status.endsAt > now && status.kind === "slow")?.magnitude ?? 0;
|
||||
const maximumStep = Math.min(delta, 0.05) * mob.moveSpeed * Math.max(0.1, 1 - slow);
|
||||
if (!movementLocked && feared) {
|
||||
if (active && !movementLocked && feared) {
|
||||
stepFearedMobAway(
|
||||
position,
|
||||
targetPosition,
|
||||
@@ -1524,9 +1533,9 @@ function SummonedPopulationMember({
|
||||
mob.leashRange,
|
||||
position,
|
||||
);
|
||||
} else if (!movementLocked && mob.combatPhase === "chasing") {
|
||||
stepToward(position, targetPosition, maximumStep);
|
||||
}
|
||||
navigateMob(navigator, mob, position, targetPosition, mob.homePosition ?? initial,
|
||||
maximumStep, active, now, movementLocked || feared);
|
||||
const facingSign = feared && !movementLocked ? -1 : 1;
|
||||
const yaw = Math.atan2(
|
||||
(targetPosition[0] - position[0]) * facingSign,
|
||||
|
||||
Reference in new issue
Block a user