Compare commits
3
Commits
tamagotchi
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
831c30e504 | ||
|
|
bc366fd408 | ||
|
|
0c40f28e27 |
@@ -1,4 +1,4 @@
|
|||||||
This branch is the BP and RP pack for **The Tamagotchi DLC Map**.
|
This branch is the BP and RP pack for **The BLANK DLC Map or ADDON**.
|
||||||
Each Branch of this repository Should be it's own addon/piece of content.
|
Each Branch of this repository Should be it's own addon/piece of content.
|
||||||
|
|
||||||
If you need to ask any questions regarding any code: Discord momoko_koigakubo
|
If you need to ask any questions regarding any code: Discord momoko_koigakubo
|
||||||
|
|||||||
@@ -3,32 +3,26 @@
|
|||||||
"header": {
|
"header": {
|
||||||
"name": "pack.name",
|
"name": "pack.name",
|
||||||
"description": "pack.description",
|
"description": "pack.description",
|
||||||
"uuid": "4390e189-ec4a-4f43-bc80-555b6c986147",
|
"uuid": "***",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"min_engine_version": "1.26.50"
|
"min_engine_version": "1.26.50"
|
||||||
},
|
},
|
||||||
"modules": [
|
"modules": [
|
||||||
{
|
{
|
||||||
"type": "data",
|
"type": "data",
|
||||||
"uuid": "a06b47ef-e0d9-4154-94c1-9a6bd86e506f",
|
"uuid": "***",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Tamagotchi Scripting",
|
"description": "Test Scripting",
|
||||||
"type": "script",
|
"type": "script",
|
||||||
"uuid": "3dec0970-c9b8-4e64-886a-cdc237cf938d",
|
"uuid": "***",
|
||||||
"version": "1.0.0",
|
"version": [1, 0, 0],
|
||||||
"entry": "scripts/main.js"
|
"entry": "scripts/main.js"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": [
|
|
||||||
{
|
|
||||||
"module_name":"@minecraft/server",
|
|
||||||
"version":"2.10.0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"authors": ["Momoko"],
|
"authors": ["blah"],
|
||||||
"product_type": "addon"
|
"product_type": "addon"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pack.name=The Tamagotchi Resource Pack
|
||||||
|
pack.description=A Resource pack for the Tamagotchi Map
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
* @typedef {object} Region
|
|
||||||
* @property {string} nameKey
|
|
||||||
* @property {number} order
|
|
||||||
* @property {boolean} unlockedAtStart
|
|
||||||
* @property {number} unlockedCost
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Record<string, Region>}
|
|
||||||
*/
|
|
||||||
export const REGIONS = {
|
|
||||||
lagoon: {nameKey: "tama.region.lagoon.name",
|
|
||||||
order: 0, unlockedAtStart: true, unlockedCost: 0},
|
|
||||||
cropcountry: {nameKey: "tama.region.cropcountry.name",
|
|
||||||
order: 1, unlockedAtStart: false, unlockedCost: 100},
|
|
||||||
seaside: {nameKey: "tama.region.seaside.name",
|
|
||||||
order: 2, unlockedAtStart: false, unlockedCost: 500},
|
|
||||||
skyland: {nameKey: "tama.region.skyland.name",
|
|
||||||
order: 3, unlockedAtStart: false, unlockedCost: 1000}
|
|
||||||
};
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
import {
|
|
||||||
CommandPermissionLevel,
|
|
||||||
CustomCommandStatus,
|
|
||||||
CustomCommandParamType,
|
|
||||||
system,
|
|
||||||
} from "@minecraft/server";
|
|
||||||
import { REGIONS } from "../config/regions.js";
|
|
||||||
import { resetGates, resetGate, unlockGate, unlockGates,
|
|
||||||
updateBalance, returnBalance, printGateState} from "../save/state.js";
|
|
||||||
import { unlockRegion } from "../systems/progression.js";
|
|
||||||
|
|
||||||
//the system calls this function we do not
|
|
||||||
//our import into main runs the first line of this etc
|
|
||||||
system.beforeEvents.startup.subscribe(({ customCommandRegistry }) => {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerEnum("rzb_tamagotchi:region", Object.keys(REGIONS));
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:print_gates_states",
|
|
||||||
description: "This command prints the gate states",
|
|
||||||
permissionLevel: CommandPermissionLevel.Host,
|
|
||||||
cheatsRequired: true,
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
system.run(() => {
|
|
||||||
printGateState();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:reset_gates_all",
|
|
||||||
description: "This command resets all gates to default",
|
|
||||||
permissionLevel: CommandPermissionLevel.Host,
|
|
||||||
cheatsRequired: true,
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
system.run(() => {
|
|
||||||
resetGates();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success,
|
|
||||||
message: "Gates reset to default",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:reset_gate",
|
|
||||||
description: "This command resets a single gate",
|
|
||||||
permissionLevel: CommandPermissionLevel.Host,
|
|
||||||
cheatsRequired: true,
|
|
||||||
mandatoryParameters: [
|
|
||||||
{
|
|
||||||
// Use the enum by setting the name to the enum name
|
|
||||||
name: "rzb_tamagotchi:region",
|
|
||||||
type: CustomCommandParamType.Enum,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
(origin, region) => {
|
|
||||||
system.run(() => {
|
|
||||||
resetGate(region);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success,
|
|
||||||
message: "Gate ${REGION[id]} reset to default",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:unlocks_gates_all",
|
|
||||||
description: "This command unlocks all gates",
|
|
||||||
permissionLevel: CommandPermissionLevel.Host,
|
|
||||||
cheatsRequired: true,
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
system.run(() => {
|
|
||||||
unlockGates();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success,
|
|
||||||
message: "All gates Unlocked",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:unlock_gate",
|
|
||||||
description: "This command unlocks a single gate",
|
|
||||||
permissionLevel: CommandPermissionLevel.Host,
|
|
||||||
cheatsRequired: true,
|
|
||||||
mandatoryParameters: [
|
|
||||||
{
|
|
||||||
// Use the enum by setting the name to the enum name
|
|
||||||
name: "rzb_tamagotchi:region",
|
|
||||||
type: CustomCommandParamType.Enum,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
(origin, region) => {
|
|
||||||
system.run(() => {
|
|
||||||
unlockGate(region, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success,
|
|
||||||
message: `Gate ${REGIONS[id]} unlocked`,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:request_unlock",
|
|
||||||
description: "This command calls unlockRegion(), for entities",
|
|
||||||
permissionLevel: CommandPermissionLevel.Any,
|
|
||||||
cheatsRequired: false,
|
|
||||||
mandatoryParameters: [
|
|
||||||
{
|
|
||||||
// Use the enum by setting the name to the enum name
|
|
||||||
name: "rzb_tamagotchi:region",
|
|
||||||
type: CustomCommandParamType.Enum,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
(origin, region) => {
|
|
||||||
system.run(() => {
|
|
||||||
const result = unlockRegion(region);
|
|
||||||
|
|
||||||
// no entity to talk to when run from a command block or console
|
|
||||||
if (!origin.sourceEntity) { return; }
|
|
||||||
|
|
||||||
if (result.ok) {
|
|
||||||
origin.sourceEntity.sendMessage({
|
|
||||||
translate: "tama.unlock.success",
|
|
||||||
with: { rawtext: [{ translate: REGIONS[region].nameKey }] }
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reason codes are turned into player-facing text here.
|
|
||||||
// Every branch produces a RawMessage - a plain string would be
|
|
||||||
// sent literally instead of being looked up in the lang file.
|
|
||||||
let why;
|
|
||||||
switch (result.reason) {
|
|
||||||
case "already_unlocked":
|
|
||||||
why = {
|
|
||||||
translate: "tama.unlock.already_unlocked",
|
|
||||||
with: { rawtext: [{ translate: REGIONS[region].nameKey }] }
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case "missing_prior_region":
|
|
||||||
why = result.requires
|
|
||||||
? {
|
|
||||||
translate: "tama.unlock.missing_prior",
|
|
||||||
with: { rawtext: [{ translate: REGIONS[result.requires].nameKey }] }
|
|
||||||
}
|
|
||||||
: { translate: "tama.unlock.first_region" };
|
|
||||||
break;
|
|
||||||
case "insufficient_funds":
|
|
||||||
why = {
|
|
||||||
translate: "tama.unlock.insufficient_funds",
|
|
||||||
with: [String(result.cost), String(result.balance)]
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case "unknown_region":
|
|
||||||
why = { translate: "tama.unlock.unknown_region" };
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
why = {
|
|
||||||
translate: "tama.unlock.default",
|
|
||||||
with: { rawtext: [{ translate: REGIONS[region].nameKey }] }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
origin.sourceEntity.sendMessage(why);
|
|
||||||
});
|
|
||||||
|
|
||||||
// note: CustomCommandResult.message is typed `string`, so it cannot
|
|
||||||
// carry a RawMessage and can never be translated. All player-facing
|
|
||||||
// text for this command goes through sendMessage above instead.
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
customCommandRegistry.registerCommand(
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:balance_update",
|
|
||||||
description: "This command updates the player balance",
|
|
||||||
permissionLevel: CommandPermissionLevel.Host,
|
|
||||||
cheatsRequired: true,
|
|
||||||
mandatoryParameters: [
|
|
||||||
{
|
|
||||||
name: "rzb_tamagotchi:cost",
|
|
||||||
type: CustomCommandParamType.Integer,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
(origin, cost) => {
|
|
||||||
system.run(() => { //deferred tick so we get return message first
|
|
||||||
updateBalance(cost);
|
|
||||||
|
|
||||||
// the new balance only exists after the deferred update runs,
|
|
||||||
// so report it here rather than in the return value below
|
|
||||||
if (origin.sourceEntity) {
|
|
||||||
origin.sourceEntity.sendMessage(`Your balance is ${returnBalance()}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: CustomCommandStatus.Success,
|
|
||||||
message: `Balance changed by ${cost}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)})
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const DEBUG = true;;
|
|
||||||
const PREFIX = "[TAMA]";
|
|
||||||
|
|
||||||
export function log(message) {
|
|
||||||
if(!DEBUG) return;
|
|
||||||
console.warn(`${PREFIX} : ${message}`);
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { log } from "./core/log.js";
|
|
||||||
import { load } from "./save/state.js";
|
|
||||||
import { getState } from "./save/state.js";
|
|
||||||
import "./core/commands.js"
|
|
||||||
import {world} from "@minecraft/server";
|
|
||||||
log("main.js loaded)");
|
|
||||||
|
|
||||||
/*
|
|
||||||
Dynamic properties have to exist post worldLoad
|
|
||||||
|
|
||||||
1.9 -> 2.0 scripts now load before world load
|
|
||||||
Grabbed data will throw an exception
|
|
||||||
if we don't do things after worldLoad
|
|
||||||
You can't serve a pizza if you don't have a pizza
|
|
||||||
|
|
||||||
Players, entities, blocks
|
|
||||||
Time of day, Gamemode, difficulty
|
|
||||||
*/
|
|
||||||
world.afterEvents.worldLoad.subscribe(() => {
|
|
||||||
load();
|
|
||||||
console.log(JSON.stringify(getState()));
|
|
||||||
});
|
|
||||||
|
|
||||||
//good for debugging gate values
|
|
||||||
//console.log(JSON.stringify(getState()));
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
import { REGIONS } from "../config/regions.js";
|
|
||||||
import { log } from "../core/log.js";
|
|
||||||
import { world } from "@minecraft/server";
|
|
||||||
|
|
||||||
const KEY = "tama.progress";
|
|
||||||
const VERSION = 1; //For updating the json in the save
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The in-memory copy of the whole save document, so we don't re-read the
|
|
||||||
* world's dynamic properties every time something needs a value.
|
|
||||||
* Null until load() runs. saveState() writes it back out to the world save.
|
|
||||||
*
|
|
||||||
* cache = {
|
|
||||||
* version: 1,
|
|
||||||
* coins: 0,
|
|
||||||
* gates: {
|
|
||||||
* lagoon: true,
|
|
||||||
* farmland: false,
|
|
||||||
* seaside: false,
|
|
||||||
* skyland: false
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
let cache = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the save document out of the world and puts it in `cache`.
|
|
||||||
*
|
|
||||||
* Nothing stored under KEY yet means a brand-new world - getDynamicProperty
|
|
||||||
* returns undefined - so build the defaults and write them straight back,
|
|
||||||
* which is what creates the save.
|
|
||||||
*
|
|
||||||
* Otherwise the stored value is JSON text, so parse it back into an object.
|
|
||||||
*/
|
|
||||||
export function load(){
|
|
||||||
const raw = world.getDynamicProperty(KEY);
|
|
||||||
//let raw = undefined;
|
|
||||||
//good for debugging before the value is updated
|
|
||||||
//console.log(raw);
|
|
||||||
|
|
||||||
if(raw === undefined) {
|
|
||||||
cache = buildDefaults();
|
|
||||||
saveState();
|
|
||||||
} else {
|
|
||||||
//good for debugging post update
|
|
||||||
//console.log(raw);
|
|
||||||
cache = JSON.parse(raw);
|
|
||||||
}
|
|
||||||
if(cache.version < VERSION) {
|
|
||||||
//if(version < (VERSION) -> add attribute etc))
|
|
||||||
log("==================================");
|
|
||||||
log(`version: ${cache.version}, code expects ${VERSION}`);
|
|
||||||
log("==================================");
|
|
||||||
//if attribute === undefined -> set default value
|
|
||||||
cache.version = VERSION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a fresh save document for a world that has never been played.
|
|
||||||
*
|
|
||||||
* `gates` is an object (not an array) filled by looping REGIONS and copying
|
|
||||||
* each region's unlockedAtStart value, so adding a region to the config
|
|
||||||
* automatically adds its gate here with no change to this function.
|
|
||||||
*/
|
|
||||||
function buildDefaults() {
|
|
||||||
const gates = {};
|
|
||||||
const coins = 0;
|
|
||||||
for(const id in REGIONS)
|
|
||||||
{
|
|
||||||
gates[id] = REGIONS[id].unlockedAtStart;
|
|
||||||
}
|
|
||||||
return{version: VERSION, gates: gates, coins: coins};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the cached save document.
|
|
||||||
* This is the live object, not a copy - anything that mutates what comes back
|
|
||||||
* must call saveState() afterwards, or the change is lost on world close.
|
|
||||||
*/
|
|
||||||
export function getState() {
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* buildDefaults returns a value,
|
|
||||||
* using .gates returns just the
|
|
||||||
* gates value rather than coins
|
|
||||||
* and other default data
|
|
||||||
*/
|
|
||||||
export function resetGates() {
|
|
||||||
cache.gates = buildDefaults().gates;
|
|
||||||
saveState();
|
|
||||||
}
|
|
||||||
export function resetGate(id) {
|
|
||||||
//resets the gate from the config/region config
|
|
||||||
cache.gates[id] = REGIONS[id].unlockedAtStart;
|
|
||||||
saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a region's gate to T/F and persists the change.
|
|
||||||
* e.g. updateGate("farmland", state) ->
|
|
||||||
* cache.gates["farmland"] = state
|
|
||||||
*
|
|
||||||
* undefined will remove a gate from the cache
|
|
||||||
*/
|
|
||||||
export function unlockGate(nKey, state) {
|
|
||||||
cache.gates[nKey] = state;
|
|
||||||
saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unlockGates() {
|
|
||||||
for(const id in REGIONS) {
|
|
||||||
cache.gates[id] = true;
|
|
||||||
}
|
|
||||||
saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateBalance(cost) {
|
|
||||||
cache.coins += cost;
|
|
||||||
saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function returnBalance(){
|
|
||||||
const value = cache.coins;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function printGateState(){
|
|
||||||
log(JSON.stringify(getState().gates));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the cache out to the world save, where it survives the world closing.
|
|
||||||
*
|
|
||||||
* Returns early if nothing has been loaded yet - writing a null cache would
|
|
||||||
* store the text "null" and corrupt the save.
|
|
||||||
*
|
|
||||||
* Objects are not a permitted dynamic property value (only boolean, number,
|
|
||||||
* string and Vector3), so the document is converted to JSON text first.
|
|
||||||
*/
|
|
||||||
export function saveState() {
|
|
||||||
if(cache === null) return;
|
|
||||||
const text = JSON.stringify(cache);
|
|
||||||
world.setDynamicProperty(KEY, text);
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import { REGIONS } from "../config/regions.js"
|
|
||||||
import { getState, updateBalance, unlockGate, returnBalance } from "../save/state.js"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Can this region be unlocked right now, and if not, why not?
|
|
||||||
*
|
|
||||||
* Returns an outcome object rather than a boolean so callers can explain the
|
|
||||||
* refusal to the player. `reason` is a code, not display text - whoever shows
|
|
||||||
* it is responsible for turning it into a translated message.
|
|
||||||
*
|
|
||||||
* { ok: true }
|
|
||||||
* { ok: false, reason: "unknown_region" } developer error
|
|
||||||
* { ok: false, reason: "already_unlocked" }
|
|
||||||
* { ok: false, reason: "missing_prior_region", requires: "farmland" }
|
|
||||||
* { ok: false, reason: "insufficient_funds", cost: 500, balance: 120 }
|
|
||||||
*
|
|
||||||
* @param {string} regionID - a REGIONS key, e.g. "farmland"
|
|
||||||
*/
|
|
||||||
export function canUnlock(regionID) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
the region's whole config record:
|
|
||||||
{ nameKey, order, unlockedAtStart, unlockedCost}
|
|
||||||
*/
|
|
||||||
const region = REGIONS[regionID];
|
|
||||||
if (region === undefined) {
|
|
||||||
return { ok: false, reason: "unknown_region" };
|
|
||||||
}
|
|
||||||
// order number from the REGIONS section we keyed
|
|
||||||
const order = region.order;
|
|
||||||
// we return the full record.
|
|
||||||
const gates = getState().gates;
|
|
||||||
/*
|
|
||||||
if the records value for that key's order is
|
|
||||||
true: unlocked
|
|
||||||
*/
|
|
||||||
if (gates[regionID] === true) {
|
|
||||||
return { ok: false, reason: "already_unlocked" };
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
WE ARE KEYING FOR THE KEY VALUE'S ORDER PRIOR TO PASSED REGION{RegionID}
|
|
||||||
the prior value has to be true for the passed region to unlock
|
|
||||||
*/
|
|
||||||
let priorRegion = null;
|
|
||||||
for (const id in REGIONS) {
|
|
||||||
// never pass lagoon otherwise all conditions fail
|
|
||||||
if (REGIONS[id].order === order - 1) {
|
|
||||||
/*
|
|
||||||
again tdlr we get the key prior to the past key
|
|
||||||
so for example command canUnlock("seaside");
|
|
||||||
we are retrieving farm land for comparison
|
|
||||||
it's sequential you can't unlock zones non
|
|
||||||
out of order
|
|
||||||
*/
|
|
||||||
priorRegion = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if first region is auto unlocked we will never meet this condition
|
|
||||||
if (priorRegion === null) {
|
|
||||||
return { ok: false, reason: "missing_prior_region", requires: null };
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
the prior region before this one must be open first
|
|
||||||
*/
|
|
||||||
if (gates[priorRegion] !== true) {
|
|
||||||
return { ok: false, reason: "missing_prior_region", requires: priorRegion };
|
|
||||||
}
|
|
||||||
|
|
||||||
//they have to be able to pay for it.
|
|
||||||
const cost = region.unlockedCost;
|
|
||||||
const balance = returnBalance();
|
|
||||||
if (balance < cost) {
|
|
||||||
return { ok: false, reason: "insufficient_funds", cost: cost, balance: balance };
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ok: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlocks a region if the rules allow it, charges the cost, and saves.
|
|
||||||
* object canUnlock produced and can explain what went wrong.
|
|
||||||
*
|
|
||||||
* @param {string} regionID - a REGIONS key, e.g. "farmland"
|
|
||||||
*/
|
|
||||||
export function unlockRegion(regionID) {
|
|
||||||
|
|
||||||
const result = canUnlock(regionID);
|
|
||||||
if (!result.ok) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlockGate(regionID, true);
|
|
||||||
|
|
||||||
/*
|
|
||||||
always make sure things that cost money are passed negative,
|
|
||||||
because otherwise it would add to the balance
|
|
||||||
*/
|
|
||||||
updateBalance(-REGIONS[regionID].unlockedCost);
|
|
||||||
|
|
||||||
return { ok: true };
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
pack.name=The Tamagotchi Resource Pack
|
|
||||||
pack.description=A Resource pack for the Tamagotchi Map
|
|
||||||
|
|
||||||
tama.region.lagoon.name=Lagoon Town
|
|
||||||
tama.region.cropcountry.name=Crop Country
|
|
||||||
tama.region.seaside.name=Seaside
|
|
||||||
tama.region.skyland.name=Skyland
|
|
||||||
|
|
||||||
tama.unlock.already_unlocked=%1 is already unlocked
|
|
||||||
tama.unlock.missing_prior=You must unlock %1 first
|
|
||||||
tama.unlock.insufficient_funds=You need %1 coins, you have %2
|
|
||||||
tama.unlock.first_region=First region is already unlocked
|
|
||||||
tama.unlock.unknown_region=Requested region not found
|
|
||||||
tama.unlock.default=Cannot unlock Region: %1
|
|
||||||
tama.unlock.success=%1 unlocked
|
|
||||||
Reference in New Issue
Block a user