mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Prepare the achievements update
This commit is contained in:
parent
837b0d8007
commit
226149a40f
@ -62,7 +62,8 @@
|
|||||||
"webpack-plugin-replace": "^1.1.1",
|
"webpack-plugin-replace": "^1.1.1",
|
||||||
"webpack-strip-block": "^0.2.0",
|
"webpack-strip-block": "^0.2.0",
|
||||||
"whatwg-fetch": "^3.0.0",
|
"whatwg-fetch": "^3.0.0",
|
||||||
"worker-loader": "^2.0.0"
|
"worker-loader": "^2.0.0",
|
||||||
|
"yaml": "^1.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^9.4.3",
|
"autoprefixer": "^9.4.3",
|
||||||
|
@ -25,6 +25,7 @@ function gulptasksTranslations($, gulp) {
|
|||||||
files
|
files
|
||||||
.filter(name => name.endsWith(".yaml"))
|
.filter(name => name.endsWith(".yaml"))
|
||||||
.forEach(fname => {
|
.forEach(fname => {
|
||||||
|
console.log("Loading", fname);
|
||||||
const languageName = fname.replace(".yaml", "");
|
const languageName = fname.replace(".yaml", "");
|
||||||
const abspath = path.join(translationsSourceDir, fname);
|
const abspath = path.join(translationsSourceDir, fname);
|
||||||
|
|
||||||
@ -40,39 +41,13 @@ function gulptasksTranslations($, gulp) {
|
|||||||
|
|
||||||
${storePage.intro.replace(/\n/gi, "\n\n")}
|
${storePage.intro.replace(/\n/gi, "\n\n")}
|
||||||
|
|
||||||
[h2]${storePage.title_advantages}[/h2]
|
[h2]${storePage.what_others_say}[/h2]
|
||||||
|
|
||||||
[list]
|
[list]
|
||||||
${storePage.advantages
|
[*] [i]${storePage.northernlion_comment}[/i] [b]- Northernlion, YouTube[/b]
|
||||||
.map(x => "[*] " + x.replace(/<b>/, "[b]").replace(/<\/b>/, "[/b]"))
|
[*] [i]${storePage.notch_comment}[/i] [b]- Notch[/b]
|
||||||
.join("\n")}
|
[*] [i]${storePage.steam_review_comment}[/i] [b]- Steam User[/b]
|
||||||
[/list]
|
[/list]
|
||||||
|
|
||||||
[h2]${storePage.title_future}[/h2]
|
|
||||||
|
|
||||||
[list]
|
|
||||||
${storePage.planned
|
|
||||||
.map(x => "[*] " + x.replace(/<b>/, "[b]").replace(/<\/b>/, "[/b]"))
|
|
||||||
.join("\n")}
|
|
||||||
[/list]
|
|
||||||
|
|
||||||
[h2]${storePage.title_open_source}[/h2]
|
|
||||||
|
|
||||||
${storePage.text_open_source.replace(/\n/gi, "\n\n")}
|
|
||||||
|
|
||||||
[h2]${storePage.title_links}[/h2]
|
|
||||||
|
|
||||||
[list]
|
|
||||||
[*] [url=https://discord.com/invite/HN7EVzV]${storePage.links.discord}[/url]
|
|
||||||
[*] [url=https://trello.com/b/ISQncpJP/shapezio]${storePage.links.roadmap}[/url]
|
|
||||||
[*] [url=https://www.reddit.com/r/shapezio]${storePage.links.subreddit}[/url]
|
|
||||||
[*] [url=https://github.com/tobspr/shapez.io]${storePage.links.source_code}[/url]
|
|
||||||
[*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]${
|
|
||||||
storePage.links.translate
|
|
||||||
}[/url]
|
|
||||||
[/list]
|
|
||||||
|
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
fs.writeFileSync(destpath, trim(content.replace(/(\n[ \t\r]*)/gi, "\n")), {
|
fs.writeFileSync(destpath, trim(content.replace(/(\n[ \t\r]*)/gi, "\n")), {
|
||||||
|
23902
gulp/yarn.lock
23902
gulp/yarn.lock
File diff suppressed because it is too large
Load Diff
BIN
res/ui/changelog_skins/achievements.noinline.png
Normal file
BIN
res/ui/changelog_skins/achievements.noinline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 479 KiB |
18
src/css/changelog_skins.scss
Normal file
18
src/css/changelog_skins.scss
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[data-changelog-skin="achievements"] {
|
||||||
|
background: #f8f8f8;
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
background: rgba(0, 10, 20, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include S(border-radius, 5px);
|
||||||
|
&::before {
|
||||||
|
content: " ";
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
background: uiResource("changelog_skins/achievements.noinline.png") center center / cover no-repeat !important;
|
||||||
|
@include S(height, 80px);
|
||||||
|
@include S(border-radius, 5px);
|
||||||
|
@include S(margin-bottom, 5px);
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@
|
|||||||
@import "application_error";
|
@import "application_error";
|
||||||
@import "textual_game_state";
|
@import "textual_game_state";
|
||||||
@import "adinplay";
|
@import "adinplay";
|
||||||
|
@import "changelog_skins";
|
||||||
|
|
||||||
@import "states/preload";
|
@import "states/preload";
|
||||||
@import "states/main_menu";
|
@import "states/main_menu";
|
||||||
@ -119,11 +120,3 @@ body.uiHidden {
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body.modalDialogActive,
|
|
||||||
body.externalAdOpen,
|
|
||||||
body.ingameDialogOpen {
|
|
||||||
> *:not(.ingameDialog):not(.modalDialogParent):not(.loadingDialog):not(.gameLoadingOverlay):not(#ingame_HUD_ModalDialogs):not(.noBlur) {
|
|
||||||
// filter: blur(5px) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -184,7 +184,7 @@
|
|||||||
.updateLabel {
|
.updateLabel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translateX(50%) rotate(-5deg);
|
transform: translateX(50%) rotate(-5deg);
|
||||||
color: rgb(231, 78, 58);
|
color: rgb(133, 58, 231);
|
||||||
@include Heading;
|
@include Heading;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@include S(right, 40px);
|
@include S(right, 40px);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: #eef1f4;
|
background: #eef1f4;
|
||||||
|
@include S(border-radius, 3px);
|
||||||
|
|
||||||
@include DarkThemeOverride {
|
@include DarkThemeOverride {
|
||||||
background: #424242;
|
background: #424242;
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
export const CHANGELOG = [
|
export const CHANGELOG = [
|
||||||
{
|
{
|
||||||
version: "1.2.3",
|
version: "1.3.0",
|
||||||
date: "unreleased",
|
date: "12.03.2020",
|
||||||
|
skin: "achievements",
|
||||||
entries: [
|
entries: [
|
||||||
|
"There are now <strong>45 Steam Achievements!</strong>",
|
||||||
"Fixed constant signals being editable from the regular layer",
|
"Fixed constant signals being editable from the regular layer",
|
||||||
"Fixed items still overlapping sometimes between buildings and belts",
|
"Fixed items still overlapping sometimes between buildings and belts",
|
||||||
|
"Updated translations (Thanks to all contributors!)",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -12,8 +12,6 @@ const logger = createLogger("achievement_proxy");
|
|||||||
|
|
||||||
const ROTATER = "rotater";
|
const ROTATER = "rotater";
|
||||||
const DEFAULT = "default";
|
const DEFAULT = "default";
|
||||||
const BELT = "belt";
|
|
||||||
const LEVEL_26 = 26;
|
|
||||||
|
|
||||||
export class AchievementProxy {
|
export class AchievementProxy {
|
||||||
/** @param {GameRoot} root */
|
/** @param {GameRoot} root */
|
||||||
@ -22,7 +20,9 @@ export class AchievementProxy {
|
|||||||
this.provider = this.root.app.achievementProvider;
|
this.provider = this.root.app.achievementProvider;
|
||||||
this.disabled = true;
|
this.disabled = true;
|
||||||
|
|
||||||
if (!this.provider.hasAchievements()) {
|
if (G_IS_DEV && globalConfig.debug.testAchievements) {
|
||||||
|
// still enable the proxy
|
||||||
|
} else if (!this.provider.hasAchievements()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,8 @@ export class AchievementProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.provider.onLoad(this.root)
|
this.provider
|
||||||
|
.onLoad(this.root)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.disabled = false;
|
this.disabled = false;
|
||||||
logger.log("Recieving achievement signals");
|
logger.log("Recieving achievement signals");
|
||||||
@ -50,6 +51,8 @@ export class AchievementProxy {
|
|||||||
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.darkMode);
|
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.darkMode);
|
||||||
|
|
||||||
if (this.has(ACHIEVEMENTS.mam)) {
|
if (this.has(ACHIEVEMENTS.mam)) {
|
||||||
|
this.root.signals.entityAdded.add(this.onMamFailure, this);
|
||||||
|
this.root.signals.entityDestroyed.add(this.onMamFailure, this);
|
||||||
this.root.signals.storyGoalCompleted.add(this.onStoryGoalCompleted, this);
|
this.root.signals.storyGoalCompleted.add(this.onStoryGoalCompleted, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +60,6 @@ export class AchievementProxy {
|
|||||||
this.root.signals.entityAdded.add(this.onEntityAdded, this);
|
this.root.signals.entityAdded.add(this.onEntityAdded, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.has(ACHIEVEMENTS.noBeltUpgradesUntilBp)) {
|
|
||||||
this.root.signals.upgradePurchased.add(this.onUpgradePurchased, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.startSlice();
|
this.startSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,27 +72,38 @@ export class AchievementProxy {
|
|||||||
// Every other slice
|
// Every other slice
|
||||||
if (this.sliceIteration % 2 === 0) {
|
if (this.sliceIteration % 2 === 0) {
|
||||||
this.root.signals.bulkAchievementCheck.dispatch(
|
this.root.signals.bulkAchievementCheck.dispatch(
|
||||||
ACHIEVEMENTS.throughputBp25, this.sliceTime,
|
ACHIEVEMENTS.throughputBp25,
|
||||||
ACHIEVEMENTS.throughputBp50, this.sliceTime,
|
this.sliceTime,
|
||||||
ACHIEVEMENTS.throughputLogo25, this.sliceTime,
|
ACHIEVEMENTS.throughputBp50,
|
||||||
ACHIEVEMENTS.throughputLogo50, this.sliceTime,
|
this.sliceTime,
|
||||||
ACHIEVEMENTS.throughputRocket10, this.sliceTime,
|
ACHIEVEMENTS.throughputLogo25,
|
||||||
ACHIEVEMENTS.throughputRocket20, this.sliceTime
|
this.sliceTime,
|
||||||
|
ACHIEVEMENTS.throughputLogo50,
|
||||||
|
this.sliceTime,
|
||||||
|
ACHIEVEMENTS.throughputRocket10,
|
||||||
|
this.sliceTime,
|
||||||
|
ACHIEVEMENTS.throughputRocket20,
|
||||||
|
this.sliceTime
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every 3rd slice
|
// Every 3rd slice
|
||||||
if (this.sliceIteration % 3 === 0) {
|
if (this.sliceIteration % 3 === 0) {
|
||||||
this.root.signals.bulkAchievementCheck.dispatch(
|
this.root.signals.bulkAchievementCheck.dispatch(
|
||||||
ACHIEVEMENTS.play1h, this.sliceTime,
|
ACHIEVEMENTS.play1h,
|
||||||
ACHIEVEMENTS.play10h, this.sliceTime,
|
this.sliceTime,
|
||||||
ACHIEVEMENTS.play20h, this.sliceTime
|
ACHIEVEMENTS.play10h,
|
||||||
|
this.sliceTime,
|
||||||
|
ACHIEVEMENTS.play20h,
|
||||||
|
this.sliceTime
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every 10th slice
|
// Every 10th slice
|
||||||
if (this.sliceIteration % 10 === 0) {
|
if (this.sliceIteration % 10 === 0) {
|
||||||
this.provider.collection.clean();
|
if (this.provider.collection) {
|
||||||
|
this.provider.collection.clean();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.sliceIteration === this.sliceIterationLimit) {
|
if (this.sliceIteration === this.sliceIterationLimit) {
|
||||||
@ -118,6 +128,9 @@ export class AchievementProxy {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
has(key) {
|
has(key) {
|
||||||
|
if (!this.provider.collection) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return this.provider.collection.map.has(key);
|
return this.provider.collection.map.has(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +140,7 @@ export class AchievementProxy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const building = getBuildingDataFromCode(entity.components.StaticMapEntity.code)
|
const building = getBuildingDataFromCode(entity.components.StaticMapEntity.code);
|
||||||
|
|
||||||
if (building.metaInstance.id !== ROTATER) {
|
if (building.metaInstance.id !== ROTATER) {
|
||||||
return;
|
return;
|
||||||
@ -143,28 +156,18 @@ export class AchievementProxy {
|
|||||||
|
|
||||||
/** @param {number} level */
|
/** @param {number} level */
|
||||||
onStoryGoalCompleted(level) {
|
onStoryGoalCompleted(level) {
|
||||||
if (level === LEVEL_26) {
|
if (level > 26) {
|
||||||
this.root.signals.entityAdded.add(this.onMamFailure, this);
|
this.root.signals.entityAdded.add(this.onMamFailure, this);
|
||||||
this.root.signals.entityDestroyed.add(this.onMamFailure, this);
|
this.root.signals.entityDestroyed.add(this.onMamFailure, this);
|
||||||
} else if (level === LEVEL_26 + 1) {
|
|
||||||
this.root.signals.storyGoalCompleted.remove(this.onStoryGoalCompleted, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.root.signals.achievementCheck.dispatch(ACHIEVEMENTS.mam);
|
||||||
|
|
||||||
|
// reset on every level
|
||||||
|
this.root.savegame.currentData.stats.failedMam = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMamFailure() {
|
onMamFailure() {
|
||||||
this.root.savegame.currentData.stats.failedMam = true;
|
this.root.savegame.currentData.stats.failedMam = true;
|
||||||
this.root.signals.entityAdded.remove(this.onMamFailure);
|
|
||||||
this.root.signals.entityDestroyed.remove(this.onMamFailure);
|
|
||||||
this.root.signals.storyGoalCompleted.remove(this.onStoryGoalCompleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param {string} upgrade */
|
|
||||||
onUpgradePurchased(upgrade) {
|
|
||||||
if (upgrade !== BELT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.root.savegame.currentData.stats.upgradedBelt = true;
|
|
||||||
this.root.signals.upgradePurchased.remove(this.onUpgradePurchased);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ export class GameRoot {
|
|||||||
|
|
||||||
// Called with an achievement key and necessary args to validate it can be unlocked.
|
// Called with an achievement key and necessary args to validate it can be unlocked.
|
||||||
achievementCheck: /** @type {TypedSignal<[string, *]>} */ (new Signal()),
|
achievementCheck: /** @type {TypedSignal<[string, *]>} */ (new Signal()),
|
||||||
bulkAchievementCheck: /** @type {TypedSignal<[string, any]...>} */ (new Signal()),
|
bulkAchievementCheck: /** @type {TypedSignal<(string|any)[]>} */ (new Signal()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// RNG's
|
// RNG's
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
import { Application } from "../application";
|
import { Application } from "../application";
|
||||||
import { StorageComponent } from "../game/components/storage";
|
|
||||||
import { ShapeItem } from "../game/items/shape_item";
|
|
||||||
import { Entity } from "../game/entity";
|
import { Entity } from "../game/entity";
|
||||||
import { GameRoot } from "../game/root";
|
import { GameRoot } from "../game/root";
|
||||||
import { ShapeDefinition } from "../game/shape_definition";
|
import { ShapeDefinition } from "../game/shape_definition";
|
||||||
|
import { THEMES } from "../game/theme";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { enumAnalyticsDataSource } from "../game/production_analytics";
|
||||||
|
import { ShapeItem } from "../game/items/shape_item";
|
||||||
|
|
||||||
export const ACHIEVEMENTS = {
|
export const ACHIEVEMENTS = {
|
||||||
belt500Tiles: "belt500Tiles",
|
belt500Tiles: "belt500Tiles",
|
||||||
blueprint100k: "blueprint100k",
|
blueprint100k: "blueprint100k",
|
||||||
@ -55,16 +57,16 @@ export const ACHIEVEMENTS = {
|
|||||||
upgradesTier8: "upgradesTier8",
|
upgradesTier8: "upgradesTier8",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @type {keyof typeof THEMES} */
|
||||||
const DARK_MODE = "dark";
|
const DARK_MODE = "dark";
|
||||||
|
|
||||||
const HOUR_1 = 3600; // Seconds
|
const HOUR_1 = 3600; // Seconds
|
||||||
const HOUR_10 = HOUR_1 * 10;
|
const HOUR_10 = HOUR_1 * 10;
|
||||||
const HOUR_20 = HOUR_1 * 20;
|
const HOUR_20 = HOUR_1 * 20;
|
||||||
const ITEM_SHAPE = "shape";
|
const ITEM_SHAPE = ShapeItem.getId();
|
||||||
const MINUTE_30 = 1800; // Seconds
|
const MINUTE_30 = 1800; // Seconds
|
||||||
const MINUTE_60 = MINUTE_30 * 2;
|
const MINUTE_60 = MINUTE_30 * 2;
|
||||||
const MINUTE_120 = MINUTE_30 * 4;
|
const MINUTE_120 = MINUTE_30 * 4;
|
||||||
const PRODUCED = "produced";
|
|
||||||
const RATE_SLICE_COUNT = 10;
|
|
||||||
const ROTATER_CCW_CODE = 12;
|
const ROTATER_CCW_CODE = 12;
|
||||||
const ROTATER_180_CODE = 13;
|
const ROTATER_180_CODE = 13;
|
||||||
const SHAPE_BP = "CbCbCbRb:CwCwCwCw";
|
const SHAPE_BP = "CbCbCbRb:CwCwCwCw";
|
||||||
@ -72,9 +74,15 @@ const SHAPE_LOGO = "RuCw--Cw:----Ru--";
|
|||||||
const SHAPE_MS_LOGO = "RgRyRbRr";
|
const SHAPE_MS_LOGO = "RgRyRbRr";
|
||||||
const SHAPE_OLD_LEVEL_17 = "WrRgWrRg:CwCrCwCr:SgSgSgSg";
|
const SHAPE_OLD_LEVEL_17 = "WrRgWrRg:CwCrCwCr:SgSgSgSg";
|
||||||
const SHAPE_ROCKET = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
|
const SHAPE_ROCKET = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw";
|
||||||
|
|
||||||
|
/** @type {Layer} */
|
||||||
const WIRE_LAYER = "wires";
|
const WIRE_LAYER = "wires";
|
||||||
|
|
||||||
export class AchievementProviderInterface {
|
export class AchievementProviderInterface {
|
||||||
|
/* typehints:start */
|
||||||
|
collection = /** @type {AchievementCollection|undefined} */ (null);
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
/** @param {Application} app */
|
/** @param {Application} app */
|
||||||
constructor(app) {
|
constructor(app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
@ -135,9 +143,7 @@ export class Achievement {
|
|||||||
this.signal = null;
|
this.signal = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
isValid() {
|
isValid() {
|
||||||
return true;
|
return true;
|
||||||
@ -193,19 +199,16 @@ export class AchievementCollection {
|
|||||||
this.add(ACHIEVEMENTS.logoBefore18, {
|
this.add(ACHIEVEMENTS.logoBefore18, {
|
||||||
isRelevant: this.isLogoBefore18Relevant,
|
isRelevant: this.isLogoBefore18Relevant,
|
||||||
isValid: this.isLogoBefore18Valid,
|
isValid: this.isLogoBefore18Valid,
|
||||||
signal: "itemProduced"
|
signal: "itemProduced",
|
||||||
});
|
});
|
||||||
this.add(ACHIEVEMENTS.mam, {
|
this.add(ACHIEVEMENTS.mam, {
|
||||||
isRelevant: this.isMamRelevant,
|
|
||||||
isValid: this.isMamValid,
|
isValid: this.isMamValid,
|
||||||
signal: "storyGoalCompleted",
|
|
||||||
});
|
});
|
||||||
this.add(ACHIEVEMENTS.mapMarkers15, {
|
this.add(ACHIEVEMENTS.mapMarkers15, {
|
||||||
isRelevant: this.isMapMarkers15Relevant,
|
isRelevant: this.isMapMarkers15Relevant,
|
||||||
isValid: this.isMapMarkers15Valid,
|
isValid: this.isMapMarkers15Valid,
|
||||||
});
|
});
|
||||||
this.add(ACHIEVEMENTS.noBeltUpgradesUntilBp, {
|
this.add(ACHIEVEMENTS.noBeltUpgradesUntilBp, {
|
||||||
init: this.initNoBeltUpgradesUntilBp,
|
|
||||||
isRelevant: this.isNoBeltUpgradesUntilBpRelevant,
|
isRelevant: this.isNoBeltUpgradesUntilBpRelevant,
|
||||||
isValid: this.isNoBeltUpgradesUntilBpValid,
|
isValid: this.isNoBeltUpgradesUntilBpValid,
|
||||||
signal: "storyGoalCompleted",
|
signal: "storyGoalCompleted",
|
||||||
@ -354,7 +357,8 @@ export class AchievementCollection {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
achievement.unlock()
|
achievement
|
||||||
|
.unlock()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.onActivate(null, key);
|
this.onActivate(null, key);
|
||||||
})
|
})
|
||||||
@ -380,12 +384,13 @@ export class AchievementCollection {
|
|||||||
/** @param {string} key - Maps to an Achievement */
|
/** @param {string} key - Maps to an Achievement */
|
||||||
remove(key) {
|
remove(key) {
|
||||||
const achievement = this.map.get(key);
|
const achievement = this.map.get(key);
|
||||||
|
if (achievement) {
|
||||||
|
if (achievement.receiver) {
|
||||||
|
this.root.signals[achievement.signal].remove(achievement.receiver);
|
||||||
|
}
|
||||||
|
|
||||||
if (achievement.receiver) {
|
this.map.delete(key);
|
||||||
this.root.signals[achievement.signal].remove(achievement.receiver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.map.delete(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -447,7 +452,7 @@ export class AchievementCollection {
|
|||||||
createLevelOptions(level) {
|
createLevelOptions(level) {
|
||||||
return {
|
return {
|
||||||
isRelevant: () => this.root.hubGoals.level < level,
|
isRelevant: () => this.root.hubGoals.level < level,
|
||||||
isValid: (currentLevel) => currentLevel === level,
|
isValid: currentLevel => currentLevel === level,
|
||||||
signal: "storyGoalCompleted",
|
signal: "storyGoalCompleted",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -455,17 +460,19 @@ export class AchievementCollection {
|
|||||||
createRateOptions(shape, rate) {
|
createRateOptions(shape, rate) {
|
||||||
return {
|
return {
|
||||||
isValid: () => {
|
isValid: () => {
|
||||||
return this.root.productionAnalytics.getCurrentShapeRate(
|
return (
|
||||||
PRODUCED,
|
this.root.productionAnalytics.getCurrentShapeRate(
|
||||||
this.root.shapeDefinitionMgr.getShapeFromShortKey(shape)
|
enumAnalyticsDataSource.delivered,
|
||||||
) >= rate;
|
this.root.shapeDefinitionMgr.getShapeFromShortKey(shape)
|
||||||
}
|
) >= rate
|
||||||
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
createShapeOptions(shape) {
|
createShapeOptions(shape) {
|
||||||
return {
|
return {
|
||||||
isValid: (item) => this.isShape(item, shape),
|
isValid: item => this.isShape(item, shape),
|
||||||
signal: "itemProduced",
|
signal: "itemProduced",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -473,7 +480,7 @@ export class AchievementCollection {
|
|||||||
createSpeedOptions(level, time) {
|
createSpeedOptions(level, time) {
|
||||||
return {
|
return {
|
||||||
isRelevant: () => this.root.hubGoals.level <= level && this.root.time.now() < time,
|
isRelevant: () => this.root.hubGoals.level <= level && this.root.time.now() < time,
|
||||||
isValid: (currentLevel) => currentLevel === level && this.root.time.now() < time,
|
isValid: currentLevel => currentLevel === level && this.root.time.now() < time,
|
||||||
signal: "storyGoalCompleted",
|
signal: "storyGoalCompleted",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -500,18 +507,12 @@ export class AchievementCollection {
|
|||||||
|
|
||||||
/** @param {ShapeDefinition} definition @returns {boolean} */
|
/** @param {ShapeDefinition} definition @returns {boolean} */
|
||||||
isBlueprint100kValid(definition) {
|
isBlueprint100kValid(definition) {
|
||||||
return (
|
return definition.cachedHash === SHAPE_BP && this.root.hubGoals.storedShapes[SHAPE_BP] >= 100000;
|
||||||
definition.cachedHash === SHAPE_BP &&
|
|
||||||
this.root.hubGoals.storedShapes[SHAPE_BP] >= 100000
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {ShapeDefinition} definition @returns {boolean} */
|
/** @param {ShapeDefinition} definition @returns {boolean} */
|
||||||
isBlueprint1mValid(definition) {
|
isBlueprint1mValid(definition) {
|
||||||
return (
|
return definition.cachedHash === SHAPE_BP && this.root.hubGoals.storedShapes[SHAPE_BP] >= 1000000;
|
||||||
definition.cachedHash === SHAPE_BP &&
|
|
||||||
this.root.hubGoals.storedShapes[SHAPE_BP] >= 1000000
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
@ -530,14 +531,18 @@ export class AchievementCollection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (definition.cachedHash === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const upgrades = this.root.gameMode.getUpgrades();
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
for (let upgradeId in upgrades) {
|
for (let upgradeId in upgrades) {
|
||||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
for (const tier in upgrades[upgradeId]) {
|
||||||
const requiredShapes = upgrades[upgradeId][currentTier].required;
|
const requiredShapes = upgrades[upgradeId][tier].required;
|
||||||
|
for (let i = 0; i < requiredShapes.length; i++) {
|
||||||
for (let i = 0; i < requiredShapes.length; i++) {
|
if (definition.cachedHash === requiredShapes[i].shape) {
|
||||||
if (definition.cachedHash === requiredShapes[i].shape) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,28 +560,9 @@ export class AchievementCollection {
|
|||||||
return this.root.hubGoals.level < 18 && this.isShape(item, SHAPE_LOGO);
|
return this.root.hubGoals.level < 18 && this.isShape(item, SHAPE_LOGO);
|
||||||
}
|
}
|
||||||
|
|
||||||
initMam() {
|
|
||||||
const stats = this.root.savegame.currentData.stats;
|
|
||||||
|
|
||||||
if (stats.failedMam === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.root.hubGoals.level === 26 && stats.failedMam === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.failedMam = this.root.hubGoals.level < 26;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @returns {boolean} */
|
|
||||||
isMamRelevant() {
|
|
||||||
return this.root.hubGoals.level <= 26 && !this.root.savegame.currentData.stats.failedMam;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @params {number} level @returns {boolean} */
|
/** @params {number} level @returns {boolean} */
|
||||||
isMamValid(level) {
|
isMamValid() {
|
||||||
return level === 27 && !this.root.savegame.currentData.stats.failedMam;
|
return this.root.hubGoals.level > 27 && !this.root.savegame.currentData.stats.failedMam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
@ -589,16 +575,6 @@ export class AchievementCollection {
|
|||||||
return count === 15;
|
return count === 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
initNoBeltUpgradesUntilBp() {
|
|
||||||
const stats = this.root.savegame.currentData.stats;
|
|
||||||
|
|
||||||
if (stats.upgradedBelt === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.upgradedBelt = this.root.hubGoals.upgradeLevels.belt > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
isNoBeltUpgradesUntilBpRelevant() {
|
isNoBeltUpgradesUntilBpRelevant() {
|
||||||
return this.root.hubGoals.level <= 12 && this.root.hubGoals.upgradeLevels.belt === 0;
|
return this.root.hubGoals.level <= 12 && this.root.hubGoals.upgradeLevels.belt === 0;
|
||||||
@ -631,8 +607,7 @@ export class AchievementCollection {
|
|||||||
|
|
||||||
/** @returns {boolean} */
|
/** @returns {boolean} */
|
||||||
isNoInverseRotaterRelevant() {
|
isNoInverseRotaterRelevant() {
|
||||||
return this.root.hubGoals.level < 14 &&
|
return this.root.hubGoals.level < 14 && !this.root.savegame.currentData.stats.usedInverseRotater;
|
||||||
!this.root.savegame.currentData.stats.usedInverseRotater;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {number} level @returns {boolean} */
|
/** @param {number} level @returns {boolean} */
|
||||||
|
@ -203,12 +203,11 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
|||||||
if (G_IS_DEV && globalConfig.debug.testAchievements) {
|
if (G_IS_DEV && globalConfig.debug.testAchievements) {
|
||||||
this.app.achievementProvider = new SteamAchievementProvider(this.app);
|
this.app.achievementProvider = new SteamAchievementProvider(this.app);
|
||||||
|
|
||||||
return this.app.achievementProvider.initialize()
|
return this.app.achievementProvider.initialize().catch(err => {
|
||||||
.catch(err => {
|
logger.error("Failed to initialize achievement provider, disabling:", err);
|
||||||
logger.error("Failed to initialize achievement provider, disabling:", err);
|
|
||||||
|
|
||||||
this.app.achievementProvider = new NoAchievementProvider(this.app);
|
this.app.achievementProvider = new NoAchievementProvider(this.app);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.app.achievementProvider.initialize();
|
return this.app.achievementProvider.initialize();
|
||||||
|
@ -78,7 +78,11 @@ export class Savegame extends ReadWriteProxy {
|
|||||||
return {
|
return {
|
||||||
version: this.getCurrentVersion(),
|
version: this.getCurrentVersion(),
|
||||||
dump: null,
|
dump: null,
|
||||||
stats: {},
|
stats: {
|
||||||
|
failedMam: false,
|
||||||
|
trashedCount: 0,
|
||||||
|
usedInverseRotater: false,
|
||||||
|
},
|
||||||
lastUpdate: Date.now(),
|
lastUpdate: Date.now(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ export class SavegameInterface_V1008 extends SavegameInterface_V1007 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(data.stats, {
|
Object.assign(data.stats, {
|
||||||
failedMam: false,
|
failedMam: true,
|
||||||
trashedCount: 0,
|
trashedCount: 0,
|
||||||
usedInverseRotater: false
|
usedInverseRotater: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ export class ChangelogState extends TextualGameState {
|
|||||||
for (let i = 0; i < entries.length; ++i) {
|
for (let i = 0; i < entries.length; ++i) {
|
||||||
const entry = entries[i];
|
const entry = entries[i];
|
||||||
html += `
|
html += `
|
||||||
<div class="entry">
|
<div class="entry" data-changelog-skin="${entry.skin || "default"}">
|
||||||
<span class="version">${entry.version}</span>
|
<span class="version">${entry.version}</span>
|
||||||
<span class="date">${entry.date}</span>
|
<span class="date">${entry.date}</span>
|
||||||
<ul class="changes">
|
<ul class="changes">
|
||||||
|
@ -66,7 +66,7 @@ export class MainMenuState extends GameState {
|
|||||||
<img src="${cachebust(
|
<img src="${cachebust(
|
||||||
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
|
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
|
||||||
)}" alt="shapez.io Logo">
|
)}" alt="shapez.io Logo">
|
||||||
<span class="updateLabel">v${G_BUILD_VERSION}</span>
|
<span class="updateLabel">v${G_BUILD_VERSION} - Achievements!</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mainWrapper ${showDemoBadges ? "demo" : "noDemo"}">
|
<div class="mainWrapper ${showDemoBadges ? "demo" : "noDemo"}">
|
||||||
|
@ -199,7 +199,9 @@ export class PreloadState extends GameState {
|
|||||||
for (let i = 0; i < changelogEntries.length; ++i) {
|
for (let i = 0; i < changelogEntries.length; ++i) {
|
||||||
const entry = changelogEntries[i];
|
const entry = changelogEntries[i];
|
||||||
dialogHtml += `
|
dialogHtml += `
|
||||||
<div class="changelogDialogEntry">
|
<div class="changelogDialogEntry" data-changelog-skin="${
|
||||||
|
entry.skin || "default"
|
||||||
|
}">
|
||||||
<span class="version">${entry.version}</span>
|
<span class="version">${entry.version}</span>
|
||||||
<span class="date">${entry.date}</span>
|
<span class="date">${entry.date}</span>
|
||||||
<ul class="changes">
|
<ul class="changes">
|
||||||
|
@ -30,49 +30,20 @@ steamPage:
|
|||||||
intro: >-
|
intro: >-
|
||||||
Do you like automation games? Then you are in the right place!
|
Do you like automation games? Then you are in the right place!
|
||||||
|
|
||||||
shapez.io is a relaxed game in which you have to build factories for the automated production of geometric shapes. As the level increases, the shapes become more and more complex, and you
|
shapez.io is a relaxed game in which you have to build factories for the automated production of geometric shapes. As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map.
|
||||||
have to spread out on the infinite map.
|
|
||||||
|
|
||||||
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! While you only have to process shapes at the
|
And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! While you only have to process shapes at the beginning, you will later have to color them - by extracting and mixing colors!
|
||||||
beginning, you will later have to color them - by extracting and mixing colors!
|
|
||||||
|
|
||||||
Buying the game on Steam gives you access to the full version, but you can also play a demo at shapez.io first and decide later!
|
Buying the game on Steam gives you access to the full version, but you can also play a demo at shapez.io first and decide later!
|
||||||
|
|
||||||
title_advantages: Standalone Advantages
|
what_others_say: What people say about shapez.io
|
||||||
advantages:
|
|
||||||
- <b>12 New Levels</b> for a total of 26 levels
|
|
||||||
- <b>18 New Buildings</b> for a fully automated factory!
|
|
||||||
- <b>Unlimited Upgrade Tiers</b> for many hours of fun!
|
|
||||||
- <b>Wires Update</b> for an entirely new dimension!
|
|
||||||
- <b>Dark Mode</b>!
|
|
||||||
- Unlimited Savegames
|
|
||||||
- Unlimited Markers
|
|
||||||
- Support me! ❤️
|
|
||||||
|
|
||||||
title_future: Planned Content
|
nothernlion_comment: >-
|
||||||
planned:
|
This game is great - I'm having a wonderful time playing, and time has flown by.
|
||||||
- Blueprint Library
|
notch_comment: >-
|
||||||
- Steam Achievements
|
Oh crap. I really should sleep, but I think I just figured out how to make a computer in shapez.io
|
||||||
- Puzzle Mode
|
steam_review_comment: >-
|
||||||
- Minimap
|
This game has stolen my life and I don't want it back. Very chill factory game that won't let me stop making my lines more efficient.
|
||||||
- Mods
|
|
||||||
- Sandbox mode
|
|
||||||
- ... and a lot more!
|
|
||||||
|
|
||||||
title_open_source: This game is open source!
|
|
||||||
text_open_source: >-
|
|
||||||
Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible.
|
|
||||||
|
|
||||||
Be sure to check out my trello board for the full roadmap!
|
|
||||||
|
|
||||||
title_links: Links
|
|
||||||
|
|
||||||
links:
|
|
||||||
discord: Official Discord
|
|
||||||
roadmap: Roadmap
|
|
||||||
subreddit: Subreddit
|
|
||||||
source_code: Source code (GitHub)
|
|
||||||
translate: Help translate
|
|
||||||
|
|
||||||
global:
|
global:
|
||||||
loading: Loading
|
loading: Loading
|
||||||
@ -1207,11 +1178,6 @@ demo:
|
|||||||
|
|
||||||
settingNotAvailable: Not available in the demo.
|
settingNotAvailable: Not available in the demo.
|
||||||
|
|
||||||
achievements:
|
|
||||||
painting:
|
|
||||||
displayName: Painting
|
|
||||||
description: Paint a shape
|
|
||||||
|
|
||||||
tips:
|
tips:
|
||||||
- The hub will accept any input, not just the current shape!
|
- The hub will accept any input, not just the current shape!
|
||||||
- Make sure your factories are modular - it will pay out!
|
- Make sure your factories are modular - it will pay out!
|
||||||
|
@ -168,13 +168,14 @@ dialogs:
|
|||||||
desc: Suorita taso 12 avataksesi piirustukset!
|
desc: Suorita taso 12 avataksesi piirustukset!
|
||||||
keybindingsIntroduction:
|
keybindingsIntroduction:
|
||||||
title: Hyödyllisiä pikanäppäimiä
|
title: Hyödyllisiä pikanäppäimiä
|
||||||
desc: "Tässä pelissä on paljon pikanäppäimiä, jotka tekevät isojen tehtaiden
|
desc: >-
|
||||||
|
Tässä pelissä on paljon pikanäppäimiä, jotka tekevät isojen tehtaiden
|
||||||
rakentamisesta helpompaa. Tässä on muutama, mutta <strong>katso
|
rakentamisesta helpompaa. Tässä on muutama, mutta <strong>katso
|
||||||
kaikki pikanäppäimet</strong>!<br><br> <code
|
kaikki pikanäppäimet</strong>!<br><br> <code
|
||||||
class='keybinding'>CTRL</code> + Raahaus: Valitse alue.<br> <code
|
class='keybinding'>CTRL</code> + Raahaus: Valitse alue.<br> <code
|
||||||
class='keybinding'>SHIFT</code>: Pidä pohjassa sijoittaaksesi
|
class='keybinding'>SHIFT</code>: Pidä pohjassa sijoittaaksesi
|
||||||
useita samoja rakennuksia.<br> <code class='keybinding'>ALT</code>:
|
useita samoja rakennuksia.<br> <code class='keybinding'>ALT</code>:
|
||||||
Käännä sijoitettavien kuljettimien suunta.<br>"
|
Käännä sijoitettavien kuljettimien suunta.<br>
|
||||||
createMarker:
|
createMarker:
|
||||||
title: Uusi merkki
|
title: Uusi merkki
|
||||||
desc: Anna merkille kuvaava nimi. Voit myös liittää <strong>lyhyen koodin</strong>
|
desc: Anna merkille kuvaava nimi. Voit myös liittää <strong>lyhyen koodin</strong>
|
||||||
@ -306,26 +307,31 @@ ingame:
|
|||||||
hints:
|
hints:
|
||||||
1_1_extractor: Laita <strong>Poimija</strong> <strong>ympyrämuodon</strong>
|
1_1_extractor: Laita <strong>Poimija</strong> <strong>ympyrämuodon</strong>
|
||||||
päälle käyttääksesi sitä!
|
päälle käyttääksesi sitä!
|
||||||
1_2_conveyor: "Yhdistä poimija <strong>kuljettimella</strong>
|
1_2_conveyor: >-
|
||||||
|
Yhdistä poimija <strong>kuljettimella</strong>
|
||||||
keskusrakennukseen!<br><br>Vihje: <strong>Paina ja
|
keskusrakennukseen!<br><br>Vihje: <strong>Paina ja
|
||||||
raahaa</strong> kuljetinta hiirellä!"
|
raahaa</strong> kuljetinta hiirellä!
|
||||||
1_3_expand: "Tämä <strong>EI OLE</strong> tyhjäkäyntipeli! Rakenna lisää
|
1_3_expand: >-
|
||||||
|
Tämä <strong>EI OLE</strong> tyhjäkäyntipeli! Rakenna lisää
|
||||||
poimijoita ja kuljettimia saavuttaaksesi tavoitteen nopeammin
|
poimijoita ja kuljettimia saavuttaaksesi tavoitteen nopeammin
|
||||||
valmiiksi.<br><br>Vihje: Pidä <strong>SHIFT</strong> pohjassa
|
valmiiksi.<br><br>Vihje: Pidä <strong>SHIFT</strong> pohjassa
|
||||||
laittaaksesi useampia poimijoita ja käytä <strong>R</strong>
|
laittaaksesi useampia poimijoita ja käytä <strong>R</strong>
|
||||||
kääntääksesi niitä."
|
kääntääksesi niitä.
|
||||||
2_1_place_cutter: "Nyt aseta <strong>Leikkuri</strong> leikataksesi ympyrä
|
2_1_place_cutter: >-
|
||||||
|
Nyt aseta <strong>Leikkuri</strong> leikataksesi ympyrä
|
||||||
puoliksi!<br><br> PS: Leikkuri aina leikkaa <strong>ylhäältä alaspäin</strong>
|
puoliksi!<br><br> PS: Leikkuri aina leikkaa <strong>ylhäältä alaspäin</strong>
|
||||||
riippumatta sen asennosta."
|
riippumatta sen asennosta.
|
||||||
2_2_place_trash: Leikkuri voi <strong>tukkeutua</strong>!<br><br> Käytä
|
2_2_place_trash: Leikkuri voi <strong>tukkeutua</strong>!<br><br> Käytä
|
||||||
<strong>roskakoria</strong> hävittääksesi (vielä!) tarpeeton jäte.
|
<strong>roskakoria</strong> hävittääksesi (vielä!) tarpeeton jäte.
|
||||||
2_3_more_cutters: "Hienoa! Lisää <strong>kaksi leikkuria</strong> nopeuttaaksesi
|
2_3_more_cutters: >-
|
||||||
|
Hienoa! Lisää <strong>kaksi leikkuria</strong> nopeuttaaksesi
|
||||||
hidasta prosessia!<br><br> PS: Käytä <strong>pikanäppäimiä 0-9</strong>
|
hidasta prosessia!<br><br> PS: Käytä <strong>pikanäppäimiä 0-9</strong>
|
||||||
valitaksesi rakennuksen nopeammin!"
|
valitaksesi rakennuksen nopeammin!
|
||||||
3_1_rectangles: "Poimitaanpa nyt neliöitä! <strong>Rakenna 4
|
3_1_rectangles: >-
|
||||||
|
Poimitaanpa nyt neliöitä! <strong>Rakenna 4
|
||||||
poimijaa</strong> ja yhdistä ne keskusrakennukseen.<br><br> PS:
|
poimijaa</strong> ja yhdistä ne keskusrakennukseen.<br><br> PS:
|
||||||
Pidä <strong>SHIFT</strong> painettuna, kun raahaat kuljetinta
|
Pidä <strong>SHIFT</strong> painettuna, kun raahaat kuljetinta
|
||||||
aktivoidaksesi kuljetinsuunnittelijan!"
|
aktivoidaksesi kuljetinsuunnittelijan!
|
||||||
21_1_place_quad_painter: Aseta <strong>nelimaalain</strong> ja hanki
|
21_1_place_quad_painter: Aseta <strong>nelimaalain</strong> ja hanki
|
||||||
<strong>ympyröitä</strong>, <strong>valkoista</strong> ja
|
<strong>ympyröitä</strong>, <strong>valkoista</strong> ja
|
||||||
<strong>punaista</strong> väriä!
|
<strong>punaista</strong> väriä!
|
||||||
@ -333,9 +339,10 @@ ingame:
|
|||||||
<strong>E</strong>!<br><br> Sitten <strong>yhdistä kaikki neljä tuloa</strong> maalaimeen johdoilla!
|
<strong>E</strong>!<br><br> Sitten <strong>yhdistä kaikki neljä tuloa</strong> maalaimeen johdoilla!
|
||||||
21_3_place_button: MahtaVATA! Aseta nyt <strong>kytkin</strong> ja yhdistä
|
21_3_place_button: MahtaVATA! Aseta nyt <strong>kytkin</strong> ja yhdistä
|
||||||
se johdoilla!
|
se johdoilla!
|
||||||
21_4_press_button: "Paina kytkintä <strong>lähettääksesi tosi-
|
21_4_press_button: >-
|
||||||
|
Paina kytkintä <strong>lähettääksesi tosi-
|
||||||
signaalin</strong> ja aktivoidaksesi maalaimen.<br><br> PS: Kaikkia
|
signaalin</strong> ja aktivoidaksesi maalaimen.<br><br> PS: Kaikkia
|
||||||
tuloja ei tarvitse kytkeä! Kokeile vaikka vain kahta."
|
tuloja ei tarvitse kytkeä! Kokeile vaikka vain kahta.
|
||||||
connectedMiners:
|
connectedMiners:
|
||||||
one_miner: 1 poimija
|
one_miner: 1 poimija
|
||||||
n_miners: <amount> poimijaa
|
n_miners: <amount> poimijaa
|
||||||
@ -587,10 +594,11 @@ storyRewards:
|
|||||||
desc: Avasit <strong>Kääntäjän</strong>! Se kääntää muotoja myötäpäivään 90 astetta.
|
desc: Avasit <strong>Kääntäjän</strong>! Se kääntää muotoja myötäpäivään 90 astetta.
|
||||||
reward_painter:
|
reward_painter:
|
||||||
title: Värjäys
|
title: Värjäys
|
||||||
desc: "Avasit <strong>Maalaimen</strong> - Poimi joitain värialueita
|
desc: >-
|
||||||
|
Avasit <strong>Maalaimen</strong> - Poimi joitain värialueita
|
||||||
(Samoin kuin muotoja) ja yhdistä se muotoon maalaimen
|
(Samoin kuin muotoja) ja yhdistä se muotoon maalaimen
|
||||||
avulla!<br><br>PS: Jos olet värisokea, asetuksissa on <strong> tila
|
avulla!<br><br>PS: Jos olet värisokea, asetuksissa on <strong> tila
|
||||||
värisokeille</strong>!"
|
värisokeille</strong>!
|
||||||
reward_mixer:
|
reward_mixer:
|
||||||
title: Värin Sekoitus
|
title: Värin Sekoitus
|
||||||
desc: Avasit <strong>Värinsekoittajan</strong> - Yhdistä kaksi väriä
|
desc: Avasit <strong>Värinsekoittajan</strong> - Yhdistä kaksi väriä
|
||||||
@ -617,10 +625,11 @@ storyRewards:
|
|||||||
<strong>painamalla 'T' vaihtaaksesi sen versioita</strong>!
|
<strong>painamalla 'T' vaihtaaksesi sen versioita</strong>!
|
||||||
reward_miner_chainable:
|
reward_miner_chainable:
|
||||||
title: Sarjapoimija
|
title: Sarjapoimija
|
||||||
desc: "Avasit juuri <strong>Sarjapoimijan</strong>! Se voi
|
desc: >-
|
||||||
|
Avasit juuri <strong>Sarjapoimijan</strong>! Se voi
|
||||||
<strong>siirtää resurssejaan</strong> muihin poimijoihin, joten
|
<strong>siirtää resurssejaan</strong> muihin poimijoihin, joten
|
||||||
voit hankkia resursseja tehokkaammin!<br><br> PS: Vanha
|
voit hankkia resursseja tehokkaammin!<br><br> PS: Vanha
|
||||||
poimija on nyt korvattu työkalupalkissa!"
|
poimija on nyt korvattu työkalupalkissa!
|
||||||
reward_underground_belt_tier_2:
|
reward_underground_belt_tier_2:
|
||||||
title: Tunneli Taso II
|
title: Tunneli Taso II
|
||||||
desc: Avasit uuden version <strong>Tunnelista</strong> - Siinä on <strong>pidempi
|
desc: Avasit uuden version <strong>Tunnelista</strong> - Siinä on <strong>pidempi
|
||||||
@ -657,9 +666,10 @@ storyRewards:
|
|||||||
jotta sinulla on varaa siihen! (Ne mitkä juuri toimitit).
|
jotta sinulla on varaa siihen! (Ne mitkä juuri toimitit).
|
||||||
no_reward:
|
no_reward:
|
||||||
title: Seuraava taso
|
title: Seuraava taso
|
||||||
desc: "Et saanut palkintoa tältä tasolta, mutta seuraavalta tasolta saat! <br><br> PS: Parempi
|
desc: >-
|
||||||
|
Et saanut palkintoa tältä tasolta, mutta seuraavalta tasolta saat! <br><br> PS: Parempi
|
||||||
olla tuhoamatta vanhoja tehtaita - Tarvitset <strong>kaikkia</strong>
|
olla tuhoamatta vanhoja tehtaita - Tarvitset <strong>kaikkia</strong>
|
||||||
muotoja myöhemmin <strong>avataksesi päivityksiä</strong>!"
|
muotoja myöhemmin <strong>avataksesi päivityksiä</strong>!
|
||||||
no_reward_freeplay:
|
no_reward_freeplay:
|
||||||
title: Seuraava taso
|
title: Seuraava taso
|
||||||
desc: Onnittelut! Muuten, lisää sisältöä on suunniteltu täysversioon!
|
desc: Onnittelut! Muuten, lisää sisältöä on suunniteltu täysversioon!
|
||||||
@ -682,8 +692,9 @@ storyRewards:
|
|||||||
kääntää muotoa 180 astetta (Ylläripylläri! :D)
|
kääntää muotoa 180 astetta (Ylläripylläri! :D)
|
||||||
reward_display:
|
reward_display:
|
||||||
title: Näyttö
|
title: Näyttö
|
||||||
desc: "Avasit juuri <strong>Näytön</strong> - Yhdistä signaali näyttöön
|
desc: >-
|
||||||
Johto-tasolla visualisoidaksesi sen<br><br> PS: Huomasitko, että kuljetinanturi ja varasto näyttävät viimeisimmän esineen? Yritäpä saada se näkyviin näytölle!"
|
Avasit juuri <strong>Näytön</strong> - Yhdistä signaali näyttöön
|
||||||
|
Johto-tasolla visualisoidaksesi sen<br><br> PS: Huomasitko, että kuljetinanturi ja varasto näyttävät viimeisimmän esineen? Yritäpä saada se näkyviin näytölle!
|
||||||
reward_constant_signal:
|
reward_constant_signal:
|
||||||
title: Jatkuva Signaali
|
title: Jatkuva Signaali
|
||||||
desc: Avasit <strong>Jatkuvan Signaalin</strong> laitteen johtotasolla!
|
desc: Avasit <strong>Jatkuvan Signaalin</strong> laitteen johtotasolla!
|
||||||
@ -708,12 +719,13 @@ storyRewards:
|
|||||||
tavallisesti.<br><br> Mitä valitsetkin, muista pitää hauskaa!
|
tavallisesti.<br><br> Mitä valitsetkin, muista pitää hauskaa!
|
||||||
reward_wires_painter_and_levers:
|
reward_wires_painter_and_levers:
|
||||||
title: Johdot & Nelimaalain
|
title: Johdot & Nelimaalain
|
||||||
desc: "Avasit juuri <strong>Johtotason</strong>: Se on erillinen
|
desc: >-
|
||||||
|
Avasit juuri <strong>Johtotason</strong>: Se on erillinen
|
||||||
taso tavallisen tason päällä ja sieltä löytyy useita uusia
|
taso tavallisen tason päällä ja sieltä löytyy useita uusia
|
||||||
mekaniikkoja!<br><br> Aluksi avasin sinulle <strong>Nelimaalaimen</strong>
|
mekaniikkoja!<br><br> Aluksi avasin sinulle <strong>Nelimaalaimen</strong>
|
||||||
- Yhdistä johtotasolla lokerot, joihin haluat maalia<br><br>
|
- Yhdistä johtotasolla lokerot, joihin haluat maalia<br><br>
|
||||||
Vaihtaaksesi johtotasolle, paina <strong>E</strong>. <br><br>
|
Vaihtaaksesi johtotasolle, paina <strong>E</strong>. <br><br>
|
||||||
PS: <strong>Aktivoi vinkit</strong> asetuksissa nähdäksesi Johdot-tutoriaalin!"
|
PS: <strong>Aktivoi vinkit</strong> asetuksissa nähdäksesi Johdot-tutoriaalin!
|
||||||
reward_filter:
|
reward_filter:
|
||||||
title: Esinesuodatin
|
title: Esinesuodatin
|
||||||
desc: Olet avannut <strong>Esinesuodattimen</strong>! Se lähettää esineet
|
desc: Olet avannut <strong>Esinesuodattimen</strong>! Se lähettää esineet
|
||||||
@ -878,8 +890,9 @@ settings:
|
|||||||
rangeSliderPercentage: <amount> %
|
rangeSliderPercentage: <amount> %
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Pikanäppäimet
|
title: Pikanäppäimet
|
||||||
hint: "Vinkki: Muista käyttää CTRL, SHIFT ja ALT! Ne ottavat käyttöön erilaisia
|
hint: >-
|
||||||
sijoitteluvaihtoehtoja."
|
Vinkki: Muista käyttää CTRL, SHIFT ja ALT! Ne ottavat käyttöön erilaisia
|
||||||
|
sijoitteluvaihtoehtoja.
|
||||||
resetKeybindings: Nollaa pikanäppäimet
|
resetKeybindings: Nollaa pikanäppäimet
|
||||||
categoryLabels:
|
categoryLabels:
|
||||||
general: Sovellus
|
general: Sovellus
|
||||||
|
Loading…
Reference in New Issue
Block a user