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
This commit is contained in:
Phillip Thelen
2019-10-01 12:55:41 +02:00
2077 changed files with 315402 additions and 19684 deletions

View File

@@ -5,8 +5,12 @@ Habitica [![Build Status](https://travis-ci.org/HabitRPG/habitica.svg?branch=dev
[Habitica](https://habitica.com) 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!

View 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
}
};

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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",

View File

@@ -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', () => {

View File

@@ -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 }
);

View File

@@ -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',

View File

@@ -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);
});
});

View File

@@ -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}`);

View File

@@ -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',

View 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;
}));
});
});

View File

@@ -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',
});
});
});

View File

@@ -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});

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 614 B

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 KiB

After

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 KiB

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

@@ -74,10 +74,10 @@
}
.btn-success {
background: $green-10;
background: $green-100;
&:disabled {
background: $green-10;
background: $green-100;
}
&:hover:not(:disabled), &:active, &.active {

View File

@@ -78,3 +78,5 @@ $wizard-color: #2995CD;
$gems-color: #24CC8F;
$gold-color: #FFA624;
$hourglass-color: #2995CD;
$purple-task: #925cf3;

View File

@@ -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; }
}
}
}

View File

@@ -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';

View 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

View 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

View File

@@ -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',
};
}
},

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View File

@@ -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: {

File diff suppressed because it is too large Load Diff

View File

@@ -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,
});

View File

@@ -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;
},

View File

@@ -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');

View File

@@ -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>

View File

@@ -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',

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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]);
},
},
};

View File

@@ -154,7 +154,6 @@
text-align: center;
overflow-y: hidden;
max-height: 65px; // approximate max height
}
.quick-add-tip-slide-enter-active {

View File

@@ -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

View 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);
}
},
},
};

Some files were not shown because too many files have changed in this diff Show More