forked from phenom/healer-man
Release Healer Man 0.1.6
This commit is contained in:
1 parent
55cfd43d66
commit
b12fb84859
96 files changed
+10874
-609
No files matched your search
@@ -65,6 +65,7 @@ import { partyCombatRangeBand } from "../game/partyRuntime";
|
||||
import { useWailingEncounterStore } from "../game/wailingCavernsEncounter";
|
||||
import {
|
||||
clearPartyRuntimeAttackCorridor,
|
||||
getPartyRuntimePosition,
|
||||
registerPartyRuntimePosition,
|
||||
updatePartyRuntimeAttackCorridor,
|
||||
updatePartyRuntimePosition,
|
||||
@@ -75,6 +76,8 @@ import {
|
||||
import { usePartyStore } from "../game/partyStore";
|
||||
import { useGameStore } from "../game/store";
|
||||
import { useManastormStore } from "../game/manastormStore";
|
||||
import { registerCombatSpatialProvider } from "../game/combatSpatial";
|
||||
import { PLAYER_AGGRO_ID } from "../game/aggro";
|
||||
|
||||
const PARTY_MOVE_SPEED = 5.25;
|
||||
const PARTY_CATCH_UP_SPEED = 7.5;
|
||||
@@ -266,12 +269,14 @@ function initialMemberPosition(index: number): MutablePartyWorldPosition {
|
||||
|
||||
function PartyActors({
|
||||
active,
|
||||
simulate,
|
||||
navigationGraph,
|
||||
navigationFailed,
|
||||
objectives,
|
||||
stackAtEntrance,
|
||||
}: {
|
||||
readonly active: boolean;
|
||||
readonly simulate: boolean;
|
||||
readonly navigationGraph: PartyNavigationGraph | null;
|
||||
readonly navigationFailed: boolean;
|
||||
readonly objectives: readonly DungeonBossObjective[];
|
||||
@@ -442,6 +447,56 @@ function PartyActors({
|
||||
const directFollowMovingRef = useRef(new Map<string, boolean>());
|
||||
const combatAnchorsRef = useRef(new Map<string, PartyCombatAnchor>());
|
||||
const memberIdKey = members.map((member) => member.id).join("|");
|
||||
useEffect(() => registerCombatSpatialProvider({
|
||||
actor: (actorId) => {
|
||||
const gameState = useGameStore.getState();
|
||||
if (actorId === PLAYER_AGGRO_ID) {
|
||||
return { id: actorId, position: gameState.playerPosition, yaw: gameState.cameraYaw };
|
||||
}
|
||||
const memberIndex = usePartyStore.getState().members.findIndex((member) => member.id === actorId);
|
||||
const memberPosition = positionsRef.current.get(actorId);
|
||||
if (memberPosition) {
|
||||
return {
|
||||
id: actorId,
|
||||
position: memberPosition,
|
||||
yaw: actorRefs.current[memberIndex]?.rotation.y ?? gameState.cameraYaw,
|
||||
};
|
||||
}
|
||||
const summon = useCombatStore.getState().summons.find((candidate) => candidate.id === actorId);
|
||||
if (summon) return { id: actorId, position: summon.position, yaw: gameState.cameraYaw };
|
||||
const mobPosition = getMobPosition(actorId);
|
||||
if (!mobPosition) return null;
|
||||
const mob = useCombatStore.getState().mobs[actorId];
|
||||
const targetPosition = mob?.targetActorId === PLAYER_AGGRO_ID
|
||||
? gameState.playerPosition
|
||||
: mob?.targetActorId
|
||||
? positionsRef.current.get(mob.targetActorId)
|
||||
?? useCombatStore.getState().summons.find((candidate) => candidate.id === mob.targetActorId)?.position
|
||||
: null;
|
||||
const yaw = targetPosition
|
||||
? Math.atan2(targetPosition[0] - mobPosition[0], targetPosition[2] - mobPosition[2])
|
||||
: 0;
|
||||
return { id: actorId, position: mobPosition, yaw };
|
||||
},
|
||||
hasLineOfSight: hasStaticLineOfSight,
|
||||
projectGroundPoint: (requested, maximumDistance, requestedOrigin) => {
|
||||
const origin = requestedOrigin ?? useGameStore.getState().playerPosition;
|
||||
const dx = requested[0] - origin[0];
|
||||
const dz = requested[2] - origin[2];
|
||||
const planar = Math.hypot(dx, dz);
|
||||
const scale = planar > maximumDistance && planar > 0 ? maximumDistance / planar : 1;
|
||||
const x = origin[0] + dx * scale;
|
||||
const z = origin[2] + dz * scale;
|
||||
const ray = new rapier.Ray({ x, y: requested[1] + 8, z }, { x: 0, y: -1, z: 0 });
|
||||
const hit = world.castRay(
|
||||
ray,
|
||||
20,
|
||||
true,
|
||||
rapier.QueryFilterFlags.EXCLUDE_SENSORS | rapier.QueryFilterFlags.EXCLUDE_DYNAMIC,
|
||||
);
|
||||
return hit ? [x, ray.origin.y - hit.timeOfImpact, z] : null;
|
||||
},
|
||||
}), [hasStaticLineOfSight, memberIdKey, rapier, world]);
|
||||
const teleportPartyToPlayer = useCallback((player: PartyWorldPosition, now: number): void => {
|
||||
const party = usePartyStore.getState();
|
||||
party.members.forEach((member, index) => {
|
||||
@@ -606,6 +661,21 @@ function PartyActors({
|
||||
if (!active) return;
|
||||
const party = usePartyStore.getState();
|
||||
if (!party.members.length) return;
|
||||
if (!simulate) {
|
||||
party.members.forEach((member, index) => {
|
||||
const synchronized = getPartyRuntimePosition(member.id);
|
||||
if (!synchronized) return;
|
||||
const position = positionsRef.current.get(member.id) ?? initialMemberPosition(index);
|
||||
position[0] = synchronized[0];
|
||||
position[1] = synchronized[1];
|
||||
position[2] = synchronized[2];
|
||||
positionsRef.current.set(member.id, position);
|
||||
actorRefs.current[index]?.position.set(position[0], presentationY(position), position[2]);
|
||||
const movingSignal = movingSignalsRef.current.get(member.id);
|
||||
if (movingSignal) movingSignal.current = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
const game = useGameStore.getState();
|
||||
const playerNavigation = game.playerNavigationPosition;
|
||||
appendPartyBreadcrumb(playerTrailRef.current, playerNavigation);
|
||||
@@ -1320,7 +1390,13 @@ function PartyActors({
|
||||
);
|
||||
}
|
||||
|
||||
export function PartyPopulation({ active = true }: { readonly active?: boolean }) {
|
||||
export function PartyPopulation({
|
||||
active = true,
|
||||
simulate = true,
|
||||
}: {
|
||||
readonly active?: boolean;
|
||||
readonly simulate?: boolean;
|
||||
}) {
|
||||
const activeDungeonId = useGameStore((state) => state.activeDungeonId);
|
||||
const gameMode = useGameStore((state) => state.gameMode);
|
||||
const sessionRevision = useGameStore((state) => state.sessionRevision);
|
||||
@@ -1383,6 +1459,7 @@ export function PartyPopulation({ active = true }: { readonly active?: boolean }
|
||||
<PartyActors
|
||||
key={activeDungeonId}
|
||||
active={active}
|
||||
simulate={simulate}
|
||||
navigationGraph={navigationGraph}
|
||||
navigationFailed={navigationFailed || !assets.navigation}
|
||||
objectives={objectives}
|
||||
|
||||
Reference in new issue
Block a user