import { _, execute, Objective, type Score, Selector } from "sandstone"; import { type _InputCustomEventType, type _InputVariableType, Actions } from "./types"; import { getChildFunctionName } from "./utils"; /** * All possible events that can be defined in a challenge. */ export type POSSIBLE_SCENARIO_EVENTS = "start_challenge" | "init_participants" | "end_challenge" | "on_tick"; export const VISIBLE_OBJECTIVE = Objective.create("kradle.board", "dummy", [{ text: "Kradle Board", color: "gold" }]); export const HIDDEN_OBJECTIVE = Objective.create("kradle.hidden"); export const WATCHER = "watcher"; export const WEB_VIEWER = "KradleWebViewer"; export const KRADLE_PARTICIPANT_TAG = "kradle_participant"; export const WINNER_TAG = "kradle_winner"; export const DISPLAY_TAG = "***KRADLE***"; export const KRADLE_STORAGE = "kradle_storage"; export const END_STATE_KEY = "end_state"; export const MAX_DURATION = 5 * 60 * 20; // 5 minutes in ticks /// The selector that targets all participants in the game. export const ALL = Selector("@a", { tag: KRADLE_PARTICIPANT_TAG }); export const GAME_STATES = { CREATED: 0, ON: 2, OFF: 1, } as const; /// The variables that are builtin by default in every challenge. /// These variables are used to track the state of the game and the players. /// They can be used in the challenge definition to create end conditions, win conditions, and events. export const BUILTIN_VARIABLES = { death_count: { type: "individual", objective_type: "deathCount", default: 0, }, has_never_died: { type: "individual", updater: (value: Score, { death_count }) => { value.set(0); _.if(death_count.equalTo(0), () => { value.set(1); }); }, }, alive_players: { type: "global", updater: (value: Score, { has_never_died }) => { value.set(0); execute.as(ALL).run(getChildFunctionName("alive_players"), () => { _.if(has_never_died, () => { value.add(1); }); }); }, }, main_score: { type: "individual", default: 0, updater: (value: Score) => { VISIBLE_OBJECTIVE("@s").set(value); }, }, game_timer: { type: "global", default: 0, updater: (value: Score) => { value.add(1); }, }, game_state: { type: "global", default: GAME_STATES.CREATED, }, player_count: { type: "global", default: 0, }, /// This variable is used to assign a unique number to each player, starting from 1. player_number: { type: "individual", objective_type: "dummy", default: 0, updater: (value: Score, { player_count }) => { _.if(value.equalTo(0), () => { player_count.add(1); value.set(player_count); //tellraw("@a", [`${DISPLAY_TAG}`, { selector: "@s" }, "@s is player number ", value]); }); }, }, /// This variable is used to announce in-game deaths death_event: { type: "individual", objective_type: "deathCount", updater: (value: Score) => { _.if(value.greaterThan(0), () => { Actions.announce({ message: [Selector("@s"), " has died!"], }); value.set(0); // Reset the death count after announcing }); }, }, } satisfies Record>; export type BUILTIN_VARIABLE_NAMES = keyof typeof BUILTIN_VARIABLES; export const BUILTIN_SCORE_EVENTS = (variables: Record) => [ { mode: "repeatable", score: variables.main_score, actions: () => { VISIBLE_OBJECTIVE("@s").set(variables.main_score); }, }, ] satisfies _InputCustomEventType[];