Merge branch 'develop' of https://github.com/HabitRPG/habitica into autocomplete-username
# Conflicts: # website/server/controllers/api-v3/chat.js # website/server/libs/pushNotifications.js # website/server/models/user/schema.js
10
README.md
@@ -5,8 +5,12 @@ Habitica [ is an open source habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor.
|
||||
|
||||
We need more programmers! Your assistance will be greatly appreciated.
|
||||
**We need more programmers!** Your assistance will be greatly appreciated. The wiki pages below and the additional pages they link to will tell you how to get started on contributing code and where you can go to seek further help or ask questions:
|
||||
* [Guidance for Blacksmiths](http://habitica.fandom.com/wiki/Guidance_for_Blacksmiths) - an introduction to the technologies used and how the software is organized.
|
||||
* [Setting up Habitica Locally](http://habitica.fandom.com/wiki/Setting_up_Habitica_Locally) - how to set up a local install of Habitica for development and testing on various platforms.
|
||||
|
||||
For an introduction to the technologies used and how the software is organized, refer to [Guidance for Blacksmiths](http://habitica.fandom.com/wiki/Guidance_for_Blacksmiths).
|
||||
Habitica's code is licensed as described at https://github.com/HabitRPG/habitica/blob/develop/LICENSE
|
||||
|
||||
To set up a local install of Habitica for development and testing on various platforms, see [Setting up Habitica Locally](http://habitica.fandom.com/wiki/Setting_up_Habitica_Locally).
|
||||
**Found a bug?** Please report it in the [Report a Bug guild](https://habitica.com/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac) rather than creating an issue (an admin will advise you if a new issue is necessary; usually it is not).
|
||||
|
||||
**Have any questions about Habitica or its community?** See the links in the [habitica.com](https://habitica.com) website's Help menu or drop in to [Guilds > Tavern Chat](https://habitica.com/groups/tavern) to ask questions or chat socially!
|
||||
|
||||
67
migrations/archive/2019/20190927_kickstarter.js
Normal file
@@ -0,0 +1,67 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190927_kickstarter';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
let push = {pinnedItems: {$each: []}};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
set['achievements.ks2019'] = true;
|
||||
|
||||
// set['items.gear.owned.armor_special_ks2019'] = false;
|
||||
// push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.armor_special_ks2019', _id: uuid()});
|
||||
set['items.gear.owned.head_special_ks2019'] = false;
|
||||
push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.head_special_ks2019', _id: uuid()});
|
||||
// set['items.gear.owned.shield_special_ks2019'] = false;
|
||||
// push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.shield_special_ks2019', _id: uuid()});
|
||||
// set['items.gear.owned.weapon_special_ks2019'] = false;
|
||||
// push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.weapon_special_ks2019', _id: uuid()});
|
||||
set['items.gear.owned.eyewear_special_ks2019'] = false;
|
||||
push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.eyewear_special_ks2019', _id: uuid()});
|
||||
// set['items.pets.Gryphon-Gryphatrice'] = 5;
|
||||
// set['items.mounts.Gryphon-Gryphatrice'] = true;
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set, $push: push}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.local.lowerCaseUsername': {$in: []},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = 'mystery_items_201908';
|
||||
const MYSTERY_ITEMS = ['armor_mystery_201908', 'headAccessory_mystery_201908'];
|
||||
const MIGRATION_NAME = 'mystery_items_201909';
|
||||
const MYSTERY_ITEMS = ['armor_mystery_201909', 'head_mystery_201909'];
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
import { model as UserNotification } from '../../website/server/models/userNotification';
|
||||
|
||||
|
||||
1549
package-lock.json
generated
22
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "4.112.0",
|
||||
"version": "4.115.2",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@google-cloud/trace-agent": "^4.0.0",
|
||||
@@ -31,11 +31,11 @@
|
||||
"bcrypt": "^3.0.6",
|
||||
"body-parser": "^1.18.3",
|
||||
"bootstrap": "^4.1.1",
|
||||
"bootstrap-vue": "^2.0.0-rc.18",
|
||||
"bootstrap-vue": "^2.0.2",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-session": "^1.3.3",
|
||||
"coupon-code": "^0.4.5",
|
||||
"cross-env": "^5.2.0",
|
||||
"cross-env": "^6.0.0",
|
||||
"css-loader": "^0.28.11",
|
||||
"csv-stringify": "^5.1.0",
|
||||
"cwait": "^1.1.1",
|
||||
@@ -53,8 +53,9 @@
|
||||
"gulp.spritesmith": "^6.9.0",
|
||||
"habitica-markdown": "^1.3.0",
|
||||
"hellojs": "^1.18.1",
|
||||
"helmet": "^3.21.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"image-size": "^0.7.0",
|
||||
"image-size": "^0.8.0",
|
||||
"in-app-purchase": "^1.11.3",
|
||||
"intro.js": "^2.9.3",
|
||||
"jquery": ">=3.0.0",
|
||||
@@ -72,7 +73,8 @@
|
||||
"ora": "^3.2.0",
|
||||
"pageres": "^5.1.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-facebook": "^2.0.0",
|
||||
"passport-facebook": "^3.0.0",
|
||||
"passport-google-oauth2": "^0.2.0",
|
||||
"passport-google-oauth20": "1.0.0",
|
||||
"paypal-ipn": "3.0.0",
|
||||
"paypal-rest-sdk": "^1.8.1",
|
||||
@@ -86,7 +88,7 @@
|
||||
"shelljs": "^0.8.2",
|
||||
"short-uuid": "^3.0.0",
|
||||
"smartbanner.js": "^1.11.0",
|
||||
"stripe": "^5.9.0",
|
||||
"stripe": "^7.9.0",
|
||||
"superagent": "^5.0.2",
|
||||
"svg-inline-loader": "^0.8.0",
|
||||
"svg-url-loader": "^3.0.0",
|
||||
@@ -154,9 +156,9 @@
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chalk": "^2.4.1",
|
||||
"chromedriver": "^76.0.0",
|
||||
"chromedriver": "^77.0.0",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"cross-spawn": "^6.0.5",
|
||||
"cross-spawn": "^7.0.0",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-habitrpg": "^4.0.0",
|
||||
"eslint-friendly-formatter": "^4.0.1",
|
||||
@@ -165,12 +167,12 @@
|
||||
"eslint-plugin-mocha": "^5.0.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"expect.js": "^0.3.1",
|
||||
"http-proxy-middleware": "^0.19.0",
|
||||
"http-proxy-middleware": "^0.20.0",
|
||||
"istanbul": "^1.1.0-alpha.1",
|
||||
"karma": "^4.0.1",
|
||||
"karma-babel-preprocessor": "^7.0.0",
|
||||
"karma-chai-plugins": "^0.9.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-chrome-launcher": "^3.0.0",
|
||||
"karma-coverage": "^1.1.2",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
|
||||
@@ -1,27 +1,11 @@
|
||||
import {
|
||||
translations,
|
||||
localePath,
|
||||
langCodes,
|
||||
approvedLanguages,
|
||||
} from '../../../../website/server/libs/i18n';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
describe('i18n', () => {
|
||||
let listOfLocales = [];
|
||||
|
||||
before((done) => {
|
||||
fs.readdir(localePath, (err, files) => {
|
||||
if (err) return done(err);
|
||||
|
||||
files.forEach((file) => {
|
||||
if (fs.statSync(path.join(localePath, file)).isDirectory() === false) return;
|
||||
listOfLocales.push(file);
|
||||
});
|
||||
|
||||
listOfLocales = listOfLocales.sort();
|
||||
done();
|
||||
});
|
||||
});
|
||||
let listOfLocales = approvedLanguages.sort();
|
||||
|
||||
describe('translations', () => {
|
||||
it('includes a translation object for each locale', () => {
|
||||
|
||||
@@ -97,17 +97,17 @@ describe('edit subscription', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
subscriptionId = 'subId';
|
||||
stripeListSubscriptionStub = sinon.stub(stripe.customers, 'listSubscriptions')
|
||||
stripeListSubscriptionStub = sinon.stub(stripe.subscriptions, 'list')
|
||||
.resolves({
|
||||
data: [{id: subscriptionId}],
|
||||
});
|
||||
|
||||
stripeUpdateSubscriptionStub = sinon.stub(stripe.customers, 'updateSubscription').resolves({});
|
||||
stripeUpdateSubscriptionStub = sinon.stub(stripe.subscriptions, 'update').resolves({});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
stripe.customers.listSubscriptions.restore();
|
||||
stripe.customers.updateSubscription.restore();
|
||||
stripe.subscriptions.list.restore();
|
||||
stripe.subscriptions.update.restore();
|
||||
});
|
||||
|
||||
it('edits a user subscription', async () => {
|
||||
@@ -118,10 +118,9 @@ describe('edit subscription', () => {
|
||||
}, stripe);
|
||||
|
||||
expect(stripeListSubscriptionStub).to.be.calledOnce;
|
||||
expect(stripeListSubscriptionStub).to.be.calledWith(user.purchased.plan.customerId);
|
||||
expect(stripeListSubscriptionStub).to.be.calledWith({customer: user.purchased.plan.customerId});
|
||||
expect(stripeUpdateSubscriptionStub).to.be.calledOnce;
|
||||
expect(stripeUpdateSubscriptionStub).to.be.calledWith(
|
||||
user.purchased.plan.customerId,
|
||||
subscriptionId,
|
||||
{ card: token }
|
||||
);
|
||||
@@ -135,10 +134,9 @@ describe('edit subscription', () => {
|
||||
}, stripe);
|
||||
|
||||
expect(stripeListSubscriptionStub).to.be.calledOnce;
|
||||
expect(stripeListSubscriptionStub).to.be.calledWith(group.purchased.plan.customerId);
|
||||
expect(stripeListSubscriptionStub).to.be.calledWith({customer: group.purchased.plan.customerId});
|
||||
expect(stripeUpdateSubscriptionStub).to.be.calledOnce;
|
||||
expect(stripeUpdateSubscriptionStub).to.be.calledWith(
|
||||
group.purchased.plan.customerId,
|
||||
subscriptionId,
|
||||
{ card: token }
|
||||
);
|
||||
|
||||
@@ -21,13 +21,13 @@ describe('POST /group/:groupId/remove-manager', () => {
|
||||
type: groupType,
|
||||
privacy: 'public',
|
||||
},
|
||||
members: 1,
|
||||
members: 2,
|
||||
});
|
||||
|
||||
groupToUpdate = group;
|
||||
leader = groupLeader;
|
||||
nonLeader = members[0];
|
||||
nonManager = members[0];
|
||||
nonManager = members[1];
|
||||
});
|
||||
|
||||
it('returns an error when a non group leader tries to add member', async () => {
|
||||
@@ -71,10 +71,10 @@ describe('POST /group/:groupId/remove-manager', () => {
|
||||
type: 'todo',
|
||||
requiresApproval: true,
|
||||
});
|
||||
await nonLeader.post(`/tasks/${task._id}/assign/${leader._id}`);
|
||||
let memberTasks = await leader.get('/tasks/user');
|
||||
await nonLeader.post(`/tasks/${task._id}/assign/${nonManager._id}`);
|
||||
let memberTasks = await nonManager.get('/tasks/user');
|
||||
let syncedTask = find(memberTasks, findAssignedTask);
|
||||
await expect(leader.post(`/tasks/${syncedTask._id}/score/up`))
|
||||
await expect(nonManager.post(`/tasks/${syncedTask._id}/score/up`))
|
||||
.to.eventually.be.rejected.and.to.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../../helpers/api-integration/v3';
|
||||
import { find } from 'lodash';
|
||||
|
||||
describe('GET /approvals/group/:groupId', () => {
|
||||
let user, guild, member, task, syncedTask;
|
||||
let user, guild, member, addlMember, task, syncedTask, addlSyncedTask;
|
||||
|
||||
function findAssignedTask (memberTask) {
|
||||
return memberTask.group.id === guild._id;
|
||||
@@ -17,12 +16,13 @@ describe('GET /approvals/group/:groupId', () => {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
},
|
||||
members: 1,
|
||||
members: 2,
|
||||
});
|
||||
|
||||
guild = group;
|
||||
user = groupLeader;
|
||||
member = members[0];
|
||||
addlMember = members[1];
|
||||
|
||||
task = await user.post(`/tasks/group/${guild._id}`, {
|
||||
text: 'test todo',
|
||||
@@ -31,37 +31,46 @@ describe('GET /approvals/group/:groupId', () => {
|
||||
});
|
||||
|
||||
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||
await user.post(`/tasks/${task._id}/assign/${addlMember._id}`);
|
||||
|
||||
let memberTasks = await member.get('/tasks/user');
|
||||
syncedTask = find(memberTasks, findAssignedTask);
|
||||
|
||||
let addlMemberTasks = await addlMember.get('/tasks/user');
|
||||
addlSyncedTask = find(addlMemberTasks, findAssignedTask);
|
||||
|
||||
try {
|
||||
await member.post(`/tasks/${syncedTask._id}/score/up`);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-empty
|
||||
}
|
||||
|
||||
try {
|
||||
await addlMember.post(`/tasks/${addlSyncedTask._id}/score/up`);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-empty
|
||||
}
|
||||
});
|
||||
|
||||
it('errors when user is not the group leader', async () => {
|
||||
await expect(member.get(`/approvals/group/${guild._id}`))
|
||||
.to.eventually.be.rejected.and.to.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('onlyGroupLeaderCanEditTasks'),
|
||||
});
|
||||
it('provides only user\'s own tasks when user is not the group leader', async () => {
|
||||
let approvals = await member.get(`/approvals/group/${guild._id}`);
|
||||
expect(approvals[0]._id).to.equal(syncedTask._id);
|
||||
expect(approvals[1]).to.not.exist;
|
||||
});
|
||||
|
||||
it('gets a list of task that need approval', async () => {
|
||||
it('allows group leaders to get a list of tasks that need approval', async () => {
|
||||
let approvals = await user.get(`/approvals/group/${guild._id}`);
|
||||
expect(approvals[0]._id).to.equal(syncedTask._id);
|
||||
expect(approvals[1]._id).to.equal(addlSyncedTask._id);
|
||||
});
|
||||
|
||||
it('allows managers to get a list of task that need approval', async () => {
|
||||
it('allows managers to get a list of tasks that need approval', async () => {
|
||||
await user.post(`/groups/${guild._id}/add-manager`, {
|
||||
managerId: member._id,
|
||||
});
|
||||
|
||||
let approvals = await member.get(`/approvals/group/${guild._id}`);
|
||||
expect(approvals[0]._id).to.equal(syncedTask._id);
|
||||
expect(approvals[1]._id).to.equal(addlSyncedTask._id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,6 +93,25 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
|
||||
expect(syncedTask).to.exist;
|
||||
});
|
||||
|
||||
it('sends notifications to group leader and managers when a task is claimed', async () => {
|
||||
await user.post(`/groups/${guild._id}/add-manager`, {
|
||||
managerId: member2._id,
|
||||
});
|
||||
await member.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||
await user.sync();
|
||||
await member2.sync();
|
||||
let groupTask = await user.get(`/tasks/group/${guild._id}`);
|
||||
|
||||
expect(user.notifications.length).to.equal(2); // includes Guild Joined achievement
|
||||
expect(user.notifications[1].type).to.equal('GROUP_TASK_CLAIMED');
|
||||
expect(user.notifications[1].data.taskId).to.equal(groupTask[0]._id);
|
||||
expect(user.notifications[1].data.groupId).to.equal(guild._id);
|
||||
expect(member2.notifications.length).to.equal(1);
|
||||
expect(member2.notifications[0].type).to.equal('GROUP_TASK_CLAIMED');
|
||||
expect(member2.notifications[0].data.taskId).to.equal(groupTask[0]._id);
|
||||
expect(member2.notifications[0].data.groupId).to.equal(guild._id);
|
||||
});
|
||||
|
||||
it('assigns a task to a user', async () => {
|
||||
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||
|
||||
|
||||
@@ -56,11 +56,11 @@ describe('PUT /tasks/:id', () => {
|
||||
requiresApproval: true,
|
||||
});
|
||||
|
||||
let memberTasks = await member.get('/tasks/user');
|
||||
let memberTasks = await member2.get('/tasks/user');
|
||||
let syncedTask = find(memberTasks, (memberTask) => memberTask.group.taskId === task._id);
|
||||
|
||||
// score up to trigger approval
|
||||
await expect(member.post(`/tasks/${syncedTask._id}/score/up`))
|
||||
await expect(member2.post(`/tasks/${syncedTask._id}/score/up`))
|
||||
.to.eventually.be.rejected.and.to.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
|
||||
33
test/api/v3/integration/webhook/GET-user-webhook.test.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { generateUser } from '../../../../helpers/api-integration/v3';
|
||||
|
||||
describe('GET /user/webhook', () => {
|
||||
let user;
|
||||
|
||||
beforeEach(async () => {
|
||||
user = await generateUser();
|
||||
|
||||
await user.post('/user/webhook', {
|
||||
url: 'http://some-url.com',
|
||||
label: 'Label',
|
||||
enabled: true,
|
||||
type: 'taskActivity',
|
||||
options: { created: true, scored: true },
|
||||
});
|
||||
await user.post('/user/webhook', {
|
||||
url: 'http://some-other-url.com',
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
await user.sync();
|
||||
});
|
||||
|
||||
it('returns users webhooks', async () => {
|
||||
let response = await user.get('/user/webhook');
|
||||
|
||||
expect(response).to.eql(user.webhooks.map(w => {
|
||||
w.createdAt = w.createdAt.toISOString();
|
||||
w.updatedAt = w.updatedAt.toISOString();
|
||||
return w;
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -109,12 +109,13 @@ describe('getTaskClasses getter', () => {
|
||||
});
|
||||
});
|
||||
|
||||
xit('returns good todo classes', () => {
|
||||
it('returns good todo classes', () => {
|
||||
const task = {type: 'todo', value: 2};
|
||||
expect(getTaskClasses(task, 'control')).to.deep.equal({
|
||||
bg: 'task-good-control-bg',
|
||||
checkbox: 'task-good-control-checkbox',
|
||||
inner: 'task-good-control-inner-daily-todo`',
|
||||
inner: 'task-good-control-inner-daily-todo',
|
||||
icon: 'task-good-control-icon',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -140,4 +141,14 @@ describe('getTaskClasses getter', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns noninteractive classes and padlock icons for group board tasks', () => {
|
||||
const task = {type: 'todo', value: 2, group: {id: 'group-id'}};
|
||||
expect(getTaskClasses(task, 'control')).to.deep.equal({
|
||||
bg: 'task-good-control-bg-noninteractive',
|
||||
checkbox: 'task-good-control-checkbox',
|
||||
inner: 'task-good-control-inner-daily-todo',
|
||||
icon: 'task-good-control-icon',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,11 +9,18 @@ import {
|
||||
generateUser,
|
||||
} from '../../../helpers/common.helper';
|
||||
import errorMessage from '../../../../website/common/script/libs/errorMessage';
|
||||
import {BuyHourglassMountOperation} from '../../../../website/common/script/ops/buy/buyMount';
|
||||
|
||||
describe('common.ops.hourglassPurchase', () => {
|
||||
let user;
|
||||
let analytics = {track () {}};
|
||||
|
||||
function buyMount (_user, _req, _analytics) {
|
||||
const buyOp = new BuyHourglassMountOperation(_user, _req, _analytics);
|
||||
|
||||
return buyOp.purchase();
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
user = generateUser();
|
||||
sinon.stub(analytics, 'track');
|
||||
@@ -66,7 +73,7 @@ describe('common.ops.hourglassPurchase', () => {
|
||||
|
||||
it('does not grant to mounts without Mystic Hourglasses', (done) => {
|
||||
try {
|
||||
hourglassPurchase(user, {params: {type: 'mounts', key: 'MantisShrimp-Base'}});
|
||||
buyMount(user, {params: {key: 'MantisShrimp-Base'}});
|
||||
} catch (err) {
|
||||
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||
expect(err.message).to.eql(i18n.t('notEnoughHourglasses'));
|
||||
@@ -90,7 +97,7 @@ describe('common.ops.hourglassPurchase', () => {
|
||||
user.purchased.plan.consecutive.trinkets = 1;
|
||||
|
||||
try {
|
||||
hourglassPurchase(user, {params: {type: 'mounts', key: 'Orca-Base'}});
|
||||
buyMount(user, {params: {key: 'Orca-Base'}});
|
||||
} catch (err) {
|
||||
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||
expect(err.message).to.eql(i18n.t('notAllowedHourglass'));
|
||||
@@ -120,7 +127,7 @@ describe('common.ops.hourglassPurchase', () => {
|
||||
};
|
||||
|
||||
try {
|
||||
hourglassPurchase(user, {params: {type: 'mounts', key: 'MantisShrimp-Base'}});
|
||||
buyMount(user, {params: {key: 'MantisShrimp-Base'}});
|
||||
} catch (err) {
|
||||
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||
expect(err.message).to.eql(i18n.t('mountsAlreadyOwned'));
|
||||
@@ -144,7 +151,7 @@ describe('common.ops.hourglassPurchase', () => {
|
||||
it('buys a mount', () => {
|
||||
user.purchased.plan.consecutive.trinkets = 2;
|
||||
|
||||
let [, message] = hourglassPurchase(user, {params: {type: 'mounts', key: 'MantisShrimp-Base'}});
|
||||
let [, message] = buyMount(user, {params: {key: 'MantisShrimp-Base'}});
|
||||
expect(message).to.eql(i18n.t('hourglassPurchase'));
|
||||
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
|
||||
expect(user.items.mounts).to.eql({'MantisShrimp-Base': true});
|
||||
|
||||
@@ -657,5 +657,6 @@ export default {
|
||||
<style src="assets/css/sprites/spritesmith-main-23.css"></style>
|
||||
<style src="assets/css/sprites/spritesmith-main-24.css"></style>
|
||||
<style src="assets/css/sprites/spritesmith-main-25.css"></style>
|
||||
<style src="assets/css/sprites/spritesmith-main-26.css"></style>
|
||||
<style src="assets/css/sprites.css"></style>
|
||||
<style src="smartbanner.js/dist/smartbanner.min.css"></style>
|
||||
|
||||
|
Before Width: | Height: | Size: 194 B |
|
Before Width: | Height: | Size: 330 B |
|
Before Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 191 B |
|
Before Width: | Height: | Size: 334 B |
|
Before Width: | Height: | Size: 614 B |
@@ -96,6 +96,52 @@
|
||||
background: url("~assets/images/BackerOnly-Pet-CerberusPup.gif") no-repeat;
|
||||
}
|
||||
|
||||
.broad_armor_special_ks2019, .slim_armor_special_ks2019, .eyewear_special_ks2019, .head_special_ks2019, .shield_special_ks2019 {
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.broad_armor_special_ks2019, .slim_armor_special_ks2019 {
|
||||
background: url("~assets/images/BackerOnly-Equip-MythicGryphonArmor.gif") no-repeat;
|
||||
}
|
||||
|
||||
.eyewear_special_ks2019 {
|
||||
background: url("~assets/images/BackerOnly-Equip-MythicGryphonVisor.gif") no-repeat;
|
||||
}
|
||||
|
||||
.head_special_ks2019 {
|
||||
background: url("~assets/images/BackerOnly-Equip-MythicGryphonHelm.gif") no-repeat;
|
||||
}
|
||||
|
||||
.shield_special_ks2019 {
|
||||
background: url("~assets/images/BackerOnly-Equip-MythicGryphonShield.gif") no-repeat;
|
||||
}
|
||||
|
||||
.weapon_special_ks2019 {
|
||||
background: url("~assets/images/BackerOnly-Equip-MythicGryphonGlaive.gif") no-repeat;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.Pet-Gryphon-Gryphatrice {
|
||||
background: url("~assets/images/BackerOnly-Pet-Gryphatrice.gif") no-repeat;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
|
||||
.Mount_Head_Gryphon-Gryphatrice, .Mount_Body_Gryphon-Gryphatrice {
|
||||
width: 135px;
|
||||
height: 135px;
|
||||
}
|
||||
|
||||
.Mount_Head_Gryphon-Gryphatrice {
|
||||
background: url("~assets/images/BackerOnly-Mount-Head-Gryphatrice.gif") no-repeat;
|
||||
}
|
||||
|
||||
.Mount_Body_Gryphon-Gryphatrice {
|
||||
background: url("~assets/images/BackerOnly-Mount-Body-Gryphatrice.gif") no-repeat;
|
||||
}
|
||||
|
||||
/* FIXME figure out how to handle customize menu!!
|
||||
.customize-menu .f_head_0 {
|
||||
width: 60px;
|
||||
|
||||
@@ -1,30 +1,72 @@
|
||||
.promo_armoire_backgrounds_201909 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px 0px;
|
||||
background-position: 0px -533px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_desert_pet_achievements {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -296px;
|
||||
background-position: -816px -392px;
|
||||
width: 204px;
|
||||
height: 102px;
|
||||
}
|
||||
.promo_fall_festival_2018 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -653px 0px;
|
||||
width: 372px;
|
||||
height: 180px;
|
||||
}
|
||||
.promo_fall_festival_2019 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -343px;
|
||||
width: 360px;
|
||||
height: 189px;
|
||||
}
|
||||
.promo_mystery_201909 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -361px -343px;
|
||||
width: 282px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_rocking_reptiles_bundle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -148px;
|
||||
background-position: 0px -681px;
|
||||
width: 420px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_seasonal_shop_fall {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -653px -392px;
|
||||
width: 162px;
|
||||
height: 138px;
|
||||
}
|
||||
.promo_shadow_spooky_potions {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -424px -533px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_take_this {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -424px -211px;
|
||||
background-position: -864px -181px;
|
||||
width: 96px;
|
||||
height: 69px;
|
||||
}
|
||||
.scene_casting_spells {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -340px 0px;
|
||||
width: 312px;
|
||||
height: 222px;
|
||||
}
|
||||
.scene_medal {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -424px 0px;
|
||||
background-position: -653px -181px;
|
||||
width: 210px;
|
||||
height: 210px;
|
||||
}
|
||||
.scene_video_games {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px 0px;
|
||||
width: 339px;
|
||||
height: 342px;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
.achievement-alien {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1372px -1628px;
|
||||
background-position: -1421px -1628px;
|
||||
width: 24px;
|
||||
height: 26px;
|
||||
}
|
||||
.achievement-alien2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1489px -1549px;
|
||||
background-position: -1440px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-allYourBase2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1112px -1480px;
|
||||
background-position: -1181px -1480px;
|
||||
width: 64px;
|
||||
height: 56px;
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
.achievement-aridAuthority2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -921px -1480px;
|
||||
background-position: -990px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
}
|
||||
.achievement-backToBasics2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1177px -1480px;
|
||||
background-position: -1246px -1480px;
|
||||
width: 48px;
|
||||
height: 56px;
|
||||
}
|
||||
@@ -120,7 +120,7 @@
|
||||
}
|
||||
.achievement-dustDevil2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -1480px;
|
||||
background-position: -921px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
@@ -180,181 +180,187 @@
|
||||
}
|
||||
.achievement-justAddWater2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1051px -1480px;
|
||||
background-position: -1120px -1480px;
|
||||
width: 60px;
|
||||
height: 64px;
|
||||
}
|
||||
.achievement-karaoke-2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1226px -1480px;
|
||||
background-position: -1636px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-karaoke {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1667px -1480px;
|
||||
background-position: -1446px -1628px;
|
||||
width: 24px;
|
||||
height: 26px;
|
||||
}
|
||||
.achievement-kickstarter20192x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.achievement-lostMasterclasser2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1538px -1549px;
|
||||
background-position: -1489px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-mindOverMatter2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -990px -1480px;
|
||||
background-position: -1059px -1480px;
|
||||
width: 60px;
|
||||
height: 64px;
|
||||
}
|
||||
.achievement-ninja2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1440px -1549px;
|
||||
background-position: -1391px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-npc2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1391px -1549px;
|
||||
background-position: -1342px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-nye2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1342px -1549px;
|
||||
background-position: -1293px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-partyOn2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1293px -1549px;
|
||||
background-position: -1244px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-partyUp2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1244px -1549px;
|
||||
background-position: -1195px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-perfect2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1195px -1549px;
|
||||
background-position: -1146px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-rat2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1146px -1549px;
|
||||
background-position: -1097px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-royally-loyal2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1097px -1549px;
|
||||
background-position: -1048px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-seafoam2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1048px -1549px;
|
||||
background-position: -999px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-shield2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -999px -1549px;
|
||||
background-position: -950px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-shinySeed2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -950px -1549px;
|
||||
background-position: -901px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-snowball2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -901px -1549px;
|
||||
background-position: -852px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-spookySparkles2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -1549px;
|
||||
background-position: -1638px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-stoikalm2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1618px -1480px;
|
||||
background-position: -1589px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-sun2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1569px -1480px;
|
||||
background-position: -1540px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-sword2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1520px -1480px;
|
||||
background-position: -1491px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-thankyou2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1471px -1480px;
|
||||
background-position: -1442px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-thermometer2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1422px -1480px;
|
||||
background-position: -1393px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-tree2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1373px -1480px;
|
||||
background-position: -1344px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-triadbingo2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1324px -1480px;
|
||||
background-position: -1295px -1480px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-ultimate-healer2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1275px -1480px;
|
||||
background-position: -1274px -1628px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-ultimate-mage2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1274px -1628px;
|
||||
background-position: -1176px -1628px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-ultimate-rogue2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1176px -1628px;
|
||||
background-position: -490px -1628px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-ultimate-warrior2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -490px -1628px;
|
||||
background-position: 0px -1628px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-unearned2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1628px;
|
||||
background-position: -1538px -1549px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
@@ -366,415 +372,415 @@
|
||||
}
|
||||
.achievement-wolf2x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1636px -1549px;
|
||||
background-position: -1372px -1628px;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.background_alpine_slopes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -888px;
|
||||
background-position: 0px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_amid_ancient_ruins {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1036px;
|
||||
background-position: -142px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_among_giant_anemones {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -1036px;
|
||||
background-position: -284px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_apple_picking {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -1036px;
|
||||
background-position: -426px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_aquarium {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -1036px;
|
||||
background-position: -568px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_archaeological_dig {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -1036px;
|
||||
background-position: -710px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_archery_range {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -1036px;
|
||||
background-position: -852px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_at_the_docks {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -1036px;
|
||||
background-position: -994px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_aurora {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -1036px;
|
||||
background-position: -1136px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_autumn_flower_garden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -1036px;
|
||||
background-position: -1278px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.customize-option.background_autumn_flower_garden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1161px -1051px;
|
||||
background-position: -1303px -15px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.background_autumn_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px 0px;
|
||||
background-position: -1278px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_avalanche {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -148px;
|
||||
background-position: -1278px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_back_alley {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -296px;
|
||||
background-position: -1278px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_back_of_giant_beast {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -444px;
|
||||
background-position: -1278px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bamboo_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -592px;
|
||||
background-position: -1278px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bayou {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -740px;
|
||||
background-position: -1278px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_beach {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -888px;
|
||||
background-position: -1278px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_beehive {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -1036px;
|
||||
background-position: 0px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bell_tower {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1184px;
|
||||
background-position: -142px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_beside_well {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -1184px;
|
||||
background-position: -284px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_birch_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -1184px;
|
||||
background-position: -426px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_blacksmithy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -1184px;
|
||||
background-position: -568px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_blizzard {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -1184px;
|
||||
background-position: -710px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_blossoming_desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -1184px;
|
||||
background-position: -852px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_blue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -1184px;
|
||||
background-position: -994px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bridge {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -1184px;
|
||||
background-position: -1136px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bug_covered_log {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -1184px;
|
||||
background-position: -1278px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_buried_treasure {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -1184px;
|
||||
background-position: -1420px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_champions_colosseum {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px 0px;
|
||||
background-position: -1420px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cherry_trees {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -148px;
|
||||
background-position: -1420px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_chessboard_land {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -296px;
|
||||
background-position: -1420px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_clouds {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -444px;
|
||||
background-position: 0px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_coral_reef {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px 0px;
|
||||
background-position: -1420px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cornfields {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -740px;
|
||||
background-position: -1420px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cozy_barn {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -888px;
|
||||
background-position: -1420px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cozy_bedroom {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -1036px;
|
||||
background-position: -1420px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cozy_library {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -1184px;
|
||||
background-position: 0px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_creepy_castle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1332px;
|
||||
background-position: -142px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_crosscountry_ski_trail {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -1332px;
|
||||
background-position: -284px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_crystal_cave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -1332px;
|
||||
background-position: -426px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dark_deep {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -1332px;
|
||||
background-position: -568px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_deep_mine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -1332px;
|
||||
background-position: -710px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_deep_sea {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -1332px;
|
||||
background-position: -852px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_desert_dunes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -1332px;
|
||||
background-position: -994px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_castle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -1332px;
|
||||
background-position: -1136px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_city {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -1332px;
|
||||
background-position: -1278px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_ruins {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1278px -1332px;
|
||||
background-position: -1420px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_distant_castle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -1332px;
|
||||
background-position: -1562px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dojo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px 0px;
|
||||
background-position: -1562px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_drifting_raft {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -148px;
|
||||
background-position: -1562px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_driving_a_coach {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -296px;
|
||||
background-position: -1562px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_driving_a_sleigh {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -444px;
|
||||
background-position: -1562px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_duck_pond {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -592px;
|
||||
background-position: -1562px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dungeon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -740px;
|
||||
background-position: -1562px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dusty_canyons {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -888px;
|
||||
background-position: -1562px -1036px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_elegant_balcony {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -1036px;
|
||||
background-position: -1562px -1184px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fairy_ring {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -1184px;
|
||||
background-position: -1562px -1332px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fantastical_shoe_store {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1562px -1332px;
|
||||
background-position: 0px -1480px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_farmhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1480px;
|
||||
background-position: -142px -1480px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fiber_arts_room {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -1480px;
|
||||
background-position: -284px -1480px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_field_with_colored_eggs {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -1480px;
|
||||
background-position: -426px -1480px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_floating_islands {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -1480px;
|
||||
background-position: -568px -1480px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_floral_meadow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -1480px;
|
||||
background-position: -710px -1480px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flower_market {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -1480px;
|
||||
background-position: -1420px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.customize-option.background_flower_market {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -735px -1495px;
|
||||
background-position: -1445px -607px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.background_flying_over_a_field_of_wildflowers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1420px -592px;
|
||||
background-position: -1136px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.customize-option.background_flying_over_a_field_of_wildflowers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1445px -607px;
|
||||
background-position: -1161px -903px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
@@ -1,96 +1,156 @@
|
||||
.quest_bunny {
|
||||
.quest_alligator {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -1543px;
|
||||
width: 210px;
|
||||
height: 186px;
|
||||
}
|
||||
.quest_butterfly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1320px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_cheetah {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -220px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_cow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -175px;
|
||||
width: 174px;
|
||||
background-position: -1320px -1112px;
|
||||
width: 201px;
|
||||
height: 213px;
|
||||
}
|
||||
.quest_dilatory {
|
||||
.quest_armadillo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -220px -232px;
|
||||
background-position: -1320px -660px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatoryDistress1 {
|
||||
.quest_atom1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -1332px;
|
||||
width: 210px;
|
||||
height: 210px;
|
||||
}
|
||||
.quest_dilatoryDistress2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -932px;
|
||||
width: 150px;
|
||||
background-position: -1082px -1332px;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_dilatoryDistress3 {
|
||||
.quest_atom2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px -220px;
|
||||
background-position: -642px -1534px;
|
||||
width: 207px;
|
||||
height: 138px;
|
||||
}
|
||||
.quest_atom3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -211px -1534px;
|
||||
width: 216px;
|
||||
height: 180px;
|
||||
}
|
||||
.quest_axolotl {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatory_derby {
|
||||
.quest_badger {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -232px;
|
||||
background-position: -660px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dolphin {
|
||||
.quest_basilist {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
background-position: -191px -1721px;
|
||||
width: 189px;
|
||||
height: 141px;
|
||||
}
|
||||
.quest_dustbunnies {
|
||||
.quest_beetle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -1332px;
|
||||
width: 204px;
|
||||
height: 201px;
|
||||
}
|
||||
.quest_bronze {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -220px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_egg {
|
||||
.quest_bunny {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -573px;
|
||||
width: 165px;
|
||||
height: 207px;
|
||||
background-position: 0px -1534px;
|
||||
width: 210px;
|
||||
height: 186px;
|
||||
}
|
||||
.quest_evilsanta {
|
||||
.quest_butterfly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -1385px;
|
||||
width: 118px;
|
||||
height: 131px;
|
||||
background-position: -660px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_evilsanta2 {
|
||||
.quest_cheetah {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_cow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px 0px;
|
||||
width: 174px;
|
||||
height: 213px;
|
||||
}
|
||||
.quest_dilatory {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatoryDistress1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1540px -1082px;
|
||||
width: 210px;
|
||||
height: 210px;
|
||||
}
|
||||
.quest_dilatoryDistress2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -573px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_dilatoryDistress3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatory_derby {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dolphin {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dustbunnies {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_egg {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -214px;
|
||||
width: 165px;
|
||||
height: 207px;
|
||||
}
|
||||
.quest_evilsanta {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -724px;
|
||||
width: 118px;
|
||||
height: 131px;
|
||||
}
|
||||
.quest_evilsanta2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px -660px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_falcon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -220px;
|
||||
background-position: 0px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_ferret {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -440px;
|
||||
background-position: -220px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
@@ -102,19 +162,19 @@
|
||||
}
|
||||
.quest_ghost_stag {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -220px -672px;
|
||||
background-position: -660px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_goldenknight1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px -672px;
|
||||
background-position: -880px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_goldenknight2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1305px -1332px;
|
||||
background-position: -1333px -1332px;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
}
|
||||
@@ -126,91 +186,91 @@
|
||||
}
|
||||
.quest_gryphon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1088px -1332px;
|
||||
background-position: -865px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_guineapig {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px -220px;
|
||||
background-position: -1320px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_harpy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px -440px;
|
||||
background-position: -220px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_hedgehog {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -211px -1332px;
|
||||
background-position: -205px -1332px;
|
||||
width: 219px;
|
||||
height: 186px;
|
||||
}
|
||||
.quest_hippo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -892px;
|
||||
background-position: 0px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_horse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -220px 0px;
|
||||
background-position: -220px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_kangaroo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px -892px;
|
||||
background-position: -440px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_kraken {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -871px -1332px;
|
||||
background-position: -648px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_lostMasterclasser1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -892px;
|
||||
background-position: -880px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_lostMasterclasser2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px -892px;
|
||||
background-position: -1100px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_lostMasterclasser3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1320px 0px;
|
||||
background-position: -660px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_mayhemMistiflying1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -1083px;
|
||||
background-position: -1762px -422px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_mayhemMistiflying2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -672px;
|
||||
background-position: -1320px -880px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_mayhemMistiflying3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1320px -660px;
|
||||
background-position: -1320px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_monkey {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1320px -880px;
|
||||
background-position: -1100px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
@@ -222,49 +282,49 @@
|
||||
}
|
||||
.quest_moon2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -220px -1112px;
|
||||
background-position: -440px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moon3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px -1112px;
|
||||
background-position: -1100px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moonstone1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px -1112px;
|
||||
background-position: -1100px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moonstone2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -880px -1112px;
|
||||
background-position: -440px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moonstone3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px -1112px;
|
||||
background-position: -220px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_nudibranch {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1540px -214px;
|
||||
background-position: -1540px -865px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
.quest_octopus {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -431px -1332px;
|
||||
background-position: -425px -1332px;
|
||||
width: 222px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_owl {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -1112px;
|
||||
background-position: -880px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
@@ -276,121 +336,61 @@
|
||||
}
|
||||
.quest_penguin {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -389px;
|
||||
background-position: 0px -1721px;
|
||||
width: 190px;
|
||||
height: 183px;
|
||||
}
|
||||
.quest_pterodactyl {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: 0px -672px;
|
||||
background-position: -440px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_rat {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px -452px;
|
||||
background-position: 0px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_robot {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px -232px;
|
||||
background-position: -660px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_rock {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1540px -865px;
|
||||
background-position: -1540px -214px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
.quest_rooster {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px 0px;
|
||||
background-position: -428px -1534px;
|
||||
width: 213px;
|
||||
height: 174px;
|
||||
}
|
||||
.quest_sabretooth {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1320px -1112px;
|
||||
background-position: -220px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_seaserpent {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px -660px;
|
||||
background-position: 0px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_sheep {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1320px -220px;
|
||||
background-position: -440px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_silver {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px -892px;
|
||||
background-position: -1320px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_slime {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1100px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_sloth {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_snail {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1540px -1082px;
|
||||
width: 219px;
|
||||
height: 213px;
|
||||
}
|
||||
.quest_snake {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -654px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_spider {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -211px -1543px;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_squirrel {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_stoikalmCalamity1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -781px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_stoikalmCalamity2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -660px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_stoikalmCalamity3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -440px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_taskwoodsTerror1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-12.png');
|
||||
background-position: -1762px -1234px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
564
website/client/assets/css/sprites/spritesmith-main-26.css
Normal file
@@ -0,0 +1,564 @@
|
||||
.Pet-Velociraptor-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -574px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Aquatic {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Bronze {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Celestial {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Cupid {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ember {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Fairy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -410px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Floral {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -410px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Frost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -410px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ghost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -410px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Glass {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -492px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Glow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -492px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -492px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Holly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -492px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-IcySnow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Peppermint {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Rainbow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-RoseQuartz {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-RoyalPurple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -410px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -492px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shadow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -574px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shimmer {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -574px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Silver {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -574px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -574px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Spooky {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -574px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-StarryNight {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Sunshine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Thunderstorm {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veggie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veteran {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Watery {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -410px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -492px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -656px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -656px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -656px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -656px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -656px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -656px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -82px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -164px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -246px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet_HatchingPotion_Aquatic {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -397px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -207px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Bronze {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -466px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Celestial {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -535px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -604px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px 0px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Cupid {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -69px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -138px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ember {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -207px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Fairy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -276px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Floral {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -345px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Frost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -414px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ghost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -483px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Glass {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -552px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Glow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -738px -621px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: 0px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Holly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -69px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_IcySnow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -138px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Peppermint {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -328px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Purple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -276px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Rainbow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -345px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -414px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_RoseQuartz {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -483px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_RoyalPurple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -552px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -621px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shadow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -690px -700px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shimmer {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px 0px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Silver {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -69px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -138px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Spooky {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -207px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_StarryNight {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -276px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Sunshine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -345px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Thunderstorm {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -414px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Watery {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -483px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -552px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-26.png');
|
||||
background-position: -807px -621px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 992 B |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 29 KiB |
BIN
website/client/assets/images/BackerOnly-Pet-Gryphatrice.gif
Normal file
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 486 KiB After Width: | Height: | Size: 487 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 430 KiB After Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 282 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 165 KiB |
BIN
website/client/assets/images/sprites/spritesmith-main-26.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 120 KiB |
@@ -74,10 +74,10 @@
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: $green-10;
|
||||
background: $green-100;
|
||||
|
||||
&:disabled {
|
||||
background: $green-10;
|
||||
background: $green-100;
|
||||
}
|
||||
|
||||
&:hover:not(:disabled), &:active, &.active {
|
||||
|
||||
@@ -78,3 +78,5 @@ $wizard-color: #2995CD;
|
||||
$gems-color: #24CC8F;
|
||||
$gold-color: #FFA624;
|
||||
$hourglass-color: #2995CD;
|
||||
|
||||
$purple-task: #925cf3;
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $maroon-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(26, 24, 29, 0.24) !important; }
|
||||
&-inner-daily-todo { background: $maroon-500 !important; }
|
||||
&-checkbox { color: $maroon-100 !important; }
|
||||
@@ -38,6 +41,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $red-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(26, 24, 29, 0.24) !important; }
|
||||
&-inner-daily-todo { background: $red-500 !important; }
|
||||
&-checkbox { color: $red-100 !important; }
|
||||
@@ -69,6 +75,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $orange-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(183, 90, 28, 0.4) !important; }
|
||||
&-inner-daily-todo { background: $orange-500 !important; }
|
||||
&-checkbox { color: $orange-100 !important; }
|
||||
@@ -109,6 +118,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $yellow-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(183, 90, 28, 0.32) !important; }
|
||||
&-inner-daily-todo { background: $yellow-500 !important; }
|
||||
&-checkbox { color: $yellow-100 !important; }
|
||||
@@ -149,6 +161,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $green-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(26, 24, 29, 0.24) !important; }
|
||||
&-inner-daily-todo { background: #77f4c7 !important; }
|
||||
&-checkbox { color: $green-10 !important; }
|
||||
@@ -179,6 +194,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $teal-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(26, 24, 29, 0.24) !important; }
|
||||
&-inner-daily-todo { background: #8dedf6 !important; }
|
||||
&-checkbox { color: $teal-100 !important; }
|
||||
@@ -209,6 +227,9 @@
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: $blue-100 !important;
|
||||
}
|
||||
&-inner-habit { background: rgba(26, 24, 29, 0.24) !important; }
|
||||
&-inner-daily-todo { background: $blue-500 !important; }
|
||||
&-checkbox { color: $blue-100 !important; }
|
||||
@@ -231,6 +252,19 @@
|
||||
}
|
||||
|
||||
&-purple { // purple, only used in modals
|
||||
&-control {
|
||||
&-bg {
|
||||
background: $purple-task !important;
|
||||
&:hover {
|
||||
.habit-control { background: rgba(26, 24, 29, 0.48) !important; }
|
||||
.daily-todo-control { background: rgba(255, 255, 255, 0.72) !important; }
|
||||
}
|
||||
}
|
||||
&-inner-habit { background: rgba(26, 24, 29, 0.24) !important; }
|
||||
&-inner-daily-todo { background: #ffffff80 !important; }
|
||||
&-checkbox { color: $purple-task !important; }
|
||||
}
|
||||
|
||||
&-modal {
|
||||
&-bg { background: $purple-300 !important; }
|
||||
&-icon { color: $purple-300 !important; }
|
||||
@@ -254,6 +288,10 @@
|
||||
|
||||
&:hover { background: rgba(255, 217, 160, 0.48) !important; }
|
||||
}
|
||||
&-bg-noninteractive {
|
||||
background: rgba(255, 217, 160, 0.32) !important;
|
||||
.small-text { color: $orange-10 !important; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// possible values are: normal, fall, habitoween, thanksgiving, winter, nye, birthday, valentines, spring, summer
|
||||
// more to be added on future seasons
|
||||
|
||||
$npc_market_flavor: 'normal';
|
||||
$npc_quests_flavor: 'normal';
|
||||
$npc_seasonal_flavor: 'normal';
|
||||
$npc_timetravelers_flavor: 'normal';
|
||||
$npc_tavern_flavor: 'normal';
|
||||
$npc_market_flavor: 'fall';
|
||||
$npc_quests_flavor: 'fall';
|
||||
$npc_seasonal_flavor: 'fall';
|
||||
$npc_timetravelers_flavor: 'fall';
|
||||
$npc_tavern_flavor: 'fall';
|
||||
|
||||
3
website/client/assets/svg/arrow_left.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#A5A1AC" fill-rule="evenodd" d="M16 0h-4v32h4V0zm16 8H16v16h16V8zM12 4H8v24h4V4zM8 8H4v16h4V8zm-4 4H0v8h4v-8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 220 B |
3
website/client/assets/svg/arrow_right.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#A5A1AC" fill-rule="evenodd" d="M16 0h4v32h-4V0zM0 8h16v16H0V8zm20-4h4v24h-4V4zm4 4h4v16h-4V8zm4 4h4v8h-4v-8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 220 B |
@@ -164,30 +164,32 @@ export default {
|
||||
classGear (heroClass) {
|
||||
if (heroClass === 'rogue') {
|
||||
return {
|
||||
armor: 'armor_rogue_5',
|
||||
head: 'head_rogue_5',
|
||||
shield: 'shield_rogue_6',
|
||||
weapon: 'weapon_rogue_6',
|
||||
armor: 'armor_special_fall2019Rogue',
|
||||
eyewear: 'eyewear_special_fall2019Rogue',
|
||||
head: 'head_special_fall2019Rogue',
|
||||
shield: 'shield_special_fall2019Rogue',
|
||||
weapon: 'weapon_special_fall2019Rogue',
|
||||
};
|
||||
} else if (heroClass === 'wizard') {
|
||||
return {
|
||||
armor: 'armor_wizard_5',
|
||||
head: 'head_wizard_5',
|
||||
weapon: 'weapon_wizard_6',
|
||||
armor: 'armor_special_fall2019Mage',
|
||||
head: 'head_special_fall2019Mage',
|
||||
weapon: 'weapon_special_fall2019Mage',
|
||||
};
|
||||
} else if (heroClass === 'healer') {
|
||||
return {
|
||||
armor: 'armor_healer_5',
|
||||
head: 'head_healer_5',
|
||||
shield: 'shield_healer_5',
|
||||
weapon: 'weapon_healer_6',
|
||||
armor: 'armor_special_fall2019Healer',
|
||||
eyewear: 'eyewear_special_fall2019Healer',
|
||||
head: 'head_special_fall2019Healer',
|
||||
shield: 'shield_special_fall2019Healer',
|
||||
weapon: 'weapon_special_fall2019Healer',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
armor: 'armor_warrior_5',
|
||||
head: 'head_warrior_5',
|
||||
shield: 'shield_warrior_5',
|
||||
weapon: 'weapon_warrior_6',
|
||||
armor: 'armor_special_fall2019Warrior',
|
||||
head: 'head_special_fall2019Warrior',
|
||||
shield: 'shield_special_fall2019Warrior',
|
||||
weapon: 'weapon_special_fall2019Warrior',
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
92
website/client/components/avatarModal/body-settings.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template lang="pug">
|
||||
#body.section.customize-section
|
||||
sub-menu.text-center(:items="items", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
|
||||
div(v-if='activeSubPage === "size"')
|
||||
customize-options(
|
||||
:items="sizes",
|
||||
:currentValue="user.preferences.size"
|
||||
)
|
||||
div(v-if='activeSubPage === "shirt"')
|
||||
customize-options(
|
||||
:items="freeShirts",
|
||||
:currentValue="user.preferences.shirt"
|
||||
)
|
||||
customize-options(
|
||||
v-if='editing',
|
||||
:items='specialShirts',
|
||||
:currentValue="user.preferences.shirt",
|
||||
:fullSet='!userOwnsSet("shirt", specialShirtKeys)',
|
||||
@unlock='unlock(`shirt.${specialShirtKeys.join(",shirt.")}`)'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import appearance from 'common/script/content/appearance';
|
||||
import {subPageMixin} from '../../mixins/subPage';
|
||||
import {userStateMixin} from '../../mixins/userState';
|
||||
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
|
||||
import subMenu from './sub-menu';
|
||||
import customizeOptions from './customize-options';
|
||||
import gem from 'assets/svg/gem.svg';
|
||||
|
||||
const freeShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price === 0);
|
||||
const specialShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'editing',
|
||||
],
|
||||
components: {
|
||||
subMenu,
|
||||
customizeOptions,
|
||||
},
|
||||
mixins: [
|
||||
subPageMixin,
|
||||
userStateMixin,
|
||||
avatarEditorUtilies,
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
specialShirtKeys,
|
||||
icons: Object.freeze({
|
||||
gem,
|
||||
}),
|
||||
items: [
|
||||
{
|
||||
id: 'size',
|
||||
label: this.$t('size'),
|
||||
},
|
||||
{
|
||||
id: 'shirt',
|
||||
label: this.$t('shirt'),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
sizes () {
|
||||
return ['slim', 'broad'].map(s => this.mapKeysToFreeOption(s, 'size'));
|
||||
},
|
||||
freeShirts () {
|
||||
return freeShirtKeys.map(s => this.mapKeysToFreeOption(s, 'shirt'));
|
||||
},
|
||||
specialShirts () {
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.specialShirtKeys;
|
||||
let options = keys.map(key => this.mapKeysToOption(key, 'shirt'));
|
||||
return options;
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.changeSubPage('size');
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
304
website/client/components/avatarModal/customize-options.vue
Normal file
@@ -0,0 +1,304 @@
|
||||
<template lang="pug">
|
||||
.customize-options(:class="{'background-set': fullSet}")
|
||||
.outer-option-background(
|
||||
v-for='option in items',
|
||||
:key='option.key',
|
||||
@click='option.click(option)',
|
||||
:class='{locked: option.gemLocked || option.goldLocked, premium: Boolean(option.gem), active: option.active || currentValue === option.key, none: option.none, hide: option.hide }'
|
||||
)
|
||||
.option
|
||||
.sprite.customize-option(:class='option.class')
|
||||
.redline-outer(v-if="option.none")
|
||||
.redline
|
||||
.gem-lock(v-if='option.gemLocked')
|
||||
.svg-icon.gem(v-html='icons.gem')
|
||||
span {{ option.gem }}
|
||||
.gold-lock(v-if='option.goldLocked')
|
||||
.svg-icon.gold(v-html='icons.gold')
|
||||
span {{ option.gold }}
|
||||
.purchase-set(v-if='fullSet', @click='unlock()')
|
||||
span.label {{ $t('purchaseAll') }}
|
||||
.svg-icon.gem(v-html='icons.gem')
|
||||
span.price 5
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gem from 'assets/svg/gem.svg';
|
||||
import gold from 'assets/svg/gold.svg';
|
||||
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
|
||||
|
||||
export default {
|
||||
props: ['items', 'currentValue', 'fullSet'],
|
||||
mixins: [
|
||||
avatarEditorUtilies,
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
gem,
|
||||
gold,
|
||||
}),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
unlock () {
|
||||
this.$emit('unlock');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.customize-options {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.outer-option-background {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
pointer-events: visible;
|
||||
cursor: pointer;
|
||||
|
||||
&.premium {
|
||||
height: 112px;
|
||||
width: 96px;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.option {
|
||||
margin: 12px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&.locked {
|
||||
border-radius: 2px;
|
||||
border: 1px solid transparent;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
background-color: $white;
|
||||
|
||||
.option {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
padding-left: 6px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 4px 0 rgba($black, 0.16), 0 1px 8px 0 rgba($black, 0.12);
|
||||
border: 1px solid $purple-500;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.locked):not(.active) {
|
||||
.option:hover {
|
||||
background-color: rgba(213, 200, 255, .32);
|
||||
}
|
||||
}
|
||||
|
||||
&.premium:not(.locked):not(.active) {
|
||||
border-radius: 2px;
|
||||
background-color: rgba(59, 202, 215, 0.1);
|
||||
}
|
||||
|
||||
&.none .option {
|
||||
.sprite {
|
||||
opacity: 0.24;
|
||||
}
|
||||
|
||||
.redline-outer {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin: 0 auto 0 0;
|
||||
|
||||
.redline {
|
||||
width: 60px;
|
||||
height: 4px;
|
||||
display: block;
|
||||
background: red;
|
||||
transform: rotate(-45deg);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 20px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active .option {
|
||||
background: white;
|
||||
border: solid 4px $purple-300;
|
||||
}
|
||||
|
||||
&.premium:not(.active) .option {
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
.option {
|
||||
vertical-align: bottom;
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
|
||||
margin: 12px 8px;
|
||||
border: 4px solid transparent;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.outer-option-background:not(.none) {
|
||||
|
||||
.sprite.customize-option {
|
||||
// margin: 0 auto;
|
||||
//margin-left: -3px;
|
||||
//margin-top: -7px;
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
|
||||
&.size, &.shirt {
|
||||
margin-top: -8px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
&.color-bangs {
|
||||
margin-top: 3px;
|
||||
}
|
||||
&.skin {
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
&.chair {
|
||||
margin-left: -1px;
|
||||
margin-top: -1px;
|
||||
|
||||
&.button_chair_black {
|
||||
// different sprite margin?
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
&.handleless {
|
||||
margin-left: -5px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
}
|
||||
&.color, &.bangs {
|
||||
margin-top: 4px;
|
||||
margin-left: -3px;
|
||||
}
|
||||
|
||||
&.hair.base {
|
||||
margin-top: 0px;
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
&.headAccessory {
|
||||
margin-top: 0;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
&.headband {
|
||||
margin-top: -6px;
|
||||
margin-left: -27px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-center {
|
||||
.gem-lock, .gold-lock {
|
||||
display: inline-block;
|
||||
margin: 0 auto 8px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.gem-lock, .gold-lock {
|
||||
.svg-icon {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
margin-left: .5em;
|
||||
}
|
||||
|
||||
.svg-icon, span {
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.gem-lock span {
|
||||
color: $green-10
|
||||
}
|
||||
|
||||
.purchase-set {
|
||||
background: #fff;
|
||||
padding: 0.5em;
|
||||
border-radius: 0 0 2px 2px;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
span.price {
|
||||
color: #24cc8f;
|
||||
}
|
||||
|
||||
.gem, .coin {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
&.single {
|
||||
width: 141px;
|
||||
}
|
||||
|
||||
width: 100%;
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.gem, .coin {
|
||||
width: 20px;
|
||||
margin: 0 .5em;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.background-set {
|
||||
background-color: #edecee;
|
||||
border-radius: 2px;
|
||||
|
||||
padding-top: 12px;
|
||||
margin-left: 12px;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
|
||||
width: calc(100% - 24px);
|
||||
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
|
||||
max-width: unset; // disable col12 styling
|
||||
flex: unset;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
272
website/client/components/avatarModal/extra-settings.vue
Normal file
@@ -0,0 +1,272 @@
|
||||
<template lang="pug">
|
||||
#extra.section.container.customize-section
|
||||
sub-menu.text-center(:items="extraSubMenuItems", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
|
||||
|
||||
#hair-color(v-if='activeSubPage === "glasses"')
|
||||
customize-options(
|
||||
:items="eyewear"
|
||||
)
|
||||
|
||||
#animal-ears(v-if='activeSubPage === "ears"')
|
||||
customize-options(
|
||||
:items="animalItems('headAccessory')",
|
||||
:fullSet='!animalItemsOwned("headAccessory")',
|
||||
@unlock='unlock(animalItemsUnlockString("headAccessory"))'
|
||||
)
|
||||
|
||||
#animal-tails(v-if='activeSubPage === "tails"')
|
||||
customize-options(
|
||||
:items="animalItems('back')",
|
||||
:fullSet='!animalItemsOwned("back")',
|
||||
@unlock='unlock(animalItemsUnlockString("back"))'
|
||||
)
|
||||
#headband(v-if='activeSubPage === "headband"')
|
||||
customize-options(
|
||||
:items="headbands",
|
||||
)
|
||||
|
||||
#wheelchairs(v-if='activeSubPage === "wheelchair"')
|
||||
customize-options(
|
||||
:items="chairs",
|
||||
)
|
||||
#flowers(v-if='activeSubPage === "flower"')
|
||||
customize-options(
|
||||
:items="flowers",
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import appearance from 'common/script/content/appearance';
|
||||
import {subPageMixin} from '../../mixins/subPage';
|
||||
import {userStateMixin} from '../../mixins/userState';
|
||||
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
|
||||
import subMenu from './sub-menu';
|
||||
import customizeOptions from './customize-options';
|
||||
import gem from 'assets/svg/gem.svg';
|
||||
|
||||
const freeShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price === 0);
|
||||
const specialShirtKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'editing',
|
||||
],
|
||||
components: {
|
||||
subMenu,
|
||||
customizeOptions,
|
||||
},
|
||||
mixins: [
|
||||
subPageMixin,
|
||||
userStateMixin,
|
||||
avatarEditorUtilies,
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
animalItemKeys: {
|
||||
back: ['bearTail', 'cactusTail', 'foxTail', 'lionTail', 'pandaTail', 'pigTail', 'tigerTail', 'wolfTail'],
|
||||
headAccessory: ['bearEars', 'cactusEars', 'foxEars', 'lionEars', 'pandaEars', 'pigEars', 'tigerEars', 'wolfEars'],
|
||||
},
|
||||
chairKeys: ['none', 'black', 'blue', 'green', 'pink', 'red', 'yellow', 'handleless_black', 'handleless_blue', 'handleless_green', 'handleless_pink', 'handleless_red', 'handleless_yellow'],
|
||||
specialShirtKeys,
|
||||
icons: Object.freeze({
|
||||
gem,
|
||||
}),
|
||||
items: [
|
||||
{
|
||||
id: 'size',
|
||||
label: this.$t('size'),
|
||||
},
|
||||
{
|
||||
id: 'shirt',
|
||||
label: this.$t('shirt'),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
extraSubMenuItems () {
|
||||
const items = [];
|
||||
|
||||
if (this.editing) {
|
||||
items.push({
|
||||
id: 'glasses',
|
||||
label: this.$t('glasses'),
|
||||
});
|
||||
}
|
||||
|
||||
items.push(
|
||||
{
|
||||
id: 'wheelchair',
|
||||
label: this.$t('wheelchair'),
|
||||
},
|
||||
{
|
||||
id: 'flower',
|
||||
label: this.$t('accent'),
|
||||
},
|
||||
);
|
||||
|
||||
if (this.editing) {
|
||||
items.push({
|
||||
id: 'ears',
|
||||
label: this.$t('animalEars'),
|
||||
});
|
||||
|
||||
items.push({
|
||||
id: 'tails',
|
||||
label: this.$t('animalTails'),
|
||||
});
|
||||
|
||||
items.push({
|
||||
id: 'headband',
|
||||
label: this.$t('headband'),
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
eyewear () {
|
||||
let keys = [
|
||||
'blackTopFrame', 'blueTopFrame', 'greenTopFrame', 'pinkTopFrame', 'redTopFrame', 'whiteTopFrame', 'yellowTopFrame',
|
||||
'blackHalfMoon', 'blueHalfMoon', 'greenHalfMoon', 'pinkHalfMoon', 'redHalfMoon', 'whiteHalfMoon', 'yellowHalfMoon',
|
||||
];
|
||||
let options = keys.map(key => {
|
||||
let newKey = `eyewear_special_${key}`;
|
||||
let option = {};
|
||||
option.key = key;
|
||||
option.active = this.user.preferences.costume ? this.user.items.gear.costume.eyewear === newKey : this.user.items.gear.equipped.eyewear === newKey;
|
||||
option.class = `eyewear_special_${key}`;
|
||||
option.click = () => {
|
||||
let type = this.user.preferences.costume ? 'costume' : 'equipped';
|
||||
|
||||
return this.equip(newKey, type);
|
||||
};
|
||||
return option;
|
||||
});
|
||||
return options;
|
||||
},
|
||||
freeShirts () {
|
||||
return freeShirtKeys.map(s => this.mapKeysToFreeOption(s, 'shirt'));
|
||||
},
|
||||
specialShirts () {
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.specialShirtKeys;
|
||||
let options = keys.map(key => this.mapKeysToOption(key, 'shirt'));
|
||||
return options;
|
||||
},
|
||||
headbands () {
|
||||
let keys = ['blackHeadband', 'blueHeadband', 'greenHeadband', 'pinkHeadband', 'redHeadband', 'whiteHeadband', 'yellowHeadband'];
|
||||
let options = keys.map(key => {
|
||||
let newKey = `headAccessory_special_${key}`;
|
||||
let option = {};
|
||||
option.key = key;
|
||||
option.active = this.user.preferences.costume ? this.user.items.gear.costume.headAccessory === newKey : this.user.items.gear.equipped.headAccessory === newKey;
|
||||
option.class = `headAccessory_special_${option.key} headband`;
|
||||
option.click = () => {
|
||||
let type = this.user.preferences.costume ? 'costume' : 'equipped';
|
||||
return this.equip(newKey, type);
|
||||
};
|
||||
return option;
|
||||
});
|
||||
return options;
|
||||
},
|
||||
chairs () {
|
||||
let options = this.chairKeys.map(key => {
|
||||
let option = {};
|
||||
option.key = key;
|
||||
if (key === 'none') {
|
||||
option.none = true;
|
||||
}
|
||||
option.active = this.user.preferences.chair === key;
|
||||
option.class = `button_chair_${key} chair ${key.includes('handleless_') ? 'handleless' : ''}`;
|
||||
option.click = () => {
|
||||
return this.set({'preferences.chair': key});
|
||||
};
|
||||
return option;
|
||||
});
|
||||
return options;
|
||||
},
|
||||
flowers () {
|
||||
let keys = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
||||
let options = keys.map(key => {
|
||||
let option = {};
|
||||
option.key = key;
|
||||
if (key === 0) {
|
||||
option.none = true;
|
||||
}
|
||||
option.active = this.user.preferences.hair.flower === key;
|
||||
option.class = `hair_flower_${key} flower`;
|
||||
option.click = () => {
|
||||
return this.set({'preferences.hair.flower': key});
|
||||
};
|
||||
return option;
|
||||
});
|
||||
return options;
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.changeSubPage(this.extraSubMenuItems[0].id);
|
||||
},
|
||||
methods: {
|
||||
animalItems (category) {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.animalItemKeys[category];
|
||||
let options = keys.map(key => {
|
||||
let newKey = `${category}_special_${key}`;
|
||||
let userPurchased = this.user.items.gear.owned[newKey];
|
||||
|
||||
let option = {};
|
||||
option.key = key;
|
||||
option.active = this.user.preferences.costume ? this.user.items.gear.costume[category] === newKey : this.user.items.gear.equipped[category] === newKey;
|
||||
option.class = `headAccessory_special_${option.key} ${category}`;
|
||||
if (category === 'back') {
|
||||
option.class = `icon_back_special_${option.key} back`;
|
||||
}
|
||||
option.gemLocked = userPurchased === undefined;
|
||||
option.goldLocked = userPurchased === false;
|
||||
if (option.goldLocked) {
|
||||
option.gold = 20;
|
||||
}
|
||||
if (option.gemLocked) {
|
||||
option.gem = 2;
|
||||
}
|
||||
option.locked = option.gemLocked || option.goldLocked;
|
||||
option.click = () => {
|
||||
if (option.gemLocked) {
|
||||
return this.unlock(`items.gear.owned.${newKey}`);
|
||||
} else if (option.goldLocked) {
|
||||
return this.buy(newKey);
|
||||
} else {
|
||||
let type = this.user.preferences.costume ? 'costume' : 'equipped';
|
||||
return this.equip(newKey, type);
|
||||
}
|
||||
};
|
||||
return option;
|
||||
});
|
||||
return options;
|
||||
},
|
||||
animalItemsUnlockString (category) {
|
||||
const keys = this.animalItemKeys[category].map(key => {
|
||||
return `items.gear.owned.${category}_special_${key}`;
|
||||
});
|
||||
|
||||
return keys.join(',');
|
||||
},
|
||||
animalItemsOwned (category) {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
|
||||
let own = true;
|
||||
this.animalItemKeys[category].forEach(key => {
|
||||
if (this.user.items.gear.owned[`${category}_special_${key}`] === undefined) own = false;
|
||||
});
|
||||
return own;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
341
website/client/components/avatarModal/hair-settings.vue
Normal file
@@ -0,0 +1,341 @@
|
||||
<template lang="pug">
|
||||
#hair.section.customize-section
|
||||
sub-menu.text-center(:items="hairSubMenuItems", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
|
||||
|
||||
#hair-color(v-if='activeSubPage === "color"')
|
||||
customize-options(
|
||||
:items="freeHairColors",
|
||||
:currentValue="user.preferences.hair.color"
|
||||
)
|
||||
|
||||
div(v-if='editing && set.key !== "undefined"', v-for='set in seasonalHairColors')
|
||||
customize-options(
|
||||
:items='set.options',
|
||||
:currentValue="user.preferences.skin",
|
||||
:fullSet='!hideSet(set) && !userOwnsSet("hair", set.keys, "color")',
|
||||
@unlock='unlock(`hair.color.${set.keys.join(",hair.color.")}`)'
|
||||
)
|
||||
|
||||
#style(v-if='activeSubPage === "style"')
|
||||
div(v-for='set in styleSets')
|
||||
customize-options(
|
||||
:items='set.options',
|
||||
:fullSet='set.fullSet',
|
||||
@unlock='set.unlock()'
|
||||
)
|
||||
#bangs(v-if='activeSubPage === "bangs"')
|
||||
customize-options(
|
||||
:items='hairBangs',
|
||||
:currentValue="user.preferences.hair.bangs"
|
||||
)
|
||||
#facialhair(v-if='activeSubPage === "facialhair"')
|
||||
customize-options(
|
||||
v-if='editing',
|
||||
:items='mustacheList'
|
||||
)
|
||||
customize-options(
|
||||
v-if='editing',
|
||||
:items='beardList',
|
||||
:fullSet='isPurchaseAllNeeded("hair", ["baseHair5", "baseHair6"], ["mustache", "beard"])',
|
||||
@unlock='unlock(`hair.mustache.${baseHair5Keys.join(",hair.mustache.")},hair.beard.${baseHair6Keys.join(",hair.beard.")}`)'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import appearance from 'common/script/content/appearance';
|
||||
import {subPageMixin} from '../../mixins/subPage';
|
||||
import {userStateMixin} from '../../mixins/userState';
|
||||
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
|
||||
import subMenu from './sub-menu';
|
||||
import customizeOptions from './customize-options';
|
||||
import gem from 'assets/svg/gem.svg';
|
||||
import appearanceSets from 'common/script/content/appearance/sets';
|
||||
import groupBy from 'lodash/groupBy';
|
||||
|
||||
const hairColorBySet = groupBy(appearance.hair.color, 'set.key');
|
||||
const freeHairColorKeys = hairColorBySet[undefined].map(s => s.key);
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'editing',
|
||||
],
|
||||
components: {
|
||||
subMenu,
|
||||
customizeOptions,
|
||||
},
|
||||
mixins: [
|
||||
subPageMixin,
|
||||
userStateMixin,
|
||||
avatarEditorUtilies,
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
freeHairColorKeys,
|
||||
icons: Object.freeze({
|
||||
gem,
|
||||
}),
|
||||
baseHair1: [1, 3],
|
||||
baseHair2Keys: [2, 4, 5, 6, 7, 8],
|
||||
baseHair3Keys: [9, 10, 11, 12, 13, 14],
|
||||
baseHair4Keys: [15, 16, 17, 18, 19, 20],
|
||||
baseHair5Keys: [1, 2],
|
||||
baseHair6Keys: [1, 2, 3],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hairSubMenuItems () {
|
||||
const items = [
|
||||
{
|
||||
id: 'color',
|
||||
label: this.$t('color'),
|
||||
},
|
||||
{
|
||||
id: 'bangs',
|
||||
label: this.$t('bangs'),
|
||||
},
|
||||
{
|
||||
id: 'style',
|
||||
label: this.$t('style'),
|
||||
},
|
||||
];
|
||||
|
||||
if (this.editing) {
|
||||
items.push({
|
||||
id: 'facialhair',
|
||||
label: this.$t('facialhair'),
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
freeHairColors () {
|
||||
return freeHairColorKeys.map(s => this.mapKeysToFreeOption(s, 'hair', 'color'));
|
||||
},
|
||||
seasonalHairColors () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
|
||||
let seasonalHairColors = [];
|
||||
for (let key in hairColorBySet) {
|
||||
let set = hairColorBySet[key];
|
||||
|
||||
let keys = set.map(item => {
|
||||
return item.key;
|
||||
});
|
||||
|
||||
let options = keys.map(optionKey => {
|
||||
const option = this.mapKeysToOption(optionKey, 'hair', 'color', key);
|
||||
return option;
|
||||
});
|
||||
|
||||
let text = this.$t(key);
|
||||
if (appearanceSets[key] && appearanceSets[key].text) {
|
||||
text = appearanceSets[key].text();
|
||||
}
|
||||
|
||||
let compiledSet = {
|
||||
key,
|
||||
options,
|
||||
keys,
|
||||
text,
|
||||
};
|
||||
seasonalHairColors.push(compiledSet);
|
||||
}
|
||||
|
||||
return seasonalHairColors;
|
||||
},
|
||||
premiumHairColors () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.premiumHairColorKeys;
|
||||
let options = keys.map(key => {
|
||||
return this.mapKeysToOption(key, 'hair', 'color');
|
||||
});
|
||||
return options;
|
||||
},
|
||||
baseHair2 () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.baseHair2Keys;
|
||||
let options = keys.map(key => {
|
||||
return this.mapKeysToOption(key, 'hair', 'base');
|
||||
});
|
||||
return options;
|
||||
},
|
||||
baseHair3 () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.baseHair3Keys;
|
||||
let options = keys.map(key => {
|
||||
const option = this.mapKeysToOption(key, 'hair', 'base');
|
||||
return option;
|
||||
});
|
||||
return options;
|
||||
},
|
||||
baseHair4 () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.baseHair4Keys;
|
||||
let options = keys.map(key => {
|
||||
return this.mapKeysToOption(key, 'hair', 'base');
|
||||
});
|
||||
return options;
|
||||
},
|
||||
baseHair5 () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.baseHair5Keys;
|
||||
let options = keys.map(key => {
|
||||
return this.mapKeysToOption(key, 'hair', 'mustache');
|
||||
});
|
||||
return options;
|
||||
},
|
||||
baseHair6 () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
let keys = this.baseHair6Keys;
|
||||
let options = keys.map(key => {
|
||||
return this.mapKeysToOption(key, 'hair', 'beard');
|
||||
});
|
||||
return options;
|
||||
},
|
||||
hairBangs () {
|
||||
const none = this.mapKeysToFreeOption(0, 'hair', 'bangs');
|
||||
none.none = true;
|
||||
|
||||
const options = [1, 2, 3, 4].map(s => this.mapKeysToFreeOption(s, 'hair', 'bangs'));
|
||||
|
||||
return [none, ...options];
|
||||
},
|
||||
mustacheList () {
|
||||
const noneOption = this.mapKeysToFreeOption(0, 'hair', 'mustache');
|
||||
noneOption.none = true;
|
||||
|
||||
return [noneOption, ...this.baseHair5];
|
||||
},
|
||||
beardList () {
|
||||
const noneOption = this.mapKeysToFreeOption(0, 'hair', 'beard');
|
||||
noneOption.none = true;
|
||||
|
||||
return [noneOption, ...this.baseHair6];
|
||||
},
|
||||
styleSets () {
|
||||
const sets = [];
|
||||
|
||||
const emptyHairBase = {
|
||||
...this.mapKeysToFreeOption(0, 'hair', 'base'),
|
||||
none: true,
|
||||
};
|
||||
|
||||
if (this.editing) {
|
||||
sets.push({
|
||||
fullSet: !this.userOwnsSet('hair', this.baseHair3Keys, 'base'),
|
||||
unlock: () => this.unlock(`hair.base.${this.baseHair3Keys.join(',hair.base.')}`),
|
||||
options: [
|
||||
emptyHairBase,
|
||||
...this.baseHair3,
|
||||
],
|
||||
});
|
||||
|
||||
sets.push({
|
||||
fullSet: !this.userOwnsSet('hair', this.baseHair4Keys, 'base'),
|
||||
unlock: () => this.unlock(`hair.base.${this.baseHair4Keys.join(',hair.base.')}`),
|
||||
options: [
|
||||
...this.baseHair4,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
sets.push({
|
||||
options: [
|
||||
emptyHairBase,
|
||||
...this.baseHair1.map(key => this.mapKeysToFreeOption(key, 'hair', 'base')),
|
||||
],
|
||||
});
|
||||
|
||||
if (this.editing) {
|
||||
sets.push({
|
||||
fullSet: !this.userOwnsSet('hair', this.baseHair2Keys, 'base'),
|
||||
unlock: () => this.unlock(`hair.base.${this.baseHair2Keys.join(',hair.base.')}`),
|
||||
options: [
|
||||
...this.baseHair2,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return sets;
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.changeSubPage('color');
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Allows you to find out whether you need the "Purchase All" button or not. If there are more than 2 unpurchased items, returns true, otherwise returns false.
|
||||
* @param {string} category - The selected category.
|
||||
* @param {string[]} keySets - The items keySets.
|
||||
* @param {string[]} [types] - The items types (subcategories). Optional.
|
||||
* @returns {boolean} - Determines whether the "Purchase All" button is needed (true) or not (false).
|
||||
*/
|
||||
isPurchaseAllNeeded (category, keySets, types) {
|
||||
const purchasedItemsLengths = [];
|
||||
// If item types are specified, count them
|
||||
if (types && types.length > 0) {
|
||||
// Types can be undefined, so we must check them.
|
||||
types.forEach((type) => {
|
||||
if (this.user.purchased[category][type]) {
|
||||
purchasedItemsLengths
|
||||
.push(Object.keys(this.user.purchased[category][type]).length);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let purchasedItemsCounter = 0;
|
||||
|
||||
// If types are not specified, recursively
|
||||
// search for purchased items in the category
|
||||
const findPurchasedItems = (item) => {
|
||||
if (typeof item === 'object') {
|
||||
Object.values(item)
|
||||
.forEach((innerItem) => {
|
||||
if (typeof innerItem === 'boolean' && innerItem === true) {
|
||||
purchasedItemsCounter += 1;
|
||||
}
|
||||
return findPurchasedItems(innerItem);
|
||||
});
|
||||
}
|
||||
return purchasedItemsCounter;
|
||||
};
|
||||
|
||||
findPurchasedItems(this.user.purchased[category]);
|
||||
if (purchasedItemsCounter > 0) {
|
||||
purchasedItemsLengths.push(purchasedItemsCounter);
|
||||
}
|
||||
}
|
||||
|
||||
// We don't need to count the key sets (below)
|
||||
// if there are no purchased items at all.
|
||||
if (purchasedItemsLengths.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const allItemsLengths = [];
|
||||
// Key sets must be specify correctly.
|
||||
keySets.forEach((keySet) => {
|
||||
allItemsLengths.push(Object.keys(this[keySet]).length);
|
||||
});
|
||||
|
||||
// Simply sum all the length values and
|
||||
// write them into variables for the convenience.
|
||||
const allItems = allItemsLengths.reduce((acc, val) => acc + val);
|
||||
const purchasedItems = purchasedItemsLengths.reduce((acc, val) => acc + val);
|
||||
|
||||
const unpurchasedItems = allItems - purchasedItems;
|
||||
return unpurchasedItems > 2;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
114
website/client/components/avatarModal/skin-settings.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<template lang="pug">
|
||||
#skin.section.customize-section
|
||||
sub-menu.text-center(:items="skinSubMenuItems", :activeSubPage="activeSubPage", @changeSubPage="changeSubPage($event)")
|
||||
customize-options(
|
||||
:items="freeSkins",
|
||||
:currentValue="user.preferences.skin"
|
||||
)
|
||||
|
||||
div(v-if='editing && set.key !== "undefined"', v-for='set in seasonalSkins')
|
||||
customize-options(
|
||||
:items='set.options',
|
||||
:currentValue="user.preferences.skin",
|
||||
:fullSet='!hideSet(set) && !userOwnsSet("skin", set.keys)',
|
||||
@unlock='unlock(`skin.${set.keys.join(",skin.")}`)'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import appearance from 'common/script/content/appearance';
|
||||
import {subPageMixin} from '../../mixins/subPage';
|
||||
import {userStateMixin} from '../../mixins/userState';
|
||||
import {avatarEditorUtilies} from '../../mixins/avatarEditUtilities';
|
||||
import appearanceSets from 'common/script/content/appearance/sets';
|
||||
import subMenu from './sub-menu';
|
||||
import customizeOptions from './customize-options';
|
||||
import gem from 'assets/svg/gem.svg';
|
||||
|
||||
import groupBy from 'lodash/groupBy';
|
||||
|
||||
const skinsBySet = groupBy(appearance.skin, 'set.key');
|
||||
|
||||
const freeSkinKeys = skinsBySet[undefined].map(s => s.key);
|
||||
|
||||
// const specialSkinKeys = Object.keys(appearance.shirt).filter(k => appearance.shirt[k].price !== 0);
|
||||
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'editing',
|
||||
],
|
||||
components: {
|
||||
subMenu,
|
||||
customizeOptions,
|
||||
},
|
||||
mixins: [
|
||||
subPageMixin,
|
||||
userStateMixin,
|
||||
avatarEditorUtilies,
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
freeSkinKeys,
|
||||
icons: Object.freeze({
|
||||
gem,
|
||||
}),
|
||||
skinSubMenuItems: [
|
||||
{
|
||||
id: 'color',
|
||||
label: this.$t('color'),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
freeSkins () {
|
||||
return freeSkinKeys.map(s => this.mapKeysToFreeOption(s, 'skin'));
|
||||
},
|
||||
seasonalSkins () {
|
||||
// @TODO: For some resonse when I use $set on the user purchases object, this is not recomputed. Hack for now
|
||||
let backgroundUpdate = this.backgroundUpdate; // eslint-disable-line
|
||||
|
||||
let seasonalSkins = [];
|
||||
for (let setKey in skinsBySet) {
|
||||
let set = skinsBySet[setKey];
|
||||
|
||||
let keys = set.map(item => {
|
||||
return item.key;
|
||||
});
|
||||
|
||||
let options = keys.map(optionKey => {
|
||||
const option = this.mapKeysToOption(optionKey, 'skin', '', setKey);
|
||||
|
||||
return option;
|
||||
});
|
||||
|
||||
let text = this.$t(setKey);
|
||||
if (appearanceSets[setKey] && appearanceSets[setKey].text) {
|
||||
text = appearanceSets[setKey].text();
|
||||
}
|
||||
|
||||
let compiledSet = {
|
||||
key: setKey,
|
||||
options,
|
||||
keys,
|
||||
text,
|
||||
};
|
||||
seasonalSkins.push(compiledSet);
|
||||
}
|
||||
|
||||
return seasonalSkins;
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.changeSubPage('color');
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
52
website/client/components/avatarModal/sub-menu.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template lang="pug">
|
||||
.sub-menu.text-center
|
||||
.sub-menu-item(
|
||||
v-for="item of items",
|
||||
:key="item.id",
|
||||
@click='$emit("changeSubPage", item.id)',
|
||||
:class='{active: activeSubPage === item.id}'
|
||||
)
|
||||
strong(v-once) {{ item.label }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['items', 'activeSubPage'],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.sub-menu {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
padding-top: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.sub-menu:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sub-menu-item {
|
||||
padding: 6px 16px;
|
||||
text-align: center;
|
||||
border-bottom: 2px solid #f9f9f9;
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
line-height: 1.67;
|
||||
letter-spacing: normal;
|
||||
text-align: center;
|
||||
color: $gray-100;
|
||||
}
|
||||
|
||||
.sub-menu .sub-menu-item:hover, .sub-menu .sub-menu-item.active {
|
||||
color: $purple-200;
|
||||
border-bottom: 2px solid $purple-200;
|
||||
}
|
||||
</style>
|
||||
@@ -166,7 +166,7 @@ export default {
|
||||
},
|
||||
date (value) {
|
||||
// @TODO: Vue doesn't support this so we cant user preference
|
||||
return moment(value).toDate();
|
||||
return moment(value).toDate().toString();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -209,8 +209,6 @@ export default {
|
||||
});
|
||||
},
|
||||
async loadApprovals () {
|
||||
if (this.group.leader._id !== this.user._id) return [];
|
||||
|
||||
let approvalRequests = await this.$store.dispatch('tasks:getGroupApprovals', {
|
||||
groupId: this.searchId,
|
||||
});
|
||||
|
||||
@@ -349,25 +349,6 @@ export default {
|
||||
isMember () {
|
||||
return this.isMemberOfGroup(this.user, this.group);
|
||||
},
|
||||
memberProfileName (memberId) {
|
||||
let foundMember = find(this.group.members, function findMember (member) {
|
||||
return member._id === memberId;
|
||||
});
|
||||
return foundMember.profile.name;
|
||||
},
|
||||
isManager (memberId, group) {
|
||||
return Boolean(group.managers[memberId]);
|
||||
},
|
||||
userCanApprove (userId, group) {
|
||||
if (!group) return false;
|
||||
let leader = group.leader._id === userId;
|
||||
let userIsManager = Boolean(group.managers[userId]);
|
||||
return leader || userIsManager;
|
||||
},
|
||||
hasChallenges () {
|
||||
if (!this.group.challenges) return false;
|
||||
return this.group.challenges.length === 0;
|
||||
},
|
||||
showNoNotificationsMessage () {
|
||||
return this.group.memberCount > this.$store.state.constants.LARGE_GROUP_COUNT_MESSAGE_CUTOFF;
|
||||
},
|
||||
|
||||
@@ -250,7 +250,6 @@ div
|
||||
|
||||
&-modal {
|
||||
z-index: 1035;
|
||||
z-index: 1042; // To stay above snakbar notifications and modals
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +502,9 @@ export default {
|
||||
let droppedElement = document.getElementsByClassName('down')[0];
|
||||
if (droppedElement && droppedElement !== element) {
|
||||
droppedElement.classList.remove('down');
|
||||
droppedElement.lastChild.style.maxHeight = 0;
|
||||
if (droppedElement.lastChild) {
|
||||
droppedElement.lastChild.style.maxHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
element.classList.toggle('down');
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<template lang="pug">
|
||||
base-notification(
|
||||
:can-remove="canRemove",
|
||||
:has-icon="false",
|
||||
:notification="notification",
|
||||
:read-after-click="true",
|
||||
@click="action",
|
||||
)
|
||||
div(slot="content", v-html="notification.data.message")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
|
||||
export default {
|
||||
props: ['notification', 'canRemove'],
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
methods: {
|
||||
action () {
|
||||
const groupId = this.notification.data.groupId;
|
||||
this.$router.push({ name: 'groupPlanDetailTaskInformation', params: { groupId }});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -88,6 +88,7 @@ import QUEST_INVITATION from './notifications/questInvitation';
|
||||
import GROUP_TASK_APPROVAL from './notifications/groupTaskApproval';
|
||||
import GROUP_TASK_APPROVED from './notifications/groupTaskApproved';
|
||||
import GROUP_TASK_ASSIGNED from './notifications/groupTaskAssigned';
|
||||
import GROUP_TASK_CLAIMED from './notifications/groupTaskClaimed';
|
||||
import UNALLOCATED_STATS_POINTS from './notifications/unallocatedStatsPoints';
|
||||
import NEW_MYSTERY_ITEMS from './notifications/newMysteryItems';
|
||||
import CARD_RECEIVED from './notifications/cardReceived';
|
||||
@@ -106,7 +107,7 @@ export default {
|
||||
// One component for each type
|
||||
NEW_STUFF, GROUP_TASK_NEEDS_WORK,
|
||||
GUILD_INVITATION, PARTY_INVITATION, CHALLENGE_INVITATION,
|
||||
QUEST_INVITATION, GROUP_TASK_APPROVAL, GROUP_TASK_APPROVED, GROUP_TASK_ASSIGNED,
|
||||
QUEST_INVITATION, GROUP_TASK_APPROVAL, GROUP_TASK_APPROVED, GROUP_TASK_ASSIGNED, GROUP_TASK_CLAIMED,
|
||||
UNALLOCATED_STATS_POINTS, NEW_MYSTERY_ITEMS, CARD_RECEIVED,
|
||||
NEW_INBOX_MESSAGE, NEW_CHAT_MESSAGE,
|
||||
ACHIEVEMENT_JUST_ADD_WATER, ACHIEVEMENT_LOST_MASTERCLASSER, ACHIEVEMENT_MIND_OVER_MATTER,
|
||||
@@ -131,7 +132,7 @@ export default {
|
||||
handledNotifications: [
|
||||
'NEW_STUFF', 'GROUP_TASK_NEEDS_WORK',
|
||||
'GUILD_INVITATION', 'PARTY_INVITATION', 'CHALLENGE_INVITATION',
|
||||
'QUEST_INVITATION', 'GROUP_TASK_ASSIGNED', 'GROUP_TASK_APPROVAL', 'GROUP_TASK_APPROVED',
|
||||
'QUEST_INVITATION', 'GROUP_TASK_ASSIGNED', 'GROUP_TASK_APPROVAL', 'GROUP_TASK_APPROVED', 'GROUP_TASK_CLAIMED',
|
||||
'NEW_MYSTERY_ITEMS', 'CARD_RECEIVED',
|
||||
'NEW_INBOX_MESSAGE', 'NEW_CHAT_MESSAGE', 'UNALLOCATED_STATS_POINTS',
|
||||
'ACHIEVEMENT_JUST_ADD_WATER', 'ACHIEVEMENT_LOST_MASTERCLASSER', 'ACHIEVEMENT_MIND_OVER_MATTER',
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
// Condensed version
|
||||
.member-details.condensed.expanded {
|
||||
background: $header-dark-background;
|
||||
box-shadow: 0 0 0px 9px $header-dark-background;
|
||||
box-shadow: 0 0 0px 8px $header-dark-background;
|
||||
position: relative;
|
||||
z-index: 8;
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
height: calc(100% + 18px);
|
||||
margin-top: -9px;
|
||||
margin-top: -10px;
|
||||
margin-right: 1px;
|
||||
padding-top: 9px;
|
||||
padding-bottom: 24px;
|
||||
|
||||
@@ -1,34 +1,41 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
approval-modal(:task='task')
|
||||
.claim-bottom-message.col-12
|
||||
.task-unclaimed.d-flex.justify-content-between(v-if='!approvalRequested && !multipleApprovalsRequested')
|
||||
span {{ message }}
|
||||
a.text-right(@click='claim()', v-if='!userIsAssigned') {{ $t('claim') }}
|
||||
a.text-right(@click='unassign()', v-if='userIsAssigned') {{ $t('removeClaim') }}
|
||||
.row.task-single-approval(v-if='approvalRequested')
|
||||
.col-6.text-center
|
||||
a(@click='approve()') {{ $t('approveTask') }}
|
||||
.col-6.text-center
|
||||
a(@click='needsWork()') {{ $t('needsWork') }}
|
||||
.text-center.task-multi-approval(v-if='multipleApprovalsRequested')
|
||||
a(@click='showRequests()') {{ $t('viewRequests') }}
|
||||
.claim-bottom-message.d-flex.align-items-center(v-if='!approvalRequested && !multipleApprovalsRequested')
|
||||
.mr-auto.ml-2(v-html='message')
|
||||
.ml-auto.mr-2(v-if='!userIsAssigned')
|
||||
a(@click='claim()').claim-color {{ $t('claim') }}
|
||||
.ml-auto.mr-2(v-if='userIsAssigned')
|
||||
a(@click='unassign()').unclaim-color {{ $t('removeClaim') }}
|
||||
.claim-bottom-message.d-flex.align-items-center.justify-content-around(v-if='approvalRequested && userIsManager')
|
||||
a(@click='approve()').approve-color {{ $t('approveTask') }}
|
||||
a(@click='needsWork()') {{ $t('needsWork') }}
|
||||
.claim-bottom-message.d-flex.align-items-center(v-if='multipleApprovalsRequested && userIsManager')
|
||||
a(@click='showRequests()') {{ $t('viewRequests') }}
|
||||
</template>
|
||||
|
||||
<style lang="scss", scoped>
|
||||
.claim-bottom-message {
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.task-unclaimed {
|
||||
span {
|
||||
margin-right: 0.25rem;
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
.claim-bottom-message {
|
||||
background-color: $gray-700;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
color: $gray-200;
|
||||
font-size: 12px;
|
||||
padding-bottom: 0.25rem;
|
||||
padding-top: 0.25rem;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
.approve-color {
|
||||
color: $green-10 !important;
|
||||
}
|
||||
.claim-color {
|
||||
color: $blue-10 !important;
|
||||
}
|
||||
.unclaim-color {
|
||||
color: $red-50 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -76,8 +83,11 @@ export default {
|
||||
return this.$t('taskIsUnassigned');
|
||||
}
|
||||
},
|
||||
userIsManager () {
|
||||
if (this.group && (this.group.leader.id === this.user._id || this.group.managers[this.user._id])) return true;
|
||||
},
|
||||
approvalRequested () {
|
||||
if (this.task.approvals && this.task.approvals.length === 1) return true;
|
||||
if (this.task.approvals && this.task.approvals.length === 1 || this.task.group && this.task.group.approval && this.task.group.approval.requested) return true;
|
||||
},
|
||||
multipleApprovalsRequested () {
|
||||
if (this.task.approvals && this.task.approvals.length > 1) return true;
|
||||
@@ -85,8 +95,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async claim () {
|
||||
if (!confirm(this.$t('confirmClaim'))) return;
|
||||
|
||||
let taskId = this.task._id;
|
||||
// If we are on the user task
|
||||
if (this.task.userId) {
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
<template lang="pug">
|
||||
.claim-bottom-message.col-12.text-center(v-if='task.approvals && task.approvals.length > 0', :class="{approval: userIsAdmin}")
|
||||
.task-unclaimed
|
||||
| {{ message }}
|
||||
.claim-top-message.d-flex.align-content-center(v-if='message', :class="{'approval-action': userIsAdmin, 'approval-pending': !userIsAdmin}")
|
||||
.m-auto(v-html='message')
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.claim-bottom-message {
|
||||
z-index: 9;
|
||||
}
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
.claim-top-message {
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding-bottom: 0.25rem;
|
||||
padding-top: 0.25rem;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.approval {
|
||||
background: #24cc8f;
|
||||
color: #fff;
|
||||
}
|
||||
.approval-action {
|
||||
background: $green-100;
|
||||
}
|
||||
|
||||
.approval-pending {
|
||||
background: $gray-300;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -22,20 +31,22 @@ export default {
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
message () {
|
||||
let approvals = this.task.approvals;
|
||||
let approvals = this.task.approvals || [];
|
||||
let approvalsLength = approvals.length;
|
||||
let userIsRequesting = this.task.group.approvals && this.task.group.approvals.indexOf(this.user._id) !== -1;
|
||||
let userIsRequesting = approvals.findIndex((approval) => {
|
||||
return approval.userId.id === this.user._id;
|
||||
}) !== -1;
|
||||
|
||||
if (approvalsLength === 1 && !userIsRequesting) {
|
||||
return this.$t('userRequestsApproval', {userName: approvals[0].userId.profile.name});
|
||||
} else if (approvalsLength > 1 && !userIsRequesting) {
|
||||
return this.$t('userCountRequestsApproval', {userCount: approvalsLength});
|
||||
} else if (approvalsLength === 1 && userIsRequesting) {
|
||||
} else if (approvalsLength === 1 && userIsRequesting || this.task.group.approval && this.task.group.approval.requested && !this.task.group.approval.approved) {
|
||||
return this.$t('youAreRequestingApproval');
|
||||
}
|
||||
},
|
||||
userIsAdmin () {
|
||||
return this.group.leader.id === this.user._id;
|
||||
return this.group && (this.group.leader.id === this.user._id || this.group.managers[this.user._id]);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
text-align: center;
|
||||
|
||||
overflow-y: hidden;
|
||||
max-height: 65px; // approximate max height
|
||||
}
|
||||
|
||||
.quick-add-tip-slide-enter-active {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<template lang="pug">
|
||||
.task-wrapper
|
||||
.task(@click='castEnd($event, task)')
|
||||
approval-header(:task='task', v-if='this.task.group.id', :group='group')
|
||||
.task(@click='castEnd($event, task)', :class="[{'groupTask': task.group.id}, `type_${task.type}`]")
|
||||
approval-header(:task='task', v-if='task.group.id', :group='group')
|
||||
.d-flex(:class="{'task-not-scoreable': isUser !== true}")
|
||||
// Habits left side control
|
||||
.left-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.up.bg")
|
||||
.left-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="[{'control-bottom-box': this.task.group.id, 'control-top-box': approvalsClass}, controlClass.up.bg]")
|
||||
.task-control.habit-control(:class="controlClass.up.inner", @click="(isUser && task.up) ? score('up') : null")
|
||||
.svg-icon.lock(v-if="this.task.group.id && !isUser", v-html="icons.lock", :class="controlClass.up.icon")
|
||||
.svg-icon.positive(v-else, v-html="icons.positive")
|
||||
// Dailies and todos left side control
|
||||
.left-control.d-flex.justify-content-center(v-if="task.type === 'daily' || task.type === 'todo'", :class="controlClass.bg")
|
||||
.left-control.d-flex.justify-content-center(v-if="task.type === 'daily' || task.type === 'todo'", :class="[{'control-bottom-box': this.task.group.id, 'control-top-box': approvalsClass}, controlClass.bg]")
|
||||
.task-control.daily-todo-control(:class="controlClass.inner", @click="isUser ? score(task.completed ? 'down' : 'up') : null")
|
||||
.svg-icon.lock(v-html="icons.lock", v-if="this.task.group.id && !isUser && !task.completed", :class="controlClass.icon")
|
||||
.svg-icon.check(v-else, v-html="icons.check", :class="{'display-check-icon': task.completed, [controlClass.checkbox]: true}")
|
||||
@@ -99,7 +99,7 @@
|
||||
.tag-label(v-for="tag in getTagsFor(task)", v-markdown="tag")
|
||||
|
||||
// Habits right side control
|
||||
.right-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.down.bg")
|
||||
.right-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="[{'control-bottom-box': this.task.group.id, 'control-top-box': approvalsClass}, controlClass.down.bg]")
|
||||
.task-control.habit-control(:class="controlClass.down.inner", @click="(isUser && task.down) ? score('down') : null")
|
||||
.svg-icon.lock(v-if="this.task.group.id && !isUser", v-html="icons.lock", :class="controlClass.down.icon")
|
||||
.svg-icon.negative(v-else, v-html="icons.negative")
|
||||
@@ -107,12 +107,23 @@
|
||||
.right-control.d-flex.align-items-center.justify-content-center.reward-control(v-if="task.type === 'reward'", :class="controlClass.bg", @click="isUser ? score('down') : null")
|
||||
.svg-icon(v-html="icons.gold")
|
||||
.small-text {{task.value}}
|
||||
approval-footer(:task='task', v-if='this.task.group.id', :group='group')
|
||||
approval-footer(:task='task', v-if='task.group.id', :group='group')
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.control-bottom-box {
|
||||
border-bottom-left-radius: 0px !important;
|
||||
border-bottom-right-radius: 0px !important;
|
||||
}
|
||||
|
||||
.control-top-box {
|
||||
border-top-left-radius: 0px !important;
|
||||
border-top-right-radius: 0px !important;
|
||||
}
|
||||
|
||||
|
||||
.task {
|
||||
margin-bottom: 2px;
|
||||
box-shadow: 0 2px 2px 0 rgba($black, 0.16), 0 1px 4px 0 rgba($black, 0.12);
|
||||
@@ -122,13 +133,29 @@
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 1px 8px 0 rgba($black, 0.12), 0 4px 4px 0 rgba($black, 0.16);
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.task:not(.groupTask) {
|
||||
&:hover {
|
||||
.left-control, .right-control, .task-content {
|
||||
border-color: $purple-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task.groupTask {
|
||||
|
||||
&:hover {
|
||||
border: $purple-400 solid 1px;
|
||||
border-radius: 3px;
|
||||
margin: -1px; // to counter the border width
|
||||
margin-bottom: 1px;
|
||||
transition: none; // with transition, the border color switches from black to $purple-400
|
||||
}
|
||||
}
|
||||
|
||||
.task-habit-disabled-control-habit:hover {
|
||||
cursor: initial;
|
||||
}
|
||||
@@ -418,7 +445,6 @@
|
||||
transition-property: border-color, background, color;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
|
||||
.left-control {
|
||||
border-top-left-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
@@ -428,8 +454,14 @@
|
||||
|
||||
& + .task-content {
|
||||
border-left: none;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
}
|
||||
.task:not(.type_habit) {
|
||||
.left-control {
|
||||
& + .task-content {
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,6 +647,9 @@ export default {
|
||||
if (task.type === 'habit') return true;
|
||||
return false;
|
||||
},
|
||||
approvalsClass () {
|
||||
return this.group && this.task.approvals && this.task.approvals.length > 0;
|
||||
},
|
||||
controlClass () {
|
||||
return this.getTaskClasses(this.task, 'control', this.dueDate);
|
||||
},
|
||||
@@ -716,6 +751,16 @@ export default {
|
||||
const user = this.user;
|
||||
const task = this.task;
|
||||
|
||||
if (task.group.approval.required) {
|
||||
task.group.approval.requested = true;
|
||||
const groupResponse = await axios.get(`/api/v4/groups/${task.group.id}`);
|
||||
let managers = Object.keys(groupResponse.data.data.managers);
|
||||
managers.push(groupResponse.data.data.leader._id);
|
||||
if (managers.indexOf(user._id) !== -1) {
|
||||
task.group.approval.approved = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
scoreTask({task, user, direction});
|
||||
} catch (err) {
|
||||
@@ -739,8 +784,6 @@ export default {
|
||||
}
|
||||
|
||||
|
||||
if (task.group.approval.required) task.group.approval.requested = true;
|
||||
|
||||
Analytics.updateUser();
|
||||
const response = await axios.post(`/api/v4/tasks/${task._id}/score/${direction}`);
|
||||
const tmp = response.data.data._tmp || {}; // used to notify drops, critical hits and other bonuses
|
||||
|
||||
178
website/client/mixins/avatarEditUtilities.js
Normal file
@@ -0,0 +1,178 @@
|
||||
import moment from 'moment';
|
||||
import axios from 'axios';
|
||||
|
||||
import unlock from '../../common/script/ops/unlock';
|
||||
import buy from '../../common/script/ops/buy/buy';
|
||||
|
||||
import get from 'lodash/get';
|
||||
|
||||
import appearanceSets from 'common/script/content/appearance/sets';
|
||||
|
||||
|
||||
import {userStateMixin} from './userState';
|
||||
|
||||
export const avatarEditorUtilies = {
|
||||
mixins: [userStateMixin],
|
||||
data () {
|
||||
return {
|
||||
backgroundUpdate: new Date(),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
hideSet (set) {
|
||||
return moment(appearanceSets[set.key].availableUntil).isBefore(moment());
|
||||
},
|
||||
mapKeysToFreeOption (key, type, subType) {
|
||||
const userPreference = subType ? this.user.preferences[type][subType] : this.user.preferences[type];
|
||||
const pathKey = subType ? `${type}.${subType}` : `${type}`;
|
||||
|
||||
const option = {};
|
||||
option.key = key;
|
||||
option.pathKey = pathKey;
|
||||
option.active = userPreference === key;
|
||||
option.class = this.createClass(type, subType, key);
|
||||
option.click = (optionParam) => {
|
||||
return option.gemLocked ? this.unlock(`${optionParam.pathKey}.${key}`) : this.set({[`preferences.${optionParam.pathKey}`]: optionParam.key});
|
||||
};
|
||||
return option;
|
||||
},
|
||||
mapKeysToOption (key, type, subType, set) {
|
||||
const option = this.mapKeysToFreeOption(key, type, subType);
|
||||
|
||||
let userPurchased = subType ? this.user.purchased[type][subType] : this.user.purchased[type];
|
||||
let locked = !userPurchased || !userPurchased[key];
|
||||
let hide = false;
|
||||
|
||||
if (set && appearanceSets[set]) {
|
||||
if (locked) hide = moment(appearanceSets[set].availableUntil).isBefore(moment());
|
||||
}
|
||||
|
||||
option.gemLocked = locked;
|
||||
option.hide = hide;
|
||||
if (locked) {
|
||||
option.gem = 2;
|
||||
}
|
||||
|
||||
return option;
|
||||
},
|
||||
createClass (type, subType, key) {
|
||||
let str = `${type} ${subType} `;
|
||||
|
||||
switch (type) {
|
||||
case 'shirt': {
|
||||
str += `${this.user.preferences.size}_shirt_${key}`;
|
||||
break;
|
||||
}
|
||||
case 'size': {
|
||||
str += `${key}_shirt_black`;
|
||||
break;
|
||||
}
|
||||
case 'hair': {
|
||||
if (subType === 'color') {
|
||||
str += `hair_bangs_1_${key}`; // todo get current hair-bang setting
|
||||
} else {
|
||||
str += `hair_${subType}_${key}_${this.user.preferences.hair.color}`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'skin': {
|
||||
str += `skin skin_${key}`;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// `hair_base_${option.key}_${user.preferences.hair.color}`
|
||||
// console.warn('unknown type', type, key);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
userOwnsSet (type, setKeys, subType) {
|
||||
let owns = true;
|
||||
|
||||
setKeys.forEach(key => {
|
||||
if (subType) {
|
||||
if (!this.user.purchased[type] || !this.user.purchased[type][subType] || !this.user.purchased[type][subType][key]) owns = false;
|
||||
return;
|
||||
}
|
||||
if (!this.user.purchased[type][key]) owns = false;
|
||||
});
|
||||
|
||||
return owns;
|
||||
},
|
||||
set (settings) {
|
||||
this.$store.dispatch('user:set', settings);
|
||||
},
|
||||
equip (key, type) {
|
||||
this.$store.dispatch('common:equip', {key, type});
|
||||
},
|
||||
/**
|
||||
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
|
||||
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
|
||||
* Pass in this paramater as "skin.abc". Alternatively, pass as an array ["skin.abc", "skin.xyz"] to unlock sets
|
||||
*/
|
||||
async unlock (path) {
|
||||
let fullSet = path.indexOf(',') !== -1;
|
||||
let isBackground = path.indexOf('background.') !== -1;
|
||||
|
||||
let cost;
|
||||
|
||||
if (isBackground) {
|
||||
cost = fullSet ? 3.75 : 1.75; // (Backgrounds) 15G per set, 7G per individual
|
||||
} else {
|
||||
cost = fullSet ? 1.25 : 0.5; // (Hair, skin, etc) 5G per set, 2G per individual
|
||||
}
|
||||
|
||||
let loginIncentives = [
|
||||
'background.blue',
|
||||
'background.green',
|
||||
'background.red',
|
||||
'background.purple',
|
||||
'background.yellow',
|
||||
'background.violet',
|
||||
];
|
||||
|
||||
if (loginIncentives.indexOf(path) === -1) {
|
||||
if (fullSet) {
|
||||
if (confirm(this.$t('purchaseFor', {cost: cost * 4})) !== true) return;
|
||||
// @TODO: implement gem modal
|
||||
// if (this.user.balance < cost) return $rootScope.openModal('buyGems');
|
||||
} else if (!get(this.user, `purchased.${path}`)) {
|
||||
if (confirm(this.$t('purchaseFor', {cost: cost * 4})) !== true) return;
|
||||
// @TODO: implement gem modal
|
||||
// if (this.user.balance < cost) return $rootScope.openModal('buyGems');
|
||||
}
|
||||
}
|
||||
|
||||
await axios.post(`/api/v4/user/unlock?path=${path}`);
|
||||
try {
|
||||
unlock(this.user, {
|
||||
query: {
|
||||
path,
|
||||
},
|
||||
});
|
||||
this.backgroundUpdate = new Date();
|
||||
} catch (e) {
|
||||
alert(e.message);
|
||||
}
|
||||
},
|
||||
async buy (item) {
|
||||
const options = {
|
||||
currency: 'gold',
|
||||
key: item,
|
||||
type: 'marketGear',
|
||||
quantity: 1,
|
||||
pinType: 'marketGear',
|
||||
};
|
||||
await axios.post(`/api/v4/user/buy/${item}`, options);
|
||||
try {
|
||||
buy(this.user, {
|
||||
params: options,
|
||||
});
|
||||
this.backgroundUpdate = new Date();
|
||||
} catch (e) {
|
||||
alert(e.message);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||