prendy
Version:
Make games with prerendered backdrops using babylonjs and repond
109 lines (92 loc) • 3.75 kB
text/typescript
import { breakableForEach, forEach } from "chootils/dist/loops";
import { getState, makeEffects } from "repond";
import { meta } from "../../meta";
import { AnyTriggerName, CharacterName, DollName, PlaceName, StoryCallback, TriggerNameByPlace } from "../../types";
import { getCharDollStuff } from "../prendyUtils/characters";
import { getUsefulStoryStuff } from "./prendyRuleMakers";
export function makeInteractButtonEffects({
onInteractAtTrigger,
onInteractAtTalk,
}: {
onInteractAtTrigger: ReturnType<typeof makeOnInteractAtTrigger>;
onInteractAtTalk: ReturnType<typeof makeOnInteractToTalk>;
}) {
return makeEffects(({ itemEffect, effect }) => ({
whenInteractButtonClicked: itemEffect({
run() {
onInteractAtTrigger();
onInteractAtTalk();
},
check: { prop: "interactButtonPressTime", type: "players" },
// atStepEnd: true,
step: "story", // story insead of input, so virtual stick animations dont overwrite the story click ones
}),
}));
}
// --------------------------------------------------
//
// makeOnInteractAtTrigger
// when pressing interact button at trigger
type OnInteractAtTriggerOptions = Partial<{
[P_PlaceName in PlaceName]: Partial<{
[P_TriggerName in TriggerNameByPlace[P_PlaceName]]: StoryCallback;
}>;
}>;
// the returned function when the interact buttons clicked
export function makeOnInteractAtTrigger(
callBacksObject: OnInteractAtTriggerOptions,
characterNameParam?: CharacterName
) {
const onClickInteractButton = () => {
const { placeInfoByName } = meta.assets!;
const characterName = characterNameParam || meta.assets!.characterNames[0];
const usefulStoryStuff = getUsefulStoryStuff();
const { aConvoIsHappening, nowPlaceName, playerMovingPaused } = usefulStoryStuff.globalState;
if (aConvoIsHappening || playerMovingPaused) return;
const { atTriggers } = getState().characters[characterName];
const triggerNames = placeInfoByName[nowPlaceName].triggerNames as AnyTriggerName[];
// NOTE Could b breakable if only checking one trigger
forEach(triggerNames, (triggerName) => {
if (atTriggers[triggerName]) {
// removing types to fix issue
(callBacksObject as Record<any, any>)[nowPlaceName]?.[triggerName]?.(usefulStoryStuff);
}
});
};
return onClickInteractButton;
}
// --------------------------------------------------
//
// makeOnInteractToTalk
// when 'talking' to a doll
type OnInteractToTalkOptions = Partial<{
[P_DollName in DollName]: StoryCallback;
}>;
// the returned function gets run when interact button's clicked
export function makeOnInteractToTalk(
callBacksObject: OnInteractToTalkOptions,
distanceType: "touch" | "talk" = "talk",
characterNameParam?: CharacterName
) {
const onClickInteractButton = () => {
const characterName = characterNameParam || meta.assets!.characterNames[0];
const { dollNames } = meta.assets!;
const usefulStoryStuff = getUsefulStoryStuff();
const { aConvoIsHappening, playerMovingPaused } = usefulStoryStuff.globalState;
if (aConvoIsHappening || playerMovingPaused) return;
const { dollState, dollRefs: charDollRefs, dollName: charDollName } = getCharDollStuff(characterName) ?? {};
if (!dollState) return;
const { inRange } = dollState;
breakableForEach(dollNames, (dollName) => {
const dollState = getState().dolls[dollName];
const callBackToRun = callBacksObject[dollName];
const isInTalkRange = inRange[dollName][distanceType];
// && dollState.isVisible
if (dollName !== charDollName && isInTalkRange) {
callBackToRun?.(usefulStoryStuff);
return true; // break
}
});
};
return onClickInteractButton;
}