dadish 2, fbwg3, and progress knight quest
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
(function (workerScript) {
|
||||
if (!/MSIE 10/i.test (navigator.userAgent)) {
|
||||
try {
|
||||
var blob = new Blob (["\
|
||||
var fakeIdToId = {};\
|
||||
onmessage = function (event) {\
|
||||
var data = event.data,\
|
||||
name = data.name,\
|
||||
fakeId = data.fakeId,\
|
||||
time;\
|
||||
if(data.hasOwnProperty('time')) {\
|
||||
time = data.time;\
|
||||
}\
|
||||
switch (name) {\
|
||||
case 'setInterval':\
|
||||
fakeIdToId[fakeId] = setInterval(function () {\
|
||||
postMessage({fakeId: fakeId});\
|
||||
}, time);\
|
||||
break;\
|
||||
case 'clearInterval':\
|
||||
if (fakeIdToId.hasOwnProperty (fakeId)) {\
|
||||
clearInterval(fakeIdToId[fakeId]);\
|
||||
delete fakeIdToId[fakeId];\
|
||||
}\
|
||||
break;\
|
||||
case 'setTimeout':\
|
||||
fakeIdToId[fakeId] = setTimeout(function () {\
|
||||
postMessage({fakeId: fakeId});\
|
||||
if (fakeIdToId.hasOwnProperty (fakeId)) {\
|
||||
delete fakeIdToId[fakeId];\
|
||||
}\
|
||||
}, time);\
|
||||
break;\
|
||||
case 'clearTimeout':\
|
||||
if (fakeIdToId.hasOwnProperty (fakeId)) {\
|
||||
clearTimeout(fakeIdToId[fakeId]);\
|
||||
delete fakeIdToId[fakeId];\
|
||||
}\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
"]);
|
||||
// Obtain a blob URL reference to our worker 'file'.
|
||||
workerScript = window.URL.createObjectURL(blob);
|
||||
} catch (error) {
|
||||
/* Blob is not supported, use external script instead */
|
||||
}
|
||||
}
|
||||
var worker,
|
||||
fakeIdToCallback = {},
|
||||
lastFakeId = 0,
|
||||
maxFakeId = 0x7FFFFFFF, // 2 ^ 31 - 1, 31 bit, positive values of signed 32 bit integer
|
||||
logPrefix = 'HackTimer.js by turuslan: ';
|
||||
if (typeof (Worker) !== 'undefined') {
|
||||
function getFakeId () {
|
||||
do {
|
||||
if (lastFakeId == maxFakeId) {
|
||||
lastFakeId = 0;
|
||||
} else {
|
||||
lastFakeId ++;
|
||||
}
|
||||
} while (fakeIdToCallback.hasOwnProperty (lastFakeId));
|
||||
return lastFakeId;
|
||||
}
|
||||
try {
|
||||
worker = new Worker (workerScript);
|
||||
window.setInterval = function (callback, time /* , parameters */) {
|
||||
var fakeId = getFakeId ();
|
||||
fakeIdToCallback[fakeId] = {
|
||||
callback: callback,
|
||||
parameters: Array.prototype.slice.call(arguments, 2)
|
||||
};
|
||||
worker.postMessage ({
|
||||
name: 'setInterval',
|
||||
fakeId: fakeId,
|
||||
time: time
|
||||
});
|
||||
return fakeId;
|
||||
};
|
||||
window.clearInterval = function (fakeId) {
|
||||
if (fakeIdToCallback.hasOwnProperty(fakeId)) {
|
||||
delete fakeIdToCallback[fakeId];
|
||||
worker.postMessage ({
|
||||
name: 'clearInterval',
|
||||
fakeId: fakeId
|
||||
});
|
||||
}
|
||||
};
|
||||
window.setTimeout = function (callback, time /* , parameters */) {
|
||||
var fakeId = getFakeId ();
|
||||
fakeIdToCallback[fakeId] = {
|
||||
callback: callback,
|
||||
parameters: Array.prototype.slice.call(arguments, 2),
|
||||
isTimeout: true
|
||||
};
|
||||
worker.postMessage ({
|
||||
name: 'setTimeout',
|
||||
fakeId: fakeId,
|
||||
time: time
|
||||
});
|
||||
return fakeId;
|
||||
};
|
||||
window.clearTimeout = function (fakeId) {
|
||||
if (fakeIdToCallback.hasOwnProperty(fakeId)) {
|
||||
delete fakeIdToCallback[fakeId];
|
||||
worker.postMessage ({
|
||||
name: 'clearTimeout',
|
||||
fakeId: fakeId
|
||||
});
|
||||
}
|
||||
};
|
||||
worker.onmessage = function (event) {
|
||||
var data = event.data,
|
||||
fakeId = data.fakeId,
|
||||
request,
|
||||
parameters,
|
||||
callback;
|
||||
if (fakeIdToCallback.hasOwnProperty(fakeId)) {
|
||||
request = fakeIdToCallback[fakeId];
|
||||
callback = request.callback;
|
||||
parameters = request.parameters;
|
||||
if (request.hasOwnProperty ('isTimeout') && request.isTimeout) {
|
||||
delete fakeIdToCallback[fakeId];
|
||||
}
|
||||
}
|
||||
if (typeof (callback) === 'string') {
|
||||
try {
|
||||
callback = new Function (callback);
|
||||
} catch (error) {
|
||||
console.log (logPrefix + 'Error parsing callback code string: ', error);
|
||||
}
|
||||
}
|
||||
if (typeof (callback) === 'function') {
|
||||
callback.apply (window, parameters);
|
||||
}
|
||||
};
|
||||
worker.onerror = function (event) {
|
||||
console.log (event);
|
||||
};
|
||||
} catch (error) {
|
||||
console.log (logPrefix + 'Initialisation failed');
|
||||
console.error (error);
|
||||
}
|
||||
} else {
|
||||
console.log (logPrefix + 'Initialisation failed - HTML5 Web Worker is not supported');
|
||||
}
|
||||
}) ('HackTimerWorker.js');
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
|
||||
Task is a base class combining core functionality used in jobs and skills.
|
||||
|
||||
A task object stores: name, level, max level ever achieved,
|
||||
current experience (e.g. experience accumulated inside the current task level),
|
||||
and an array of experience multipliplying effects from items and skills.
|
||||
|
||||
*/
|
||||
class Task {
|
||||
constructor(baseData) {
|
||||
this.baseData = baseData
|
||||
this.name = baseData.name
|
||||
this.level = 0
|
||||
this.maxLevel = 0
|
||||
this.xp = 0
|
||||
|
||||
this.xpMultipliers = [
|
||||
]
|
||||
}
|
||||
|
||||
getMaxXp() {
|
||||
var maxXp = Math.round(this.baseData.maxXp * (this.level + 1) * Math.pow(1.01, this.level))
|
||||
return maxXp
|
||||
}
|
||||
|
||||
getXpLeft() {
|
||||
return Math.round(this.getMaxXp() - this.xp)
|
||||
}
|
||||
|
||||
getMaxLevelMultiplier() {
|
||||
var maxLevelMultiplier = 1 + this.maxLevel / 10
|
||||
return maxLevelMultiplier
|
||||
}
|
||||
|
||||
getXpGain() {
|
||||
return applyMultipliers(10, this.xpMultipliers)
|
||||
}
|
||||
|
||||
increaseXp() {
|
||||
this.xp += applySpeed(this.getXpGain())
|
||||
if (this.xp >= this.getMaxXp()) {
|
||||
var excess = this.xp - this.getMaxXp()
|
||||
while (excess >= 0) {
|
||||
this.level += 1
|
||||
excess -= this.getMaxXp()
|
||||
}
|
||||
this.xp = this.getMaxXp() + excess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Job extends Task {
|
||||
constructor(baseData) {
|
||||
super(baseData)
|
||||
this.incomeMultipliers = [
|
||||
]
|
||||
}
|
||||
|
||||
getLevelMultiplier() {
|
||||
var levelMultiplier = 1 + Math.log10(this.level + 1)
|
||||
return levelMultiplier
|
||||
}
|
||||
|
||||
getIncome() {
|
||||
return applyMultipliers(this.baseData.income, this.incomeMultipliers)
|
||||
}
|
||||
}
|
||||
|
||||
class Skill extends Task {
|
||||
constructor(baseData) {
|
||||
super(baseData)
|
||||
}
|
||||
|
||||
getEffect() {
|
||||
var effect = 1 + this.baseData.effect * this.level
|
||||
return effect
|
||||
}
|
||||
|
||||
getEffectDescription() {
|
||||
var description = this.baseData.description
|
||||
var text = "x" + String(this.getEffect().toFixed(2)) + " " + description
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
class Item {
|
||||
constructor(baseData) {
|
||||
this.baseData = baseData
|
||||
this.name = baseData.name
|
||||
this.expenseMultipliers = [
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
getEffect() {
|
||||
if (gameData.currentProperty != this && !gameData.currentMisc.includes(this)) return 1
|
||||
var effect = this.baseData.effect
|
||||
return effect
|
||||
}
|
||||
|
||||
getEffectDescription() {
|
||||
var description = this.baseData.description
|
||||
if (itemCategories["Properties"].includes(this.name)) description = "Happiness"
|
||||
var text = "x" + this.baseData.effect.toFixed(1) + " " + description
|
||||
return text
|
||||
}
|
||||
|
||||
getExpense() {
|
||||
return applyMultipliers(this.baseData.expense, this.expenseMultipliers)
|
||||
}
|
||||
}
|
||||
|
||||
class Requirement {
|
||||
constructor(elements, requirements) {
|
||||
this.elements = elements
|
||||
this.requirements = requirements
|
||||
this.completed = false
|
||||
}
|
||||
|
||||
isCompleted() {
|
||||
if (this.completed) {return true}
|
||||
for (var requirement of this.requirements) {
|
||||
if (!this.getCondition(requirement)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
this.completed = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class TaskRequirement extends Requirement {
|
||||
constructor(elements, requirements) {
|
||||
super(elements, requirements)
|
||||
this.type = "task"
|
||||
}
|
||||
|
||||
getCondition(requirement) {
|
||||
return gameData.taskData[requirement.task].level >= requirement.requirement
|
||||
}
|
||||
}
|
||||
|
||||
class CoinRequirement extends Requirement {
|
||||
constructor(elements, requirements) {
|
||||
super(elements, requirements)
|
||||
this.type = "coins"
|
||||
}
|
||||
|
||||
getCondition(requirement) {
|
||||
return gameData.coins >= requirement.requirement
|
||||
}
|
||||
}
|
||||
|
||||
class AgeRequirement extends Requirement {
|
||||
constructor(elements, requirements) {
|
||||
super(elements, requirements)
|
||||
this.type = "age"
|
||||
}
|
||||
|
||||
getCondition(requirement) {
|
||||
return daysToYears(gameData.days) >= requirement.requirement
|
||||
}
|
||||
}
|
||||
|
||||
class EvilRequirement extends Requirement {
|
||||
constructor(elements, requirements) {
|
||||
super(elements, requirements)
|
||||
this.type = "evil"
|
||||
}
|
||||
|
||||
getCondition(requirement) {
|
||||
return gameData.evil >= requirement.requirement
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Contains object definitions for Town Buildings.
|
||||
* Provides container object to allow easy tracking of new buildings
|
||||
* and automates some linking of new buildings to game logic.
|
||||
*/
|
||||
|
||||
var o_townBuildingsContainer = {
|
||||
|
||||
o_woodenHut: {
|
||||
name: "Wooden Hut",
|
||||
id: "woodenHut",
|
||||
count: 0,
|
||||
baseCost: 100000000001, //treat as const
|
||||
costOfNextBuilding: 100000000001,
|
||||
costGrowthFactor: 1.01,
|
||||
role: ["Housing"],
|
||||
|
||||
handleClick: function(eventObject) {
|
||||
if(gameData.coins >= this.costOfNextBuilding) {
|
||||
gameData.coins -= this.costOfNextBuilding;
|
||||
console.log(`Inside handleClick(). This.count: ${this.count}`);
|
||||
this.count += 1;
|
||||
console.log(`Post-increment. This.count: ${this.count}`);
|
||||
this.costOfNextBuilding *= this.costGrowthFactor;
|
||||
}
|
||||
|
||||
updateTooltip(eventObject);
|
||||
},
|
||||
},
|
||||
|
||||
o_farm: {
|
||||
name: "Farm",
|
||||
id: "farm",
|
||||
count: 0,
|
||||
baseCost: 1000000000001, //treat as const
|
||||
costOfNextBuilding: 1000000000001,
|
||||
costGrowthFactor: 1.05,
|
||||
role: ["Food", "Income", "Prestige", "Nobility xp"],
|
||||
xpMultiplier: 1.10,
|
||||
income: 150, //1s 50c
|
||||
|
||||
handleClick: function(eventObject) {
|
||||
if(gameData.coins >= this.costOfNextBuilding) {
|
||||
gameData.coins -= this.costOfNextBuilding;
|
||||
this.count++;
|
||||
this.costOfNextBuilding *= this.costGrowthFactor;
|
||||
}
|
||||
|
||||
//global function, lives in townFunctions.js
|
||||
gameData.rawTownIncome = updateRawTownIncome();
|
||||
updateTooltip(eventObject);
|
||||
},
|
||||
|
||||
getExperienceMultiplier: function() {
|
||||
return this.count * this.xpMultiplier;
|
||||
},
|
||||
|
||||
getIncome: function() {
|
||||
return this.income * this.count;
|
||||
},
|
||||
},
|
||||
|
||||
o_grainShed: {
|
||||
name: "Grain Shed",
|
||||
id: "grainShed",
|
||||
count: 0,
|
||||
baseCost: 100000000001, //treat as const
|
||||
costOfNextBuilding: 100000000001,
|
||||
costGrowthFactor: 1.07,
|
||||
role: ["Food", "Income Boost"],
|
||||
targets: ["Farm"],
|
||||
incomeMultiplier: 1.06,
|
||||
|
||||
handleClick: function(eventObject) {
|
||||
if(gameData.coins >= this.costOfNextBuilding) {
|
||||
gameData.coins -= this.costOfNextBuilding;
|
||||
this.count++;
|
||||
this.costOfNextBuilding *= this.costGrowthFactor;
|
||||
}
|
||||
|
||||
//global function, lives in townFunctions.js
|
||||
gameData.rawTownIncome = updateRawTownIncome();
|
||||
updateTooltip(eventObject);
|
||||
},
|
||||
|
||||
calculateMultiplier: function() {
|
||||
return Math.pow(this.incomeMultiplier, this.count);
|
||||
}
|
||||
},
|
||||
|
||||
} // container
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
Contains global functions related to Town features
|
||||
*/
|
||||
|
||||
// Purpose: calculate the amount of money a player makes from their town buildings.
|
||||
//
|
||||
// How: iterate through town building container. If 'income' is a property, multiply
|
||||
// the income * count and add it to the total income variable. Return the total income
|
||||
// variable.
|
||||
function updateRawTownIncome() {
|
||||
//console.log("testing updateRawTownIncome function. We are inside the function now.");
|
||||
var totalIncome = 0;
|
||||
//console.log("totalIncome: " + totalIncome);
|
||||
//console.log("Starting for loop...");
|
||||
for(building in o_townBuildingsContainer) {
|
||||
//console.log("key: " + building);
|
||||
//building represents the key, so we use it to get a reference to the actual object
|
||||
var o_building = o_townBuildingsContainer[building];
|
||||
//console.log("value: " + o_building);
|
||||
if('income' in o_building) {
|
||||
//console.log("Income is detected in " + o_building.name + " building.");
|
||||
|
||||
/*
|
||||
* Description: if a building might have its income boosted by other buildings,
|
||||
* we iterate through all buildings to calculate the total income multiplier from all
|
||||
* buildings that boost it.
|
||||
*
|
||||
* We also do a few checks to make sure the properties we rely on are defined.
|
||||
*
|
||||
* This may become a performance bottleneck with large numbers of buildings
|
||||
* due to nested for loops and their O(n^2) behavior.
|
||||
*/
|
||||
if(o_building.name === "Farm") {
|
||||
var multiplier = 1.0;
|
||||
for(building2 in o_townBuildingsContainer) {
|
||||
var o_building2 = o_townBuildingsContainer[building2];
|
||||
if(('role' in o_building2) && (o_building2.role.includes("Income Boost"))){
|
||||
if (o_building2.targets !== undefined && o_building2.targets.includes("Farm")) {
|
||||
multiplier *= o_building2.calculateMultiplier();
|
||||
}
|
||||
}
|
||||
}
|
||||
totalIncome += (o_building.getIncome() * multiplier);
|
||||
} else {
|
||||
totalIncome += (o_building.getIncome());
|
||||
}
|
||||
//console.log("Income from " + o_building.name + " added to total. New total income: " + totalIncome);
|
||||
}
|
||||
}
|
||||
//console.log("For loop complete. totalIncome = " + totalIncome);
|
||||
return totalIncome;
|
||||
}
|
||||
|
||||
/*
|
||||
* Description: saves select building object properties into a saveObject
|
||||
* and writes that saveObject into gameData.townData. This function is
|
||||
* called right before gameData is saved to localStorage.
|
||||
*/
|
||||
function saveTownState() {
|
||||
if(enableVerboseLogging == 1) console.log("saving town state...");
|
||||
|
||||
for(building in o_townBuildingsContainer) {
|
||||
if(enableVerboseLogging == 1) console.log("key: " + building);
|
||||
var o_building = o_townBuildingsContainer[building];
|
||||
if(enableVerboseLogging == 1) console.log("value: " + o_building);
|
||||
var saveObject = {
|
||||
name: o_building.name,
|
||||
count: o_building.count,
|
||||
costOfNextBuilding: o_building.costOfNextBuilding,
|
||||
};
|
||||
if(saveObject !== undefined) {
|
||||
if(enableVerboseLogging == 1) console.log("This is the save object we created: " + saveObject);
|
||||
gameData.townData[saveObject.name] = saveObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadTownState() {
|
||||
for(building in o_townBuildingsContainer) {
|
||||
var o_building = o_townBuildingsContainer[building];
|
||||
if(o_building.name in gameData.townData) {
|
||||
var savedBuilding = gameData.townData[o_building.name];
|
||||
o_building.count = savedBuilding.count;
|
||||
o_building.costOfNextBuilding = savedBuilding.costOfNextBuilding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function destroyTownWhileEmbracingEvil() {
|
||||
//reset values in o_townBuildingContainer to their base values
|
||||
//reset values in gameData.townData, if it is not null, to their base values
|
||||
if(gameData.townData) {
|
||||
for(building in o_townBuildingsContainer) {
|
||||
var o_building = o_townBuildingsContainer[building];
|
||||
if(o_building.name in gameData.townData) {
|
||||
var savedBuilding = gameData.townData[o_building.name];
|
||||
savedBuilding.count = o_building.count = 0;
|
||||
o_building.costOfNextBuilding = savedBuilding.costOfNextBuilding = o_building.baseCost;
|
||||
}
|
||||
}
|
||||
gameData.rawTownIncome = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function testSuccessOfTownDestruction() {
|
||||
for(building in o_townBuildingsContainer) {
|
||||
var o_building = o_townBuildingsContainer[building];
|
||||
if(o_building.name in gameData.townData) {
|
||||
var savedBuilding = gameData.townData[o_building.name];
|
||||
if(enableVerboseLogging == 1) {
|
||||
console.log(`Type of Saved Count: ${typeof savedBuilding.count}`);
|
||||
console.log(`${o_building.name} Saved count: ${savedBuilding.count}`);
|
||||
console.log(`${o_building.name} Saved cost: ${savedBuilding.costOfNextBuilding}`);
|
||||
console.log(`${o_building.name} Working count: ${o_building.count}`);
|
||||
console.log(`${o_building.name} Working cost: ${o_building.costOfNextBuilding}`);
|
||||
}
|
||||
savedBuilding.count = o_building.count = 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// temporary brute-force function to limit Town income until it is modulated by future feature interaction.
|
||||
// the kingdom has spoken.
|
||||
function regulateGrainMarkets() {
|
||||
if(gameData.rawTownIncome > 1000000000) { //1000 platinum
|
||||
gameData.rawTownIncome = 1000000000;
|
||||
}
|
||||
}
|
||||
setInterval(regulateGrainMarkets, 15000);
|
||||
@@ -0,0 +1,40 @@
|
||||
function updateTooltip(eventObject) {
|
||||
//eventObject.currentTarget.id = the button's building id, like "woodenHut"
|
||||
// So tooltip ID is merely a template string `tooltip-${eventObject.currentTarget.id}
|
||||
let tooltipId = `tooltip-${eventObject.currentTarget.id}`;
|
||||
//console.log("Print all function args: " + arguments[0] + arguments[1]);
|
||||
//console.log("Tooltip ID: " + tooltipId);
|
||||
var tooltipElement = document.querySelector("#" + tooltipId);
|
||||
|
||||
//console.log("Grabbed the tooltip element whose text we're updating!");
|
||||
//console.log(tooltipElement);
|
||||
|
||||
//console.log("Here's the text content: ");
|
||||
//console.log(tooltipElement.textContent);
|
||||
//console.log("Typeof text content: " + typeof tooltipElement.textContent);
|
||||
let originalText = tooltipElement.textContent;
|
||||
|
||||
//hard code new cost for wooden hut, for now
|
||||
//in future, will grab building cost based off of tooltipId
|
||||
//let newBuildingCost = o_townBuildingsContainer.o_woodenHut.costOfNextBuilding;
|
||||
let newBuildingCost = o_townBuildingsContainer[`o_${eventObject.currentTarget.id}`].costOfNextBuilding;
|
||||
|
||||
|
||||
/* TEST getNested function from townFunctions.js */
|
||||
/* const test = o_townBuildingsContainer;
|
||||
console.log("***** testing getNested() *******");
|
||||
console.log(getNested(test, 'o_woodenHut', 'id'));
|
||||
console.log(test[`o_${eventObject.currentTarget.id}`]); */
|
||||
|
||||
//console.log(`New building cost: ${newBuildingCost}`);
|
||||
//console.log(`Searching ${tooltipId} for the span that wraps building cost...`);
|
||||
let buildingID = tooltipId.replace('tooltip-', '');
|
||||
let coinSpanId = `#coins-${buildingID}`;
|
||||
//console.log(`Coin span id: ${coinSpanId}`);
|
||||
let coinSpan = document.querySelector(coinSpanId);
|
||||
//console.log(`Coin span element: ${coinSpan}`);
|
||||
//console.log(`Coin span text content: ${coinSpan.textContent}`);
|
||||
//console.log("Replacing coin value with formatted building cost...");
|
||||
formatCoins(newBuildingCost, coinSpan);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user