You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

750 lines
27 KiB

let game = new Vue({
el: '#root',
data: {
version: 0.8,
debug: {
levelSandbox: false,
buildingsSandbox: false
},
resources: {
gold: {
amount: 500,
name: 'Gold',
worth: 1,
icon: 'img/gold.png',
unlocked: true
},
wood: {
amount: 0,
name: 'Wood',
worth: 5,
icon: 'img/wood.png',
unlocked: false
},
stone: {
amount: 0,
name: 'Stone',
worth: 10,
icon: 'img/stone.png',
unlocked: false
},
iron: {
amount: 0,
name: 'Iron',
worth: 25,
icon: 'img/iron.png',
unlocked: false
},
corn: {
amount: 0,
name: 'Corn',
worth: 35,
icon: 'img/corn.png',
unlocked: false
},
coal: {
amount: 0,
name: 'Coal',
worth: 30,
icon: 'img/coal.png',
unlocked: false
},
planks: {
amount: 0,
name: 'Planks',
worth: 75,
icon: 'img/planks.png',
unlocked: false
},
bricks: {
amount: 0,
name: 'Bricks',
worth: 50,
icon: 'img/bricks.png',
unlocked: false
},
},
storageNames: null,
buildings: {
bank: {
name: 'Bank',
resource: 'gold',
icon: 'medieval_largeCastle',
level: 1,
maxLevel: 10,
isOwned: true,
isUpgradeable: true,
amount: 100,
intervalInSeconds: 15,
price: 500,
amountPerLevel: [100, 150, 500, 750, 1000, 1500, 2000, 2500, 3000, 5000],
pricePerLevel: [500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000],
intervalPerLevel: [15, 25, 30, 45, 60, 90, 90, 120, 120, 120],
},
lumberjack: {
name: 'Lumberjack',
resource: 'wood',
icon: 'medieval_lumber',
level: 0,
maxLevel: 10,
isOwned: false,
isUpgradeable: true,
amount: 2,
intervalInSeconds: 10,
price: 250,
resourcesToBuild: {
gold: 250
},
amountPerLevel: [10, 15, 20, 25, 30, 30, 30, 30, 30, 30],
pricePerLevel: [250, 500, 1000, 1250, 1500, 2000, 3000, 4000, 5000, 6000],
intervalPerLevel: [15, 15, 15, 15, 15, 15, 10, 10, 5, 5],
},
quarry: {
name: 'Quarry',
resource: 'stone',
icon: 'medieval_mine',
level: 0,
maxLevel: 10,
isOwned: false,
isUpgradeable: true,
amount: 2,
intervalInSeconds: 20,
price: 500,
resourcesToBuild: {
wood: 500
},
amountPerLevel: [10, 15, 20, 25, 30, 30, 30, 30, 30, 30],
pricePerLevel: [500, 1000, 2000, 2500, 3000, 4000, 6000, 8000, 10000, 12000],
intervalPerLevel: [15, 15, 15, 15, 15, 15, 15, 15, 10, 5],
},
coalmine: {
name: 'Coal Mine',
resource: 'coal',
icon: 'medieval_mine',
level: 0,
maxLevel: 10,
isOwned: false,
isUpgradeable: true,
amount: 2,
intervalInSeconds: 20,
price: 500,
resourcesToBuild: {
stone: 600
},
amountPerLevel: [10, 15, 20, 25, 30, 30, 30, 30, 30, 30],
pricePerLevel: [1000, 2000, 4000, 6000, 8000, 10000, 12000, 15000, 20000],
intervalPerLevel: [15, 15, 15, 15, 15, 15, 15, 15, 10, 5],
},
farm: {
name: 'Farm',
resource: 'corn',
icon: 'medieval_farm',
level: 0,
maxLevel: 10,
isOwned: false,
isUpgradeable: true,
amount: 5,
price: 500,
resourcesToBuild: {
wood: 400,
stone: 350
},
intervalInSeconds: 15,
amountPerLevel: [100, 250, 500, 750, 1000, 1500, 2000, 2500, 3000, 5000],
pricePerLevel: [500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000],
intervalPerLevel: [15, 25, 30, 45, 60, 90, 90, 120, 120, 120],
},
carpenter: {
name: 'Carpenter',
resource: 'planks',
icon: 'medieval_lumber',
level: 0,
maxLevel: 10,
isOwned: false,
isUpgradeable: true,
amount: 5,
intervalInSeconds: 25,
price: 500,
hasRequirements: true,
requires: {
wood: 2
},
resourcesToBuild: {
wood: 600,
stone: 250
},
amountPerLevel: [100, 250, 500, 750, 1000, 1500, 2000, 2500, 3000, 5000],
pricePerLevel: [500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000],
intervalPerLevel: [15, 25, 30, 45, 60, 90, 90, 120, 120, 120],
},
blacksmith: {
name: 'Blacksmith',
resource: 'iron',
icon: 'medieval_blacksmith',
level: 0,
maxLevel: 10,
isOwned: false,
isUpgradeable: true,
amount: 2,
intervalInSeconds: 20,
price: 500,
hasRequirements: true,
requires: {
stone: 2,
coal: 1
},
resourcesToBuild: {
gold: 6000,
wood: 200,
stone: 750
},
amountPerLevel: [15, 25, 30, 45, 60, 90, 90, 120, 120, 120],
pricePerLevel: [500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000],
intervalPerLevel: [15, 25, 30, 45, 60, 90, 90, 120, 120, 120],
},
},
currentQuest: null,
questSkipCounter: 0,
loadedIntervals: []
},
created() {
this.storageNames = {
lastVersion: 'lastVersion',
resources: 'resources' + this.version,
buildings: 'buildings' + this.version,
}
this.checkVersion();
this.checkBuildings();
this.loadResourcesFromStorage();
this.loadBuildingsFromStorage();
this.reloadBuildings();
},
methods: {
// System & Saving
// Check if a new version is played and notify the user of the loss of his beloved score & progress
checkVersion() {
let lastVersion = localStorage.getItem(this.storageNames.lastVersion);
if (lastVersion && lastVersion < this.version) {
this.sendSystemNotification('Your beta-progress has been resetted due to a new version of the game, we\'re very sorry about that.')
}
localStorage.setItem(this.storageNames.lastVersion, this.version);
},
// Check if buildings-array is outdated
checkBuildings() {
let savedBuildings = JSON.parse(localStorage.getItem(this.storageNames.buildings));
if (!savedBuildings) {
localStorage.setItem(this.storageNames.buildings, JSON.stringify(this.buildings));
} else if (savedBuildings.length !== this.buildings.length) {
localStorage.setItem(this.storageNames.buildings, JSON.stringify(this.buildings));
this.sendInfo('Buildings have been resetted due to an important update.');
}
},
// Save buildings with progress -> has to resetted while in beta via version
saveBuildingsToStorage() {
localStorage.setItem(this.storageNames.buildings, JSON.stringify(this.buildings));
},
loadBuildingsFromStorage() {
let game = this;
let savedBuildings = JSON.parse(localStorage.getItem(this.storageNames.buildings));
if (savedBuildings) {
Object.keys(savedBuildings).forEach((building) => {
if (savedBuildings[building].isOwned) {
savedBuildings[building].loader = 0;
}
if (savedBuildings[building].hasMissingResources) {
savedBuildings[building].loader = 100;
}
if (savedBuildings[building].level > savedBuildings[building].maxLevel) {
savedBuildings[building].level = savedBuildings[building].maxLevel;
}
});
game.buildings = savedBuildings;
}
},
// Save resources a user has
saveResourcesToStorage() {
localStorage.setItem(this.storageNames.resources, JSON.stringify(this.resources));
},
loadResourcesFromStorage: function () {
let savedResources = JSON.parse(localStorage.getItem(this.storageNames.resources));
if (savedResources) {
this.resources = savedResources;
}
},
// Resource-Management
// add resources
add(amount = 0, resource = 'gold') {
let resourceName = this.resources[resource].name.toLowerCase();
this.resources[resourceName].amount += amount;
this.resources[resourceName].unlocked = true;
this.sendResourceMessage(amount, resourceName);
this.$forceUpdate();
this.saveResourcesToStorage();
},
// decrease resource
sub(amount = 0, resource = 'gold') {
this.resources[resource].amount -= amount;
return this.saveResourcesToStorage();
},
// Buying & upgrading buildings + checks + interval-generators
reloadBuildings() {
let game = this;
Object.keys(this.buildings).forEach((building) => {
if (game.buildings[building].isOwned && !game.buildings[building].hasMissingResources) {
game.buildings[building].price = game.buildings[building].pricePerLevel[game.buildings[building].level - 1];
game.buildings[building].amount = game.buildings[building].amountPerLevel[game.buildings[building].level - 1];
game.buildings[building].interval = game.buildings[building].intervalPerLevel[game.buildings[building].level - 1];
game.initiateIntervals(game.buildings[building]);
}
});
},
initiateIntervals(building) {
building.intervalEarnID = setInterval(() => {
if (building.hasRequirements) {
if (
game.buildingHasEnoughResourcesToStart(building)
) {
building.hasMissingResources = false;
building.loader = 0;
game.sendNotification(building.name + ' has resumed production of ' + building.resource + '.')
game.useRequiredResources(building);
game.add(building.amount, building.resource);
game.reloadSingleBuilding(building);
game.saveBuildingsToStorage();
} else {
if (building.hasMissingResources === false) {
building.hasMissingResources = true;
game.sendWarning(building.name + ' has stopped production of ' + building.resource + ' due to missing resources.')
clearInterval(building.intervalLoadingID);
game.saveBuildingsToStorage();
}
}
} else {
game.add(building.amount, building.resource);
}
}, building.intervalInSeconds * 1000);
if (this.buildingHasEnoughResourcesToStart(building)) {
building.intervalLoadingID = setInterval(() => {
if (building.loader < 100) {
building.loader += 10;
} else {
building.loader = 10;
}
game.$forceUpdate()
}, building.intervalInSeconds / 10 * 1000)
}
this.loadedIntervals.push(building.intervalEarnID, building.intervalLoadingID);
},
buyBuilding(building) {
if (building.resourcesToBuild) {
if (this.buildingIsBuildable(building)) {
Object.keys(building.resourcesToBuild).forEach((resourceToBuild) => {
game.resources[resourceToBuild].amount -= building.resourcesToBuild[resourceToBuild];
});
building.isOwned = true;
building.price = building.pricePerLevel[0];
building.amount = building.amountPerLevel[0];
building.interval = building.intervalPerLevel[0];
this.upgradeBuilding(building, true);
this.saveBuildingsToStorage();
}
} else {
if (this.resources.gold.amount >= building.price) {
this.sub(building.price);
building.isOwned = true;
building.price = building.pricePerLevel[0];
building.amount = building.amountPerLevel[0];
building.interval = building.intervalPerLevel[0];
this.upgradeBuilding(building, true);
this.saveBuildingsToStorage();
} else {
this.sendWarning('Not enough gold');
}
}
},
buildingIsBuildable(building) {
let game = this;
let resourcesMissing = [];
Object.keys(building.resourcesToBuild).forEach((resourceToBuild) => {
if (building.resourcesToBuild[resourceToBuild] > game.resources[resourceToBuild].amount) {
resourcesMissing.push(resourceToBuild);
}
});
if (resourcesMissing.length) {
resourcesMissing.forEach((resource) => {
game.sendNotEnoughResourceToBuildWarning(
'Not enough ' + resource + ' to build ' + building.name + '!',
building
);
});
return false;
} else {
return true;
}
},
buyUpgrade(building) {
if (building.level === building.maxLevel) {
this.sendWarning('Already at MAX-Level');
return false;
}
if (this.resources.gold.amount >= building.price) {
this.sub(building.price);
this.upgradeBuilding(building);
} else {
this.sendWarning('Not enough gold');
}
},
upgradeBuilding(building, first = false) {
if (building.level < (building.maxLevel)) {
building.level++;
this.sendBuildingUpgradedNotification(
building.name + ' has been upgraded to level ' + building.level + '!',
building
);
if (building.level === building.maxLevel) {
building.isUpgradeable = false;
}
} else {
building.isUpgradeable = false;
this.sendWarning('Building is already at max-level.')
return false;
}
building.price = building.pricePerLevel[building.level - 1];
building.amount = building.amountPerLevel[building.level - 1];
if (first === false) {
building.intervalInSeconds = building.intervalPerLevel[building.level - 1];
}
this.reloadSingleBuilding(building);
this.saveBuildingsToStorage();
},
reloadSingleBuilding(building) {
clearInterval(building.intervalEarnID);
clearInterval(building.intervalLoadingID);
building.loader = 0;
this.initiateIntervals(building);
},
buildingHasEnoughResourcesToStart(building) {
let resourcesMissing = [];
let game = this;
if (building.requires) {
Object.keys(building.requires).forEach((resource) => {
if (building.requires[resource] > game.resources[resource].amount) {
resourcesMissing.push(resource);
}
});
if (resourcesMissing.length) {
resourcesMissing.forEach((resource) => {
game.sendWarning(
'Not enough ' + resource + ' to produce ' + building.resource + '!'
);
});
return false;
} else {
return true;
}
} else {
return true;
}
},
// Quests
generateQuestWithRandomItems(skip = false) {
if (skip && this.questSkipCounter >= 3) {
this.sendWarning('You can only skip 3 quests in a row!');
return false;
}
let game = this;
let quest = [];
let rewardSum = 0;
const maxResourcesPerQuest = 3;
let unlockedResources = [];
Object.keys(game.resources).forEach((resource) => {
if (game.resources[resource].unlocked && resource !== 'gold') {
unlockedResources.push(resource);
}
});
if (unlockedResources.length > 1) {
unlockedResources = unlockedResources.sort(() => 0.5 - Math.random());
unlockedResources = unlockedResources.slice(
1,
(maxResourcesPerQuest > unlockedResources.length) ? unlockedResources.length : maxResourcesPerQuest
);
} else if (unlockedResources.length === 1) {
unlockedResources = [unlockedResources[0]];
}
unlockedResources.forEach((resource) => {
if (resource !== 'gold') {
let amount = game.getRandomAmountForQuestResource();
if (amount) {
quest[resource] = amount;
rewardSum += (quest[resource] * game.resources[resource].worth);
}
}
});
if (rewardSum > 0) {
if (skip) {
if (game.resources.gold.amount > 250) {
game.resources.gold.amount -= 250;
game.questSkipCounter++;
} else {
game.sendWarning('Not enough gold to skip this quest');
return false;
}
}
quest['reward'] = rewardSum;
game.currentQuest = quest;
game.$forceUpdate();
} else {
game.currentQuest = null;
game.sendInfo('You haven\'t unlocked any resources yet.');
}
},
getRandomAmountForQuestResource() {
// defines the rates of possible amounts of resources for quests
let possibleAmountsForQuest = [
5, 10, 15, 20, 25, 30, 35, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600
];
return possibleAmountsForQuest[Math.floor(Math.random() * possibleAmountsForQuest.length)];
},
isQuestRedeemable() {
let game = this;
let resourcesMissing = [];
let atLeastOneResourceIsMissing = false;
Object.keys(game.currentQuest).forEach((resource) => {
if (resource !== 'reward' && game.resources[resource].amount < game.currentQuest[resource]) {
resourcesMissing.push(resource);
atLeastOneResourceIsMissing = true;
}
});
if (atLeastOneResourceIsMissing) {
resourcesMissing.forEach((resource) => {
game.sendWarning(
'Not enough ' + resource + ' to end quest.'
);
});
return false;
} else {
return true;
}
},
redeemReward() {
let game = this;
if (game.isQuestRedeemable()) {
Object.keys(game.currentQuest).forEach((resource) => {
if (resource !== 'reward') {
game.resources[resource].amount -= game.currentQuest[resource];
}
});
game.add(game.currentQuest['reward']);
game.sendRewardMessage(game.currentQuest['reward']);
game.questSkipCounter = 0;
game.generateQuestWithRandomItems();
} else {
return false;
}
},
useRequiredResources(building) {
this.resources.wood.amount -= (building.requires.wood ? building.requires.wood : 0);
this.resources.stone.amount -= (building.requires.stone ? building.requires.stone : 0);
this.resources.iron.amount -= (building.requires.iron ? building.requires.iron : 0);
this.resources.bricks.amount -= (building.requires.bricks ? building.requires.bricks : 0);
this.resources.corn.amount -= (building.requires.corn ? building.requires.corn : 0);
this.resources.coal.amount -= (building.requires.coal ? building.requires.coal : 0);
},
// Templating
getFormattedNumber(value) {
return value.toLocaleString();
},
getResourceIconForBuilding(building) {
return this.getResourceIcon(building.resource);
},
getResourceIcon(resource) {
return '<img class="resource-icon" src="img/' + resource + '.png" title="' + resource + '" alt="' + resource + '">';
},
getRequirementsText(building) {
let requirementList = '<br/>Uses';
requirementList += building.requires.wood ? ' ' + building.requires.wood + ' ' + this.getResourceIcon('wood') : '';
requirementList += building.requires.stone ? ' ' + building.requires.stone + ' ' + this.getResourceIcon('stone') : '';
requirementList += building.requires.iron ? ' ' + building.requires.iron + ' ' + this.getResourceIcon('iron') : '';
requirementList += building.requires.bricks ? ' ' + building.requires.bricks + ' ' + this.getResourceIcon('bricks') : '';
requirementList += building.requires.coal ? ' ' + building.requires.coal + ' ' + this.getResourceIcon('coal') : '';
requirementList += building.requires.corn ? ' ' + building.requires.corn + ' ' + this.getResourceIcon('corn') : '';
return requirementList + ' for ' + building.amount + ' ' + this.getResourceIconForBuilding(building);
},
getColorForQuestResource(needed, has) {
return (has >= needed) ? 'lightgreen' : 'red';
},
// Alerts
sendRewardMessage(reward) {
iziToast.show({
image: 'img/gold.png',
color: 'green',
message: 'You got a reward of ' + reward + ' gold!',
position: 'bottomCenter',
timeout: 1500,
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendResourceMessage(amount, resource) {
iziToast.show({
image: 'img/' + resource + '.png',
theme: 'dark',
position: 'bottomCenter',
message: amount + ' ' + resource,
timeout: 1000,
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendNotification(message) {
iziToast.show({
color: 'green',
message: message,
position: 'bottomCenter',
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendSystemNotification(message) {
iziToast.show({
color: 'red',
message: message,
position: 'topCenter',
timeout: 7000,
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendNotEnoughResourceToBuildWarning(message, building) {
iziToast.show({
color: 'red',
message: message,
image: 'img/' + building.icon + '.png',
position: 'bottomCenter',
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendBuildingUpgradedNotification(message, building) {
iziToast.show({
color: 'green',
message: message,
image: 'img/' + building.icon + '.png',
position: 'bottomCenter',
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendWarning(message) {
iziToast.show({
color: 'red',
message: message,
position: 'bottomCenter',
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
sendInfo(message) {
iziToast.show({
color: 'blue',
message: message,
position: 'bottomCenter',
transitionIn: 'boundInRight',
transitionInMobile: 'boundInRight'
});
},
reset(hard = false) {
localStorage.removeItem('buildings' + this.version);
localStorage.removeItem('currentQuest' + this.version);
if (hard) {
localStorage.removeItem('resources' + this.version);
}
location.reload();
}
}
});