108 lines
5.2 KiB
TypeScript
108 lines
5.2 KiB
TypeScript
import { useEffect, useRef } from "react";
|
|
import { useShellStore } from "../app/shellStore";
|
|
import { useCombatStore } from "./combatStore";
|
|
import { resetPartyRuntimeClock } from "./partyRuntime";
|
|
import { usePartyStore } from "./partyStore";
|
|
import { useGameStore } from "./store";
|
|
import { useManastormStore } from "./manastormStore";
|
|
import { onlineGroupAiPartySize, useOnlineGroupStore } from "../app/onlineGroupStore";
|
|
import { useDungeonSimulationStore } from "./dungeonSimulationStore";
|
|
import { useCompanionSpecReadinessStore } from "./companionSpecReadinessStore";
|
|
import { useCompanionPartyPreferences } from "./companionPartyPreferences";
|
|
import { RANDOMIZED_BITE_SIZED_STOCKADES_DUNGEON_ID } from "./dungeonContentSource";
|
|
|
|
/** Owns party lifecycle; the combat interval itself remains in CombatBridge. */
|
|
export function PartyBridge() {
|
|
const character = useShellStore((state) => state.activeCharacter);
|
|
const playerRole = useShellStore((state) => state.activeDungeonRole);
|
|
const gameMode = useGameStore((state) => state.gameMode);
|
|
const manastormPartySize = useManastormStore((state) => state.partySize);
|
|
const onlineActivity = useOnlineGroupStore((state) => state.activeActivity);
|
|
const onlineGroup = useOnlineGroupStore((state) => state.snapshot.group);
|
|
const level = useCombatStore((state) => state.level);
|
|
const simulationMode = useDungeonSimulationStore((state) => state.sessionMode);
|
|
const simulationSeed = useDungeonSimulationStore((state) => state.seed);
|
|
const resetRevision = useGameStore((state) => state.resetRevision);
|
|
const readinessPolicy = useCompanionSpecReadinessStore((state) => state.config);
|
|
const readinessPolicyRevision = useCompanionSpecReadinessStore((state) => state.revision);
|
|
const deviceIncludeBetaSpecs = useCompanionPartyPreferences((state) => state.includeBetaSpecs);
|
|
const mountedResetRevision = useRef(resetRevision);
|
|
|
|
useEffect(() => {
|
|
if (!character) return;
|
|
const combat = useCombatStore.getState();
|
|
const party = usePartyStore.getState();
|
|
const requestedPartySize = gameMode === "manastorm" ? manastormPartySize : 5;
|
|
const aiPartySize = onlineActivity
|
|
&& onlineActivity.type === (gameMode === "manastorm" ? "manastorm" : "dungeon")
|
|
? onlineGroupAiPartySize(onlineActivity.partySize)
|
|
: requestedPartySize;
|
|
const sharedOnlineParty = onlineActivity && onlineGroup?.activity?.id === onlineActivity.id
|
|
? onlineGroup.members
|
|
: [];
|
|
const randomizedReadyOnly = onlineActivity?.type === "dungeon"
|
|
&& onlineActivity.contentId === RANDOMIZED_BITE_SIZED_STOCKADES_DUNGEON_ID;
|
|
const companionOptions = {
|
|
readinessPolicy,
|
|
readinessPolicyRevision: onlineActivity?.companionReadinessRevision ?? readinessPolicyRevision,
|
|
includeBetaSpecs: randomizedReadyOnly ? false : onlineActivity?.includeBetaSpecs ?? deviceIncludeBetaSpecs,
|
|
excludedPlayerSpecializationId: character.specializationId,
|
|
excludedPlayerSpecializationIds: sharedOnlineParty.flatMap((member) => (
|
|
member.character?.specializationId ? [member.character.specializationId] : []
|
|
)),
|
|
allowedCompanionSpecializationIds: onlineActivity?.companionSpecializationIds,
|
|
occupiedHumanRoles: sharedOnlineParty.flatMap((member) => member.role ? [member.role] : []),
|
|
};
|
|
if (simulationMode === "play") {
|
|
party.initializeParty(
|
|
onlineActivity?.id ?? character.id,
|
|
combat.level,
|
|
combat.health,
|
|
playerRole,
|
|
aiPartySize,
|
|
randomizedReadyOnly ? "wow" : character.categoryId ?? "wow",
|
|
companionOptions,
|
|
);
|
|
} else {
|
|
party.initializeSpectatorParty(simulationSeed, combat.level, character.categoryId ?? "wow", companionOptions);
|
|
}
|
|
usePartyStore.getState().syncEquipment(combat.equipment, combat.inventory);
|
|
combat.synchronizeActors();
|
|
combat.applyDefaultPartyBuffs();
|
|
combat.applyPrecombatPreparation();
|
|
resetPartyRuntimeClock();
|
|
}, [character?.id, deviceIncludeBetaSpecs, gameMode, manastormPartySize, onlineActivity?.id,
|
|
onlineActivity?.includeBetaSpecs, onlineGroup?.updatedAt, playerRole, readinessPolicy,
|
|
readinessPolicyRevision, simulationMode, simulationSeed]);
|
|
|
|
useEffect(() => {
|
|
const party = usePartyStore.getState();
|
|
const combat = useCombatStore.getState();
|
|
party.syncLevel(level);
|
|
usePartyStore.getState().syncEquipment(combat.equipment, combat.inventory);
|
|
combat.synchronizeActors();
|
|
combat.applyDefaultPartyBuffs();
|
|
combat.applyPrecombatPreparation();
|
|
}, [level]);
|
|
|
|
useEffect(() => {
|
|
if (mountedResetRevision.current === resetRevision) return;
|
|
mountedResetRevision.current = resetRevision;
|
|
const combat = useCombatStore.getState();
|
|
usePartyStore.getState().resetCombat(combat.level, combat.health);
|
|
usePartyStore.getState().syncEquipment(combat.equipment, combat.inventory);
|
|
combat.synchronizeActors();
|
|
combat.applyDefaultPartyBuffs();
|
|
combat.applyPrecombatPreparation();
|
|
resetPartyRuntimeClock();
|
|
}, [resetRevision]);
|
|
|
|
useEffect(() => useCombatStore.subscribe((state, previous) => {
|
|
if (state.selectedTargetId && state.selectedTargetId !== previous.selectedTargetId) {
|
|
usePartyStore.getState().clearSelection();
|
|
}
|
|
}), []);
|
|
|
|
return null;
|
|
}
|