Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82f34ed437 | ||
|
|
3b268287b1 | ||
|
|
0e253fbb06 | ||
|
|
043696c225 | ||
|
|
69c2b0378f | ||
|
|
fcfc44fd13 | ||
|
|
76773d27c6 | ||
|
|
b3e81177ec | ||
|
|
020726f6f8 | ||
|
|
9f9b0c73c3 | ||
|
|
2c03c114da | ||
|
|
8e9500fed2 | ||
|
|
377f849f9e | ||
|
|
8bbada540d | ||
|
|
ee867a9d30 | ||
|
|
14a4f42b50 | ||
|
|
2cbb0a85a4 | ||
|
|
975e068fe2 | ||
|
|
5a5f1d6895 | ||
|
|
1db0cda6b1 | ||
|
|
f987585cf1 | ||
|
|
0325ae9636 | ||
|
|
4c4fbfe790 | ||
|
|
6b59262e3e | ||
|
|
5630e8cc8e | ||
|
|
5268bbb8a9 | ||
|
|
34faf2fd50 | ||
|
|
896950dbf0 | ||
|
|
424c50f2a4 | ||
|
|
f235a64d96 | ||
|
|
286abe334e | ||
|
|
81333a3074 | ||
|
|
3c31945524 | ||
|
|
103945f7c5 | ||
|
|
b9d9a17aca | ||
|
|
a0b6f576d2 | ||
|
|
30036963b1 | ||
|
|
e1fe48bee4 | ||
|
|
77b19ffe97 | ||
|
|
e9a5e084fc | ||
|
|
12250a93f1 | ||
|
|
7094e75dd8 | ||
|
|
74c93955f8 | ||
|
|
e4b2ef6599 | ||
|
|
a26c2bce23 | ||
|
|
6cd00897ed | ||
|
|
3c442318d8 | ||
|
|
fd3f7e2b0e | ||
|
|
6f0bd0b913 | ||
|
|
5b7621ceb3 | ||
|
|
b8b414cae5 | ||
|
|
783338f1f0 | ||
|
|
fb6ca0c73b | ||
|
|
5792f54aa0 | ||
|
|
3c943c8f23 | ||
|
|
4b2fd60e47 | ||
|
|
75281ab638 | ||
|
|
d46c9967fb | ||
|
|
4132a39b90 | ||
|
|
36cc229dd2 | ||
|
|
ef0c11c2bd | ||
|
|
3a8312832c | ||
|
|
df17753bb6 | ||
|
|
1a97d69edd | ||
|
|
7baa7427a0 | ||
|
|
270078a030 | ||
|
|
bb2768071d | ||
|
|
ec75de5a90 | ||
|
|
b9b944ba29 | ||
|
|
fa9553b371 | ||
|
|
8d5cbbe9be | ||
|
|
3a339a4a09 | ||
|
|
664cf5a47b | ||
|
|
bcf304984d | ||
|
|
08d84ba691 | ||
|
|
4007c26801 | ||
|
|
344c20fd99 | ||
|
|
f5c2c39f6a | ||
|
|
bda3fb5f4d | ||
|
|
eff8db0afd | ||
|
|
8cce38ede1 | ||
|
|
ab0dae8df3 | ||
|
|
0824af05b7 | ||
|
|
28bf024990 | ||
|
|
8c59420d4e | ||
|
|
8a30ac0607 | ||
|
|
e1984762b5 | ||
|
|
0360326f41 | ||
|
|
f3f215abea | ||
|
|
feb98a5ac7 | ||
|
|
2094a4d4b8 | ||
|
|
90532b0763 | ||
|
|
6fba71ea2c | ||
|
|
5755bfc952 | ||
|
|
08c6e8298c | ||
|
|
5a30b0cf1f | ||
|
|
cf847cd1d8 | ||
|
|
5753d3e648 | ||
|
|
4718e5e5ea | ||
|
|
9a2dbace30 | ||
|
|
ef07abfd28 | ||
|
|
b28adc6b42 | ||
|
|
c814eabb29 | ||
|
|
4dc19a8c60 | ||
|
|
89f6a9b07e | ||
|
|
a23926f34f | ||
|
|
118198b594 | ||
|
|
97e80e2093 | ||
|
|
2588befceb | ||
|
|
f09274225a | ||
|
|
03b66abe70 | ||
|
|
9d41fb0252 | ||
|
|
012fa2f8ef | ||
|
|
00d8d9d0cc | ||
|
|
cc4772c75a | ||
|
|
fabaaa6d92 | ||
|
|
854696728a | ||
|
|
314926cc06 | ||
|
|
68fa834946 | ||
|
|
09440d5adf | ||
|
|
1724bfc553 | ||
|
|
8304f99ecb | ||
|
|
d2fcdf4493 | ||
|
|
649404ac6a | ||
|
|
774db2564f | ||
|
|
521a1e646d | ||
|
|
2619ac37d9 | ||
|
|
2ce9b319a0 | ||
|
|
477c23dd67 | ||
|
|
7af71d1457 | ||
|
|
3171550de2 | ||
|
|
6477801d3e | ||
|
|
14798ced82 | ||
|
|
34d37cefcc | ||
|
|
bd21933cea |
@@ -1,18 +1,5 @@
|
||||
FROM node:10
|
||||
|
||||
# Install global packages
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
# Clone Habitica repo and install dependencies
|
||||
RUN mkdir -p /usr/src/habitrpg
|
||||
WORKDIR /usr/src/habitrpg
|
||||
RUN git clone https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
|
||||
RUN cp config.json.example config.json
|
||||
RUN npm install
|
||||
|
||||
# Create Build dir
|
||||
RUN mkdir -p ./website/build
|
||||
|
||||
# Start Habitica
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "start"]
|
||||
FROM node:10
|
||||
WORKDIR /code
|
||||
COPY package*.json /code/
|
||||
RUN npm install
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
@@ -61,8 +61,8 @@
|
||||
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
||||
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
||||
"SITE_HTTP_AUTH_ENABLED": "false",
|
||||
"SITE_HTTP_AUTH_PASSWORD": "password",
|
||||
"SITE_HTTP_AUTH_USERNAME": "admin",
|
||||
"SITE_HTTP_AUTH_PASSWORDS": "password,wordpass,passkey",
|
||||
"SITE_HTTP_AUTH_USERNAMES": "admin,tester,contributor",
|
||||
"SLACK_FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||
"SLACK_FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"SLACK_SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
|
||||
@@ -1,14 +1,45 @@
|
||||
version: "3"
|
||||
services:
|
||||
|
||||
client:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile-Dev
|
||||
command: ["npm", "run", "client:dev"]
|
||||
depends_on:
|
||||
- server
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- BASE_URL=http://server:3000
|
||||
image: habitica
|
||||
networks:
|
||||
- habitica
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- '.:/usr/src/habitrpg'
|
||||
|
||||
- .:/code
|
||||
- /code/node_modules
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile-Dev
|
||||
command: ["npm", "start"]
|
||||
depends_on:
|
||||
- mongo
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- NODE_DB_URI=mongodb://mongo/habitrpg
|
||||
image: habitica
|
||||
networks:
|
||||
- habitica
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- '.:/usr/src/habitrpg'
|
||||
- .:/code
|
||||
- /code/node_modules
|
||||
mongo:
|
||||
image: mongo:3.4
|
||||
networks:
|
||||
- habitica
|
||||
ports:
|
||||
- "27017:27017"
|
||||
networks:
|
||||
habitica:
|
||||
driver: bridge
|
||||
|
||||
@@ -16,7 +16,7 @@ const IMG_DIST_PATH = 'website/client/assets/images/sprites/';
|
||||
const CSS_DIST_PATH = 'website/client/assets/css/sprites/';
|
||||
|
||||
function checkForSpecialTreatment (name) {
|
||||
let regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame/;
|
||||
let regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame|^eyewear_special_\w+HalfMoon/;
|
||||
return name.match(regex) || name === 'head_0';
|
||||
}
|
||||
|
||||
|
||||
62
migrations/archive/2019/20190530_halfmoon_glasses.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190530_halfmoon_glasses';
|
||||
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 = {
|
||||
'items.gear.owned.eyewear_special_blackHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_blueHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_greenHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_pinkHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_redHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_whiteHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_yellowHalfMoon': true,
|
||||
};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-05-01')},
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
};
|
||||
59
migrations/archive/2019/20190618_summer_splash_orcas.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190618_summer_splash_orcas';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set;
|
||||
|
||||
if (user && user.items && user.items.pets && typeof user.items.pets['Orca-Base'] !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME };
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Orca-Base'] !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME, 'items.pets.Orca-Base': 5 };
|
||||
} else {
|
||||
set = { migration: MIGRATION_NAME, 'items.mounts.Orca-Base': true };
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-05-18')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = 'mystery_items_201905';
|
||||
const MYSTERY_ITEMS = ['headAccessory_mystery_201905', 'back_mystery_201905'];
|
||||
const MIGRATION_NAME = 'mystery_items_201906';
|
||||
const MYSTERY_ITEMS = ['headAccessory_mystery_201906', 'armor_mystery_201906'];
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
import { model as UserNotification } from '../../website/server/models/userNotification';
|
||||
|
||||
|
||||
771
package-lock.json
generated
16
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "4.97.0",
|
||||
"version": "4.103.0",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@google-cloud/trace-agent": "^3.6.0",
|
||||
@@ -14,7 +14,7 @@
|
||||
"apn": "^2.2.0",
|
||||
"autoprefixer": "^9.4.0",
|
||||
"aws-sdk": "^2.432.0",
|
||||
"axios": "^0.18.0",
|
||||
"axios": "^0.19.0",
|
||||
"axios-progress-bar": "^1.2.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.2.3",
|
||||
@@ -48,7 +48,7 @@
|
||||
"got": "^9.0.0",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-babel": "^7.0.1",
|
||||
"gulp-imagemin": "^5.0.3",
|
||||
"gulp-imagemin": "^6.0.0",
|
||||
"gulp-nodemon": "^2.4.1",
|
||||
"gulp.spritesmith": "^6.9.0",
|
||||
"habitica-markdown": "^1.3.0",
|
||||
@@ -58,9 +58,9 @@
|
||||
"in-app-purchase": "^1.11.3",
|
||||
"intro.js": "^2.9.3",
|
||||
"jquery": ">=3.0.0",
|
||||
"js2xmlparser": "^3.0.0",
|
||||
"js2xmlparser": "^4.0.0",
|
||||
"lodash": "^4.17.10",
|
||||
"merge-stream": "^1.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"method-override": "^3.0.0",
|
||||
"moment": "^2.22.1",
|
||||
"moment-recur": "^1.0.7",
|
||||
@@ -71,7 +71,7 @@
|
||||
"node-sass": "^4.9.0",
|
||||
"nodemailer": "^6.0.0",
|
||||
"ora": "^3.2.0",
|
||||
"pageres": "^4.1.1",
|
||||
"pageres": "^5.1.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-facebook": "^2.0.0",
|
||||
"passport-google-oauth20": "1.0.0",
|
||||
@@ -98,7 +98,7 @@
|
||||
"url-loader": "^1.0.0",
|
||||
"useragent": "^2.1.9",
|
||||
"uuid": "^3.0.1",
|
||||
"validator": "^10.5.0",
|
||||
"validator": "^11.0.0",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vue": "^2.6.10",
|
||||
"vue-loader": "^14.2.2",
|
||||
@@ -152,7 +152,7 @@
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chalk": "^2.4.1",
|
||||
"chromedriver": "^2.40.0",
|
||||
"chromedriver": "^73.0.0",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"coveralls": "^3.0.3",
|
||||
"cross-spawn": "^6.0.5",
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('auth middleware', () => {
|
||||
describe('auth with headers', () => {
|
||||
it('allows to specify a list of user field that we do not want to load', (done) => {
|
||||
const authWithHeaders = authWithHeadersFactory({
|
||||
userFieldsToExclude: ['items', 'flags', 'auth.timestamps'],
|
||||
userFieldsToExclude: ['items'],
|
||||
});
|
||||
|
||||
req.headers['x-api-user'] = user._id;
|
||||
@@ -27,11 +27,34 @@ describe('auth middleware', () => {
|
||||
|
||||
const userToJSON = res.locals.user.toJSON();
|
||||
expect(userToJSON.items).to.not.exist;
|
||||
expect(userToJSON.flags).to.not.exist;
|
||||
expect(userToJSON.auth.timestamps).to.not.exist;
|
||||
expect(userToJSON.auth).to.exist;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('makes sure some fields are always included', (done) => {
|
||||
const authWithHeaders = authWithHeadersFactory({
|
||||
userFieldsToExclude: [
|
||||
'items', 'auth.timestamps',
|
||||
'preferences', 'notifications', '_id', 'flags', 'auth', // these are always loaded
|
||||
],
|
||||
});
|
||||
|
||||
req.headers['x-api-user'] = user._id;
|
||||
req.headers['x-api-key'] = user.apiToken;
|
||||
|
||||
authWithHeaders(req, res, (err) => {
|
||||
if (err) return done(err);
|
||||
|
||||
const userToJSON = res.locals.user.toJSON();
|
||||
expect(userToJSON.items).to.not.exist;
|
||||
expect(userToJSON.auth.timestamps).to.exist;
|
||||
expect(userToJSON.auth).to.exist;
|
||||
expect(userToJSON.notifications).to.exist;
|
||||
expect(userToJSON.preferences).to.exist;
|
||||
expect(userToJSON._id).to.exist;
|
||||
expect(userToJSON.flags).to.exist;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import moment from 'moment';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
import validator from 'validator';
|
||||
import { sleep } from '../../../helpers/api-unit.helper';
|
||||
import { sleep, translationCheck } from '../../../helpers/api-unit.helper';
|
||||
import {
|
||||
SPAM_MESSAGE_LIMIT,
|
||||
SPAM_MIN_EXEMPT_CONTRIB_LEVEL,
|
||||
@@ -271,7 +271,16 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`Participating Member attacks Wailing Whale for 5.0 damage.` `Wailing Whale attacks party for 7.5 damage.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member attacks Wailing Whale for 5.0 damage. Wailing Whale attacks party for 7.5 damage.`',
|
||||
info: {
|
||||
bossDamage: '7.5',
|
||||
quest: 'whale',
|
||||
type: 'boss_damage',
|
||||
user: 'Participating Member',
|
||||
userDamage: '5.0',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('applies damage only to participating members of party', async () => {
|
||||
@@ -344,7 +353,10 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledTwice;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`You defeated Wailing Whale! Questing party members receive the rewards of victory.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`You defeated Wailing Whale! Questing party members receive the rewards of victory.`',
|
||||
info: { quest: 'whale', type: 'boss_defeated' },
|
||||
});
|
||||
});
|
||||
|
||||
it('calls finishQuest when boss has <= 0 hp', async () => {
|
||||
@@ -387,7 +399,10 @@ describe('Group Model', () => {
|
||||
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledWith(quest.boss.rage.effect('en'));
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: quest.boss.rage.effect('en'),
|
||||
info: { quest: 'trex_undead', type: 'boss_rage' },
|
||||
});
|
||||
expect(party.quest.progress.hp).to.eql(383.5);
|
||||
expect(party.quest.progress.rage).to.eql(0);
|
||||
});
|
||||
@@ -437,7 +452,10 @@ describe('Group Model', () => {
|
||||
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledWith(quest.boss.rage.effect('en'));
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: quest.boss.rage.effect('en'),
|
||||
info: { quest: 'lostMasterclasser4', type: 'boss_rage' },
|
||||
});
|
||||
expect(party.quest.progress.rage).to.eql(0);
|
||||
|
||||
let drainedUser = await User.findById(participatingMember._id);
|
||||
@@ -488,7 +506,15 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`Participating Member found 5 Bars of Soap.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member found 5 Bars of Soap.`',
|
||||
info: {
|
||||
items: { soapBars: 5 },
|
||||
quest: 'atom1',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sends a chat message if no progress is made', async () => {
|
||||
@@ -499,7 +525,15 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`Participating Member found 0 Bars of Soap.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member found 0 Bars of Soap.`',
|
||||
info: {
|
||||
items: { soapBars: 0 },
|
||||
quest: 'atom1',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sends a chat message if no progress is made on quest with multiple items', async () => {
|
||||
@@ -516,9 +550,15 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/`Participating Member found/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/0 Blue Fins/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/0 Fire Coral/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member found 0 Fire Coral, 0 Blue Fins.`',
|
||||
info: {
|
||||
items: { blueFins: 0, fireCoral: 0 },
|
||||
quest: 'dilatoryDistress1',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('handles collection quests with multiple items', async () => {
|
||||
@@ -535,8 +575,14 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/`Participating Member found/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/\d* (Tracks|Broken Twigs)/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch({
|
||||
message: sinon.match(/`Participating Member found/).and(sinon.match(/\d* (Tracks|Broken Twigs)/)),
|
||||
info: {
|
||||
quest: 'evilsanta2',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sends message about victory', async () => {
|
||||
@@ -547,7 +593,10 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledTwice;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`All items found! Party has received their rewards.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`All items found! Party has received their rewards.`',
|
||||
info: { type: 'all_items_found' },
|
||||
});
|
||||
});
|
||||
|
||||
it('calls finishQuest when all items are found', async () => {
|
||||
@@ -718,6 +767,258 @@ describe('Group Model', () => {
|
||||
expect(res.t).to.not.be.called;
|
||||
});
|
||||
});
|
||||
|
||||
describe('translateSystemMessages', () => {
|
||||
it('translate quest_start', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_damage', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_damage',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
userDamage: 15.3,
|
||||
bossDamage: 3.7,
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_dont_attack', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_dont_attack',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
userDamage: 15.3,
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_rage', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_rage',
|
||||
quest: 'lostMasterclasser3',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_defeated', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_defeated',
|
||||
quest: 'lostMasterclasser3',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate user_found_items', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'user_found_items',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'lostMasterclasser1',
|
||||
items: {
|
||||
ancientTome: 3,
|
||||
forbiddenTome: 2,
|
||||
hiddenTome: 1,
|
||||
},
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate all_items_found', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'all_items_found',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate spell_cast_party', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'spell_cast_party',
|
||||
user: questLeader.profile.name,
|
||||
class: 'wizard',
|
||||
spell: 'earth',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate spell_cast_user', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'spell_cast_user',
|
||||
user: questLeader.profile.name,
|
||||
class: 'special',
|
||||
spell: 'snowball',
|
||||
target: participatingMember.profile.name,
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate quest_cancel', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'quest_cancel',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate quest_abort', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'quest_abort',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_quest_completed', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_quest_completed',
|
||||
quest: 'stressbeast',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_boss_rage_tired', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_boss_rage_tired',
|
||||
quest: 'stressbeast',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_boss_rage', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_boss_rage',
|
||||
quest: 'dysheartener',
|
||||
scene: 'market',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_boss_desperation', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_boss_desperation',
|
||||
quest: 'stressbeast',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate claim_task', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'claim_task',
|
||||
user: questLeader.profile.name,
|
||||
task: 'Feed the pet',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toJSONCleanChat', () => {
|
||||
it('shows messages with 1 flag to non-admins', async () => {
|
||||
party.chat = [{
|
||||
flagCount: 1,
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
expect(toJSON.chat.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('shows messages with >= 2 flag to admins', async () => {
|
||||
party.chat = [{
|
||||
flagCount: 3,
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
const admin = new User({'contributor.admin': true});
|
||||
let toJSON = await Group.toJSONCleanChat(party, admin);
|
||||
expect(toJSON.chat.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('doesn\'t show flagged messages to non-admins', async () => {
|
||||
party.chat = [{
|
||||
flagCount: 3,
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
expect(toJSON.chat.length).to.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Instance Methods', () => {
|
||||
@@ -1007,20 +1308,22 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('formats message', () => {
|
||||
const chatMessage = party.sendChat('a new message', {
|
||||
_id: 'user-id',
|
||||
profile: { name: 'user name' },
|
||||
contributor: {
|
||||
toObject () {
|
||||
return 'contributor object';
|
||||
const chatMessage = party.sendChat({
|
||||
message: 'a new message', user: {
|
||||
_id: 'user-id',
|
||||
profile: { name: 'user name' },
|
||||
contributor: {
|
||||
toObject () {
|
||||
return 'contributor object';
|
||||
},
|
||||
},
|
||||
},
|
||||
backer: {
|
||||
toObject () {
|
||||
return 'backer object';
|
||||
backer: {
|
||||
toObject () {
|
||||
return 'backer object';
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
);
|
||||
|
||||
const chat = chatMessage;
|
||||
|
||||
@@ -1037,7 +1340,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('formats message as system if no user is passed in', () => {
|
||||
const chat = party.sendChat('a system message');
|
||||
const chat = party.sendChat({message: 'a system message'});
|
||||
|
||||
expect(chat.text).to.eql('a system message');
|
||||
expect(validator.isUUID(chat.id)).to.eql(true);
|
||||
@@ -1052,7 +1355,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('updates users about new messages in party', () => {
|
||||
party.sendChat('message');
|
||||
party.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
@@ -1066,7 +1369,7 @@ describe('Group Model', () => {
|
||||
type: 'guild',
|
||||
});
|
||||
|
||||
group.sendChat('message');
|
||||
group.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
@@ -1076,7 +1379,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('does not send update to user that sent the message', () => {
|
||||
party.sendChat('message', {_id: 'user-id', profile: { name: 'user' }});
|
||||
party.sendChat({message: 'message', user: {_id: 'user-id', profile: { name: 'user' }}});
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
@@ -1088,7 +1391,7 @@ describe('Group Model', () => {
|
||||
it('skips sending new message notification for guilds with > 5000 members', () => {
|
||||
party.memberCount = 5001;
|
||||
|
||||
party.sendChat('message');
|
||||
party.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.not.be.called;
|
||||
});
|
||||
@@ -1096,7 +1399,7 @@ describe('Group Model', () => {
|
||||
it('skips sending messages to the tavern', () => {
|
||||
party._id = TAVERN_ID;
|
||||
|
||||
party.sendChat('message');
|
||||
party.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.not.be.called;
|
||||
});
|
||||
@@ -1431,7 +1734,7 @@ describe('Group Model', () => {
|
||||
let quest;
|
||||
|
||||
beforeEach(() => {
|
||||
quest = questScrolls.whale;
|
||||
quest = questScrolls.armadillo;
|
||||
party.quest.key = quest.key;
|
||||
party.quest.active = false;
|
||||
party.quest.leader = questLeader._id;
|
||||
@@ -1579,6 +1882,36 @@ describe('Group Model', () => {
|
||||
expect(updatedSleepingParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
|
||||
});
|
||||
|
||||
it('gives out other pet-related quest achievements', async () => {
|
||||
quest = questScrolls.rock;
|
||||
party.quest.key = quest.key;
|
||||
|
||||
questLeader.achievements.quests = {
|
||||
mayhemMistiflying1: 1,
|
||||
yarn: 1,
|
||||
mayhemMistiflying2: 1,
|
||||
egg: 1,
|
||||
mayhemMistiflying3: 1,
|
||||
slime: 2,
|
||||
};
|
||||
await questLeader.save();
|
||||
await party.finishQuest(quest);
|
||||
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id).exec(),
|
||||
User.findById(participatingMember._id).exec(),
|
||||
User.findById(sleepingParticipatingMember._id).exec(),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.achievements.mindOverMatter).to.eql(true);
|
||||
expect(updatedParticipatingMember.achievements.mindOverMatter).to.not.eql(true);
|
||||
expect(updatedSleepingParticipatingMember.achievements.mindOverMatter).to.not.eql(true);
|
||||
});
|
||||
|
||||
it('gives xp and gold', async () => {
|
||||
await party.finishQuest(quest);
|
||||
|
||||
@@ -1715,13 +2048,13 @@ describe('Group Model', () => {
|
||||
questLeader = await User.findById(questLeader._id);
|
||||
participatingMember = await User.findById(participatingMember._id);
|
||||
|
||||
expect(questLeader.party.quest.completed).to.eql('whale');
|
||||
expect(questLeader.party.quest.completed).to.eql('armadillo');
|
||||
expect(questLeader.party.quest.progress.up).to.eql(10);
|
||||
expect(questLeader.party.quest.progress.down).to.eql(8);
|
||||
expect(questLeader.party.quest.progress.collectedItems).to.eql(5);
|
||||
expect(questLeader.party.quest.RSVPNeeded).to.eql(false);
|
||||
|
||||
expect(participatingMember.party.quest.completed).to.eql('whale');
|
||||
expect(participatingMember.party.quest.completed).to.eql('armadillo');
|
||||
expect(participatingMember.party.quest.progress.up).to.eql(10);
|
||||
expect(participatingMember.party.quest.progress.down).to.eql(8);
|
||||
expect(participatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||
@@ -1928,7 +2261,7 @@ describe('Group Model', () => {
|
||||
|
||||
await guild.save();
|
||||
|
||||
const groupMessage = guild.sendChat('Test message.');
|
||||
const groupMessage = guild.sendChat({message: 'Test message.'});
|
||||
await groupMessage.save();
|
||||
|
||||
await sleep();
|
||||
|
||||
@@ -171,7 +171,7 @@ describe('GET challenges/user', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return not return challenges in user groups if we send member true param', async () => {
|
||||
it('should not return challenges in user groups if we send member true param', async () => {
|
||||
let challenges = await member.get(`/challenges/user?member=${true}`);
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
@@ -214,6 +214,28 @@ describe('GET challenges/user', () => {
|
||||
let foundChallenge = _.find(challenges, { _id: privateChallenge._id });
|
||||
expect(foundChallenge).to.not.exist;
|
||||
});
|
||||
|
||||
it('should not return challenges user doesn\'t have access to, even with query parameters', async () => {
|
||||
let { group, groupLeader } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'TestPrivateGuild',
|
||||
summary: 'summary for TestPrivateGuild',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
},
|
||||
});
|
||||
|
||||
let privateChallenge = await generateChallenge(groupLeader, group, {categories: [{
|
||||
name: 'academics',
|
||||
slug: 'academics',
|
||||
}]});
|
||||
await groupLeader.post(`/challenges/${privateChallenge._id}/join`);
|
||||
|
||||
let challenges = await nonMember.get('/challenges/user?categories=academics&owned=not_owned');
|
||||
|
||||
let foundChallenge = _.find(challenges, { _id: privateChallenge._id });
|
||||
expect(foundChallenge).to.not.exist;
|
||||
});
|
||||
});
|
||||
|
||||
context('official challenge is present', () => {
|
||||
|
||||
@@ -149,7 +149,7 @@ describe('POST /group', () => {
|
||||
).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('cannotCreatePublicGuildWhenMuted'),
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('cannotInviteWhenMuted'),
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -262,7 +262,7 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('cannotInviteWhenMuted'),
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -436,7 +436,7 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('cannotInviteWhenMuted'),
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -526,7 +526,7 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('cannotInviteWhenMuted'),
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -127,7 +127,13 @@ describe('POST /groups/:groupId/quests/abort', () => {
|
||||
members: {},
|
||||
});
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/aborted the party quest Wail of the Whale.`/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch({
|
||||
message: sinon.match(/aborted the party quest Wail of the Whale.`/),
|
||||
info: {
|
||||
quest: 'whale',
|
||||
type: 'quest_abort',
|
||||
},
|
||||
});
|
||||
|
||||
stub.restore();
|
||||
});
|
||||
|
||||
@@ -141,7 +141,14 @@ describe('POST /groups/:groupId/quests/cancel', () => {
|
||||
members: {},
|
||||
});
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/cancelled the party quest Wail of the Whale.`/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch({
|
||||
message: sinon.match(/cancelled the party quest Wail of the Whale.`/),
|
||||
info: {
|
||||
quest: 'whale',
|
||||
type: 'quest_cancel',
|
||||
user: sinon.match.any,
|
||||
},
|
||||
});
|
||||
|
||||
stub.restore();
|
||||
});
|
||||
|
||||
@@ -83,12 +83,12 @@ context('avatar.vue', () => {
|
||||
expect(vm.paddingTop).to.equal('28px');
|
||||
});
|
||||
|
||||
it('is 24.5px if user has a pet', () => {
|
||||
it('is 24px if user has a pet', () => {
|
||||
vm.member.items = {
|
||||
currentPet: { name: 'Foo' },
|
||||
};
|
||||
|
||||
expect(vm.paddingTop).to.equal('24.5px');
|
||||
expect(vm.paddingTop).to.equal('24px');
|
||||
});
|
||||
|
||||
it('is 0px if user has a mount', () => {
|
||||
@@ -297,4 +297,4 @@ context('avatar.vue', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,6 +80,13 @@ describe('shared.ops.buy', () => {
|
||||
headAccessory_special_redHeadband: true,
|
||||
headAccessory_special_whiteHeadband: true,
|
||||
headAccessory_special_yellowHeadband: true,
|
||||
eyewear_special_blackHalfMoon: true,
|
||||
eyewear_special_blueHalfMoon: true,
|
||||
eyewear_special_greenHalfMoon: true,
|
||||
eyewear_special_pinkHalfMoon: true,
|
||||
eyewear_special_redHalfMoon: true,
|
||||
eyewear_special_whiteHalfMoon: true,
|
||||
eyewear_special_yellowHalfMoon: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -75,6 +75,13 @@ describe('shared.ops.buyMarketGear', () => {
|
||||
headAccessory_special_redHeadband: true,
|
||||
headAccessory_special_whiteHeadband: true,
|
||||
headAccessory_special_yellowHeadband: true,
|
||||
eyewear_special_blackHalfMoon: true,
|
||||
eyewear_special_blueHalfMoon: true,
|
||||
eyewear_special_greenHalfMoon: true,
|
||||
eyewear_special_pinkHalfMoon: true,
|
||||
eyewear_special_redHalfMoon: true,
|
||||
eyewear_special_whiteHalfMoon: true,
|
||||
eyewear_special_yellowHalfMoon: true,
|
||||
});
|
||||
expect(analytics.track).to.be.calledOnce;
|
||||
});
|
||||
|
||||
@@ -169,6 +169,24 @@ describe('shared.ops.feed', () => {
|
||||
expect(user.items.pets['Wolf-Base']).to.equal(7);
|
||||
});
|
||||
|
||||
it('awards All Your Base achievement', () => {
|
||||
user.items.pets['Wolf-Spooky'] = 5;
|
||||
user.items.food.Milk = 2;
|
||||
user.items.mounts = {
|
||||
'Wolf-Base': true,
|
||||
'TigerCub-Base': true,
|
||||
'PandaCub-Base': true,
|
||||
'LionCub-Base': true,
|
||||
'Fox-Base': true,
|
||||
'FlyingPig-Base': true,
|
||||
'Dragon-Base': true,
|
||||
'Cactus-Base': true,
|
||||
'BearCub-Base': true,
|
||||
};
|
||||
feed(user, {params: {pet: 'Wolf-Spooky', food: 'Milk'}});
|
||||
expect(user.achievements.allYourBase).to.eql(true);
|
||||
});
|
||||
|
||||
it('evolves the pet into a mount when feeding user.items.pets[pet] >= 50', () => {
|
||||
user.items.pets['Wolf-Base'] = 49;
|
||||
user.items.food.Milk = 2;
|
||||
|
||||
@@ -159,6 +159,24 @@ describe('shared.ops.hatch', () => {
|
||||
expect(user.items.eggs).to.eql({Wolf: 0});
|
||||
expect(user.items.hatchingPotions).to.eql({Base: 0});
|
||||
});
|
||||
|
||||
it('awards Back to Basics achievement', () => {
|
||||
user.items.pets = {
|
||||
'Wolf-Base': 5,
|
||||
'TigerCub-Base': 5,
|
||||
'PandaCub-Base': 10,
|
||||
'LionCub-Base': 5,
|
||||
'Fox-Base': 5,
|
||||
'FlyingPig-Base': 5,
|
||||
'Dragon-Base': 5,
|
||||
'Cactus-Base': 15,
|
||||
'BearCub-Base': 5,
|
||||
};
|
||||
user.items.eggs = {Wolf: 1};
|
||||
user.items.hatchingPotions = {Spooky: 1};
|
||||
hatch(user, {params: {egg: 'Wolf', hatchingPotion: 'Spooky'}});
|
||||
expect(user.achievements.backToBasics).to.eql(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -49,6 +49,7 @@ describe('shared.ops.rebirth', () => {
|
||||
let [, message] = rebirth(user);
|
||||
|
||||
expect(message).to.equal(i18n.t('rebirthComplete'));
|
||||
expect(user.flags.lastFreeRebirth).to.exist;
|
||||
});
|
||||
|
||||
it('rebirths a user with not enough gems but more than max level', () => {
|
||||
@@ -60,6 +61,16 @@ describe('shared.ops.rebirth', () => {
|
||||
expect(message).to.equal(i18n.t('rebirthComplete'));
|
||||
});
|
||||
|
||||
it('rebirths a user using gems if over max level but rebirthed recently', () => {
|
||||
user.stats.lvl = MAX_LEVEL + 1;
|
||||
user.flags.lastFreeRebirth = new Date();
|
||||
|
||||
let [, message] = rebirth(user);
|
||||
|
||||
expect(message).to.equal(i18n.t('rebirthComplete'));
|
||||
expect(user.balance).to.equal(0);
|
||||
});
|
||||
|
||||
it('resets user\'s tasks values except for rewards to 0', () => {
|
||||
tasks[0].value = 1;
|
||||
tasks[1].value = 1;
|
||||
|
||||
@@ -8,6 +8,7 @@ import mongo from './mongo'; // eslint-disable-line
|
||||
import moment from 'moment';
|
||||
import i18n from '../../website/common/script/i18n';
|
||||
import * as Tasks from '../../website/server/models/task';
|
||||
export { translationCheck } from './translate';
|
||||
|
||||
afterEach((done) => {
|
||||
sandbox.restore();
|
||||
|
||||
@@ -16,3 +16,9 @@ export function translate (key, variables, language) {
|
||||
|
||||
return translatedString;
|
||||
}
|
||||
|
||||
export function translationCheck (translatedString) {
|
||||
expect(translatedString).to.not.be.empty;
|
||||
expect(translatedString).to.not.eql(STRING_ERROR_MSG);
|
||||
expect(translatedString).to.not.match(STRING_DOES_NOT_EXIST_MSG);
|
||||
}
|
||||
|
||||
@@ -656,5 +656,6 @@ export default {
|
||||
<style src="assets/css/sprites/spritesmith-main-22.css"></style>
|
||||
<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.css"></style>
|
||||
<style src="smartbanner.js/dist/smartbanner.min.css"></style>
|
||||
|
||||
@@ -1,66 +1,84 @@
|
||||
.promo_armoire_backgrounds_201905 {
|
||||
.promo_armoire_backgrounds_201906 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -786px;
|
||||
background-position: 0px -869px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_bronze_quest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -499px 0px;
|
||||
background-position: 0px -359px;
|
||||
width: 360px;
|
||||
height: 360px;
|
||||
}
|
||||
.promo_feathered_friends_bundle {
|
||||
.promo_dolphin_quest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -638px;
|
||||
background-position: 0px 0px;
|
||||
width: 553px;
|
||||
height: 358px;
|
||||
}
|
||||
.promo_glass_watery_potions {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -424px -869px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_floral_sunshine_potions {
|
||||
.promo_halfmoon_glasses {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -424px -638px;
|
||||
width: 423px;
|
||||
background-position: -1086px -148px;
|
||||
width: 279px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_mystery_201905 {
|
||||
.promo_mystery_201906 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -860px -223px;
|
||||
background-position: -1086px 0px;
|
||||
width: 282px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_oddballs_bundle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -426px -720px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_orcas {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1086px -296px;
|
||||
width: 219px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_seafoam {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -720px;
|
||||
width: 425px;
|
||||
height: 148px;
|
||||
}
|
||||
.promo_seasonal_shop {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1086px -444px;
|
||||
width: 162px;
|
||||
height: 132px;
|
||||
}
|
||||
.promo_summer_splash_2019 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -554px -244px;
|
||||
width: 408px;
|
||||
height: 186px;
|
||||
}
|
||||
.promo_take_this {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1068px -371px;
|
||||
background-position: -1249px -444px;
|
||||
width: 96px;
|
||||
height: 69px;
|
||||
}
|
||||
.scene_gold {
|
||||
.scene_casting_spells {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px 0px;
|
||||
width: 498px;
|
||||
height: 360px;
|
||||
}
|
||||
.scene_languages {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -328px -361px;
|
||||
width: 297px;
|
||||
height: 261px;
|
||||
}
|
||||
.scene_rewards {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -860px -371px;
|
||||
width: 207px;
|
||||
height: 180px;
|
||||
}
|
||||
.scene_spells {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -860px 0px;
|
||||
background-position: -554px -431px;
|
||||
width: 312px;
|
||||
height: 222px;
|
||||
}
|
||||
.scene_yesterdailies_repeatables {
|
||||
.scene_positivity {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -361px;
|
||||
width: 327px;
|
||||
height: 276px;
|
||||
background-position: -554px 0px;
|
||||
width: 531px;
|
||||
height: 243px;
|
||||
}
|
||||
|
||||
984
website/client/assets/css/sprites/spritesmith-main-25.css
Normal file
@@ -0,0 +1,984 @@
|
||||
.Pet-TRex-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TRex-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-RoseQuartz {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-RoyalPurple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Shimmer {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Spooky {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-StarryNight {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Sunshine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Thunderstorm {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Veggie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Watery {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-TigerCub-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Treeling-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Triceratops-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turkey-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turkey-Gilded {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Turtle-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Unicorn-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Velociraptor-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Aquatic {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Bronze {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Celestial {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Cupid {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ember {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Fairy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Floral {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Frost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ghost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Glass {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Glow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Holly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-IcySnow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Peppermint {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Rainbow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-RoseQuartz {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-RoyalPurple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shimmer {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Spooky {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-StarryNight {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Sunshine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Thunderstorm {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -600px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veggie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -700px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veteran {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -800px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Watery {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -82px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -164px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -246px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -328px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -410px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -492px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -574px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -656px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -738px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -820px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -902px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -984px -900px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet_HatchingPotion_Aquatic {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -69px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Base {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -207px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Bronze {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -138px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Celestial {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -207px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyBlue {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -276px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyPink {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -345px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Cupid {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -414px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Desert {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -483px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ember {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -552px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Fairy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -621px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Floral {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -690px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Frost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -759px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ghost {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -828px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Glass {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px -897px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Glow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: 0px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Golden {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -69px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Holly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -138px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_IcySnow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1066px 0px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Peppermint {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -276px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Purple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -345px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Rainbow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -414px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -483px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_RoseQuartz {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -552px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_RoyalPurple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -621px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shade {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -690px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shimmer {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -759px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Skeleton {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -828px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Spooky {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -897px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_StarryNight {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -966px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Sunshine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1035px -1000px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Thunderstorm {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1135px 0px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Watery {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1135px -69px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_White {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1135px -138px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Zombie {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-25.png');
|
||||
background-position: -1135px -207px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 561 KiB After Width: | Height: | Size: 492 KiB |
|
Before Width: | Height: | Size: 580 KiB After Width: | Height: | Size: 587 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 187 KiB |
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 422 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 187 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 164 KiB |
BIN
website/client/assets/images/sprites/spritesmith-main-25.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 115 KiB |
@@ -35,6 +35,7 @@ $maroon-50: #C92B2B;
|
||||
$maroon-100: #DE3F3F;
|
||||
$maroon-500: #F19595;
|
||||
|
||||
$yellow-5: #EE9109;
|
||||
$yellow-10: #FFA623;
|
||||
$yellow-50: #FFB445;
|
||||
$yellow-100: #FFBE5D;
|
||||
@@ -60,9 +61,6 @@ $green-50: #3FDAA2;
|
||||
$green-100: #5AEAB2;
|
||||
$green-500: #A6FFDF;
|
||||
|
||||
$orange-10: #ee9109;
|
||||
$orange-50: #bf7d1a;
|
||||
|
||||
$suggested-item-color: #D5C8FF;
|
||||
|
||||
$healer-color: #cf8229;
|
||||
|
||||
@@ -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: 'summer';
|
||||
$npc_quests_flavor: 'summer';
|
||||
$npc_seasonal_flavor: 'summer';
|
||||
$npc_timetravelers_flavor: 'summer';
|
||||
$npc_tavern_flavor: 'summer';
|
||||
|
||||
3
website/client/assets/svg/chevron-down.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9">
|
||||
<path fill="none" fill-rule="evenodd" stroke="#BDA8FF" stroke-width="2.5" d="M13 1L7 7 1 1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 187 B |
6
website/client/assets/svg/clock-white.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#FFF" d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0m0 2c3.308 0 6 2.692 6 6s-2.692 6-6 6-6-2.692-6-6 2.692-6 6-6"/>
|
||||
<path stroke="#FFF" stroke-linecap="round" stroke-width="2" d="M8 5v3.031L10 10"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 358 B |
@@ -1,3 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#E1E0E3" fill-rule="evenodd" d="M8 0c2.173 0 2.445.01 3.298.048.852.04 1.433.174 1.942.372.526.205.973.478 1.418.922.444.445.717.892.922 1.418.198.509.333 1.09.372 1.942C15.99 5.555 16 5.827 16 8s-.01 2.445-.048 3.298c-.04.852-.174 1.433-.372 1.942a3.924 3.924 0 0 1-.922 1.418 3.924 3.924 0 0 1-1.418.922c-.509.198-1.09.333-1.942.372-.853.04-1.125.048-3.298.048s-2.445-.009-3.298-.048c-.852-.04-1.433-.174-1.942-.372a3.924 3.924 0 0 1-1.418-.922A3.924 3.924 0 0 1 .42 13.24c-.198-.509-.333-1.09-.372-1.942C.01 10.445 0 10.173 0 8s.01-2.445.048-3.298C.088 3.85.222 3.269.42 2.76c.205-.526.478-.973.922-1.418A3.924 3.924 0 0 1 2.76.42C3.269.222 3.85.087 4.702.048 5.555.01 5.827 0 8 0zm0 3.892a4.108 4.108 0 1 0 0 8.216 4.108 4.108 0 0 0 0-8.216zm5.23-.162a.96.96 0 1 0-1.92 0 .96.96 0 0 0 1.92 0zM8 10.667a2.666 2.666 0 1 1 0-5.333 2.666 2.666 0 0 1 0 5.333z"/>
|
||||
<path fill-rule="evenodd" d="M8 0c2.173 0 2.445.01 3.298.048.852.04 1.433.174 1.942.372.526.205.973.478 1.418.922.444.445.717.892.922 1.418.198.509.333 1.09.372 1.942C15.99 5.555 16 5.827 16 8s-.01 2.445-.048 3.298c-.04.852-.174 1.433-.372 1.942a3.924 3.924 0 0 1-.922 1.418 3.924 3.924 0 0 1-1.418.922c-.509.198-1.09.333-1.942.372-.853.04-1.125.048-3.298.048s-2.445-.009-3.298-.048c-.852-.04-1.433-.174-1.942-.372a3.924 3.924 0 0 1-1.418-.922A3.924 3.924 0 0 1 .42 13.24c-.198-.509-.333-1.09-.372-1.942C.01 10.445 0 10.173 0 8s.01-2.445.048-3.298C.088 3.85.222 3.269.42 2.76c.205-.526.478-.973.922-1.418A3.924 3.924 0 0 1 2.76.42C3.269.222 3.85.087 4.702.048 5.555.01 5.827 0 8 0zm0 3.892a4.108 4.108 0 1 0 0 8.216 4.108 4.108 0 0 0 0-8.216zm5.23-.162a.96.96 0 1 0-1.92 0 .96.96 0 0 0 1.92 0zM8 10.667a2.666 2.666 0 1 1 0-5.333 2.666 2.666 0 0 1 0 5.333z"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 969 B After Width: | Height: | Size: 954 B |
@@ -164,30 +164,31 @@ 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_summer2019Rogue',
|
||||
head: 'head_special_summer2019Rogue',
|
||||
shield: 'shield_special_summer2019Rogue',
|
||||
weapon: 'weapon_special_summer2019Rogue',
|
||||
};
|
||||
} else if (heroClass === 'wizard') {
|
||||
return {
|
||||
armor: 'armor_wizard_5',
|
||||
head: 'head_wizard_5',
|
||||
weapon: 'weapon_wizard_6',
|
||||
armor: 'armor_special_summer2019Mage',
|
||||
head: 'head_special_summer2019Mage',
|
||||
shield: 'shield_special_summer2019Mage',
|
||||
weapon: 'weapon_special_summer2019Mage',
|
||||
};
|
||||
} else if (heroClass === 'healer') {
|
||||
return {
|
||||
armor: 'armor_healer_5',
|
||||
head: 'head_healer_5',
|
||||
shield: 'shield_healer_5',
|
||||
weapon: 'weapon_healer_6',
|
||||
armor: 'armor_special_summer2019Healer',
|
||||
head: 'head_special_summer2019Healer',
|
||||
shield: 'shield_special_summer2019Healer',
|
||||
weapon: 'weapon_special_summer2019Healer',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
armor: 'armor_warrior_5',
|
||||
head: 'head_warrior_5',
|
||||
shield: 'shield_warrior_5',
|
||||
weapon: 'weapon_warrior_6',
|
||||
armor: 'armor_special_summer2019Warrior',
|
||||
head: 'head_special_summer2019Warrior',
|
||||
shield: 'shield_special_summer2019Warrior',
|
||||
weapon: 'weapon_special_summer2019Warrior',
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<template lang="pug">
|
||||
b-modal#generic-achievement(:title='data.message', size='md', :hide-footer='true')
|
||||
.modal-body
|
||||
.col-12
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p(v-html='data.modalText')
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import achievementFooter from './achievementFooter';
|
||||
import achievementAvatar from './achievementAvatar';
|
||||
|
||||
import {mapState} from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
achievementFooter,
|
||||
achievementAvatar,
|
||||
},
|
||||
props: ['data'],
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'generic-achievement');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
46
website/client/components/achievements/justAddWater.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template lang="pug">
|
||||
b-modal#just-add-water(:title='title', size='md', :hide-footer='true')
|
||||
.modal-body
|
||||
.col-12
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p {{ $t('achievementJustAddWaterModalText') }}
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import achievementFooter from './achievementFooter';
|
||||
import achievementAvatar from './achievementAvatar';
|
||||
|
||||
import {mapState} from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
achievementFooter,
|
||||
achievementAvatar,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
title: `${this.$t('modalAchievement')} ${this.$t('achievementJustAddWater')}`,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'just-add-water');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
46
website/client/components/achievements/lostMasterclasser.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template lang="pug">
|
||||
b-modal#lost-masterclasser(:title='title', size='md', :hide-footer='true')
|
||||
.modal-body
|
||||
.col-12
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p {{ $t('achievementLostMasterclasserModalText') }}
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import achievementFooter from './achievementFooter';
|
||||
import achievementAvatar from './achievementAvatar';
|
||||
|
||||
import {mapState} from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
achievementFooter,
|
||||
achievementAvatar,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
title: `${this.$t('modalAchievement')} ${this.$t('achievementLostMasterclasser')}`,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'lost-masterclasser');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
46
website/client/components/achievements/mindOverMatter.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template lang="pug">
|
||||
b-modal#mind-over-matter(:title='title', size='md', :hide-footer='true')
|
||||
.modal-body
|
||||
.col-12
|
||||
achievement-avatar.avatar
|
||||
.col-6.offset-3.text-center
|
||||
p {{ $t('achievementMindOverMatterModalText') }}
|
||||
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
|
||||
achievement-footer
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 140px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import achievementFooter from './achievementFooter';
|
||||
import achievementAvatar from './achievementAvatar';
|
||||
|
||||
import {mapState} from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
achievementFooter,
|
||||
achievementAvatar,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
title: `${this.$t('modalAchievement')} ${this.$t('achievementMindOverMatter')}`,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'mind-over-matter');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -139,7 +139,7 @@ export default {
|
||||
let val = '28px';
|
||||
|
||||
if (!this.avatarOnly) {
|
||||
if (this.member.items.currentPet) val = '24.5px';
|
||||
if (this.member.items.currentPet) val = '24px';
|
||||
if (this.member.items.currentMount) val = '0px';
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
||||
button.btn.btn-secondary.purchase-all(@click='unlock(`skin.${set.keys.join(",skin.")}`)') {{ $t('purchaseAll') }}
|
||||
#hair.section.customize-section(v-if='activeTopPage === "hair"')
|
||||
.row.col-12.sub-menu.text-center
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color"}')
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("color")', :class='{active: activeSubPage === "color", "offset-2": !editing}')
|
||||
strong(v-once) {{$t('color')}}
|
||||
.col-3.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
|
||||
strong(v-once) {{$t('bangs')}}
|
||||
@@ -139,6 +139,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
||||
span 5
|
||||
button.btn.btn-secondary.purchase-all(@click='unlock(`hair.base.${baseHair4Keys.join(",hair.base.")}`)') {{ $t('purchaseAll') }}
|
||||
.col-12.customize-options
|
||||
.head_0.option(v-if="!editing", @click='set({"preferences.hair.base": 0})', :class="[{ active: user.preferences.hair.base === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
|
||||
.option(v-for='option in baseHair1',
|
||||
:class='{active: user.preferences.hair.base === option}')
|
||||
.base.sprite.customize-option(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
|
||||
@@ -377,8 +378,8 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
||||
username-form(@usernameConfirmed='modalPage += 1', :avatarIntro='true')
|
||||
.small.text-center(v-html="$t('usernameTOSRequirements')")
|
||||
|
||||
.section.container.footer
|
||||
.row(v-if='!editing && !(modalPage === 1)')
|
||||
.section.container.footer(v-if='!editing && !(modalPage === 1)')
|
||||
.row
|
||||
.col-3.offset-1.text-center
|
||||
div(v-if='modalPage > 1', @click='prev()')
|
||||
.prev-arrow
|
||||
@@ -406,6 +407,10 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
||||
#avatar-modal___BV_modal_body_, #avatar-modal___BV_modal_body_ {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#avatar-modal .modal-dialog {
|
||||
margin-top: 7rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -1125,7 +1130,10 @@ export default {
|
||||
return options;
|
||||
},
|
||||
eyewear () {
|
||||
let keys = ['blackTopFrame', 'blueTopFrame', 'greenTopFrame', 'pinkTopFrame', 'redTopFrame', 'whiteTopFrame', 'yellowTopFrame'];
|
||||
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 = {};
|
||||
|
||||
@@ -25,7 +25,7 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
|
||||
div.guild-bank(v-if='displayGemBank', v-once) {{$t('guildBank')}}
|
||||
.row
|
||||
category-tags.col-md-12(:categories="guild.categories", :owner="isOwner", v-once)
|
||||
span.recommend-text(v-if='showSuggested(guild._id)') Suggested because you’re new to Habitica.
|
||||
span.recommend-text(v-if='showSuggested(guild._id)') {{$t('suggestedGroup')}}
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -175,8 +175,9 @@ export default {
|
||||
methods: {
|
||||
showSuggested (guildId) {
|
||||
let habiticaHelpingGuildId = '5481ccf3-5d2d-48a9-a871-70a7380cee5a';
|
||||
let createdAfterRedesign = moment(this.user.auth.timestamps.created).isAfter('2017-08-01');
|
||||
return guildId === habiticaHelpingGuildId && createdAfterRedesign;
|
||||
let sixtyDaysAgoFromNow = moment().subtract(60, 'days');
|
||||
let isUserNew = moment(this.user.auth.timestamps.created).isAfter(sixtyDaysAgoFromNow);
|
||||
return guildId === habiticaHelpingGuildId && isUserNew;
|
||||
},
|
||||
async join () {
|
||||
// @TODO: This needs to be in the notifications where users will now accept invites
|
||||
|
||||
@@ -35,7 +35,7 @@ sidebar-section(:title="$t('questDetailsTitle')")
|
||||
.grey-progress-bar
|
||||
.collect-progress-bar(:style="{width: (group.quest.progress.collect[key] / value.count) * 100 + '%'}")
|
||||
strong {{group.quest.progress.collect[key]}} / {{value.count}}
|
||||
div.text-right {{parseFloat(user.party.quest.progress.collectedItems) || 0}} items found
|
||||
div.text-right(v-if='userIsOnQuest') {{parseFloat(user.party.quest.progress.collectedItems) || 0}} items found
|
||||
.boss-info(v-if='questData.boss')
|
||||
.row
|
||||
.col-6
|
||||
|
||||
@@ -6,49 +6,61 @@ div
|
||||
report-flag-modal
|
||||
send-gems-modal
|
||||
b-navbar.topbar.navbar-inverse.static-top(toggleable="lg", type="dark", :class="navbarZIndexClass")
|
||||
b-navbar-brand.brand
|
||||
b-navbar-brand.brand(aria-label="Habitica")
|
||||
.logo.svg-icon.d-none.d-xl-block(v-html="icons.logo")
|
||||
.svg-icon.gryphon.d-xs-block.d-xl-none
|
||||
b-navbar-toggle(target='menu_collapse').menu-toggle
|
||||
.quick-menu.mobile-only.form-inline
|
||||
a.item-with-icon(@click="sync", v-b-tooltip.hover.bottom="$t('sync')")
|
||||
a.item-with-icon(@click="sync", v-b-tooltip.hover.bottom="$t('sync')", :aria-label="$t('sync')")
|
||||
.top-menu-icon.svg-icon(v-html="icons.sync")
|
||||
notification-menu.item-with-icon
|
||||
user-dropdown.item-with-icon
|
||||
b-collapse#menu_collapse.collapse.navbar-collapse
|
||||
b-collapse#menu_collapse(v-model="menuIsOpen").collapse.navbar-collapse
|
||||
b-navbar-nav.menu-list
|
||||
b-nav-item.topbar-item(tag="li", :to="{name: 'tasks'}", exact) {{ $t('tasks') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/inventory')}")
|
||||
b-nav-item.topbar-item(:class="{'active': $route.path === '/'}" tag="li", :to="{name: 'tasks'}", exact) {{ $t('tasks') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/inventory'), 'down': $route.path.startsWith('/inventory') && this.isDesktop()}").droppable
|
||||
.chevron.rotate(@click='dropdownMobile($event)')
|
||||
.chevron-icon-down(v-html="icons.chevronDown", v-once)
|
||||
router-link.nav-link(:to="{name: 'items'}") {{ $t('inventory') }}
|
||||
.topbar-dropdown
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'items'}", exact) {{ $t('items') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'equipment'}") {{ $t('equipment') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'stable'}") {{ $t('stable') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/shop')}")
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/shop'), 'down': $route.path.startsWith('/shop') && this.isDesktop()}").droppable
|
||||
.chevron.rotate(@click='dropdownMobile($event)')
|
||||
.chevron-icon-down(v-html="icons.chevronDown", v-once)
|
||||
router-link.nav-link(:to="{name: 'market'}") {{ $t('shops') }}
|
||||
.topbar-dropdown
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'market'}", exact) {{ $t('market') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'quests'}") {{ $t('quests') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'seasonal'}") {{ $t('titleSeasonalShop') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'time'}") {{ $t('titleTimeTravelers') }}
|
||||
b-nav-item.topbar-item(tag="li", :to="{name: 'party'}", v-if='this.user.party._id') {{ $t('party') }}
|
||||
b-nav-item.topbar-item(@click='openPartyModal()', v-if='!this.user.party._id') {{ $t('party') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/guilds')}")
|
||||
b-nav-item.topbar-item(:class="{'active': $route.path.startsWith('/party')}" tag="li", :to="{name: 'party'}", v-if='this.user.party._id') {{ $t('party') }}
|
||||
b-nav-item.topbar-item(:class="{'active': $route.path.startsWith('/party')}" @click='openPartyModal()', v-if='!this.user.party._id') {{ $t('party') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/groups'), 'down': $route.path.startsWith('/groups') && this.isDesktop()}").droppable
|
||||
.chevron.rotate(@click='dropdownMobile($event)')
|
||||
.chevron-icon-down(v-html="icons.chevronDown", v-once)
|
||||
router-link.nav-link(:to="{name: 'tavern'}") {{ $t('guilds') }}
|
||||
.topbar-dropdown
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/group-plans')}")
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/group-plans'), 'down': $route.path.startsWith('/group-plans') && this.isDesktop()}").droppable
|
||||
.chevron.rotate(v-if="groupPlans.length > 0", @click='dropdownMobile($event)')
|
||||
.chevron-icon-down(v-html="icons.chevronDown", v-once)
|
||||
router-link.nav-link(:to="{name: 'groupPlan'}") {{ $t('group') }}
|
||||
.topbar-dropdown
|
||||
router-link.topbar-dropdown-item.dropdown-item(v-for='group in groupPlans', :key='group._id', :to="{name: 'groupPlanDetailTaskInformation', params: {groupId: group._id}}") {{ group.name }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/challenges')}")
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/challenges'), 'down': $route.path.startsWith('/challenges') && this.isDesktop()}").droppable
|
||||
.chevron.rotate(@click='dropdownMobile($event)')
|
||||
.chevron-icon-down(v-html="icons.chevronDown", v-once)
|
||||
router-link.nav-link(:to="{name: 'myChallenges'}") {{ $t('challenges') }}
|
||||
.topbar-dropdown
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'myChallenges'}") {{ $t('myChallenges') }}
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'findChallenges'}") {{ $t('findChallenges') }}
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/help')}")
|
||||
li.topbar-item(:class="{'active': $route.path.startsWith('/help'), 'down': $route.path.startsWith('/help') && this.isDesktop()}").droppable
|
||||
.chevron.rotate(@click='dropdownMobile($event)')
|
||||
.chevron-icon-down(v-html="icons.chevronDown", v-once)
|
||||
router-link.nav-link(:to="{name: 'faq'}") {{ $t('help') }}
|
||||
.topbar-dropdown
|
||||
router-link.topbar-dropdown-item.dropdown-item(:to="{name: 'faq'}") {{ $t('faq') }}
|
||||
@@ -64,13 +76,13 @@ div
|
||||
.top-menu-icon.svg-icon(v-html="icons.hourglasses", v-b-tooltip.hover.bottom="$t('mysticHourglassesTooltip')")
|
||||
span {{ userHourglasses }}
|
||||
.item-with-icon
|
||||
.top-menu-icon.svg-icon.gem(v-html="icons.gem", @click='showBuyGemsModal("gems")', v-b-tooltip.hover.bottom="$t('gems')")
|
||||
a.top-menu-icon.svg-icon.gem(:aria-label="$t('gems')", href="#buy-gems" v-html="icons.gem", @click.prevent='showBuyGemsModal("gems")', v-b-tooltip.hover.bottom="$t('gems')")
|
||||
span {{userGems}}
|
||||
.item-with-icon.gold
|
||||
.top-menu-icon.svg-icon(v-html="icons.gold", v-b-tooltip.hover.bottom="$t('gold')")
|
||||
.top-menu-icon.svg-icon(:aria-label="$t('gold')", v-html="icons.gold", v-b-tooltip.hover.bottom="$t('gold')")
|
||||
span {{Math.floor(user.stats.gp * 100) / 100}}
|
||||
.form-inline.desktop-only
|
||||
a.item-with-icon(@click="sync", v-b-tooltip.hover.bottom="$t('sync')")
|
||||
a.item-with-icon(@click="sync", @keyup.enter="sync", role="link", :aria-label="$t('sync')", tabindex="0", v-b-tooltip.hover.bottom="$t('sync')")
|
||||
.top-menu-icon.svg-icon(v-html="icons.sync")
|
||||
notification-menu.item-with-icon
|
||||
user-dropdown.item-with-icon
|
||||
@@ -81,6 +93,10 @@ div
|
||||
@import '~client/assets/scss/utils.scss';
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.chevron {
|
||||
display: none
|
||||
}
|
||||
|
||||
.gryphon {
|
||||
background-image: url('~assets/images/melior@3x.png');
|
||||
width: 30px;
|
||||
@@ -96,6 +112,10 @@ div
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 992px) {
|
||||
.chevron {
|
||||
display: none
|
||||
}
|
||||
|
||||
.mobile-only {
|
||||
display: none !important;
|
||||
}
|
||||
@@ -111,6 +131,10 @@ div
|
||||
padding-top: 5px;
|
||||
height: 56px;
|
||||
|
||||
&:hover {
|
||||
background: $purple-200;
|
||||
}
|
||||
|
||||
&.active:not(:hover) {
|
||||
box-shadow: 0px -4px 0px $purple-300 inset;
|
||||
}
|
||||
@@ -144,12 +168,40 @@ div
|
||||
order: 1;
|
||||
text-align: center;
|
||||
|
||||
.topbar-dropdown {
|
||||
transition: max-height 0.25s ease;
|
||||
}
|
||||
|
||||
.topbar-dropdown-item {
|
||||
background: #432874;
|
||||
border-bottom: #6133b4 solid 1px;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
width: 20%;
|
||||
height: 42px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chevron-icon-down {
|
||||
width: 14px;
|
||||
top: 11px;
|
||||
right: 12px;
|
||||
position: absolute;
|
||||
display: block;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.down .rotate .chevron-icon-down {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
.topbar-item {
|
||||
position: relative;
|
||||
|
||||
&.active {
|
||||
background: #6133b4;
|
||||
}
|
||||
@@ -223,20 +275,25 @@ div
|
||||
font-weight: bold;
|
||||
transition: none;
|
||||
|
||||
.topbar-dropdown {
|
||||
display: none; // Display is set to block on hover.
|
||||
.topbar-dropdown {
|
||||
overflow: hidden;
|
||||
max-height: 0;
|
||||
|
||||
.topbar-dropdown-item {
|
||||
line-height: 1.5;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
>a {
|
||||
padding: .8em 1em !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&.down {
|
||||
color: $white !important;
|
||||
background: $purple-200;
|
||||
|
||||
.topbar-dropdown {
|
||||
display: block; // Open drop-down on hover.
|
||||
margin-top: 0; // Remove gap between navbar and drop-down.
|
||||
background: $purple-200;
|
||||
border-radius: 0px;
|
||||
@@ -290,6 +347,7 @@ div
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
&:focus /deep/ .top-menu-icon.svg-icon,
|
||||
&:hover /deep/ .top-menu-icon.svg-icon {
|
||||
color: $white;
|
||||
}
|
||||
@@ -343,6 +401,7 @@ import gemIcon from 'assets/svg/gem.svg';
|
||||
import goldIcon from 'assets/svg/gold.svg';
|
||||
import syncIcon from 'assets/svg/sync.svg';
|
||||
import svgHourglasses from 'assets/svg/hourglass.svg';
|
||||
import chevronDownIcon from 'assets/svg/chevron-down.svg';
|
||||
import logo from 'assets/svg/logo.svg';
|
||||
|
||||
import creatorIntro from '../creatorIntro';
|
||||
@@ -369,12 +428,14 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
isUserDropdownOpen: false,
|
||||
menuIsOpen: false,
|
||||
icons: Object.freeze({
|
||||
gem: gemIcon,
|
||||
gold: goldIcon,
|
||||
hourglasses: svgHourglasses,
|
||||
sync: syncIcon,
|
||||
logo,
|
||||
chevronDown: chevronDownIcon,
|
||||
}),
|
||||
};
|
||||
},
|
||||
@@ -397,6 +458,13 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
this.getUserGroupPlans();
|
||||
Array.from(document.getElementById('menu_collapse').getElementsByTagName('a')).forEach(link => {
|
||||
link.addEventListener('click', this.closeMenu);
|
||||
});
|
||||
Array.from(document.getElementsByClassName('topbar-item')).forEach(link => {
|
||||
link.addEventListener('mouseenter', this.dropdownDesktop);
|
||||
link.addEventListener('mouseleave', this.dropdownDesktop);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
modForm () {
|
||||
@@ -423,7 +491,40 @@ export default {
|
||||
|
||||
this.$root.$emit('bv::show::modal', 'buy-gems', {alreadyTracked: true});
|
||||
},
|
||||
dropdownDesktop (hover) {
|
||||
if (this.isDesktop() && hover.target.classList.contains('droppable')) {
|
||||
this.dropdown(hover.target);
|
||||
}
|
||||
},
|
||||
dropdownMobile (click) {
|
||||
this.dropdown(click.currentTarget.parentElement);
|
||||
},
|
||||
dropdown (element) {
|
||||
let droppedElement = document.getElementsByClassName('down')[0];
|
||||
if (droppedElement && droppedElement !== element) {
|
||||
droppedElement.classList.remove('down');
|
||||
droppedElement.lastChild.style.maxHeight = 0;
|
||||
}
|
||||
|
||||
element.classList.toggle('down');
|
||||
element.lastChild.style.maxHeight = element.classList.contains('down') ? `${element.lastChild.scrollHeight}px` : 0;
|
||||
},
|
||||
closeMenu () {
|
||||
if (this.isMobile()) {
|
||||
this.menuIsOpen = false;
|
||||
|
||||
Array.from(document.getElementsByClassName('droppable')).forEach(droppableElement => {
|
||||
droppableElement.classList.remove('down');
|
||||
droppableElement.lastChild.style.maxHeight = 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
isMobile () {
|
||||
return document.documentElement.clientWidth < 992;
|
||||
},
|
||||
isDesktop () {
|
||||
return !this.isMobile();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<template lang="pug">
|
||||
base-notification(
|
||||
:can-remove="canRemove",
|
||||
:notification="notification",
|
||||
:read-after-click="true",
|
||||
@click="action"
|
||||
)
|
||||
div(slot="content", v-html="achievementString")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
|
||||
export default {
|
||||
props: ['notification', 'canRemove'],
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
computed: {
|
||||
achievementString () {
|
||||
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementJustAddWater')}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
action () {
|
||||
this.$root.$emit('bv::show::modal', 'just-add-water');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template lang="pug">
|
||||
base-notification(
|
||||
:can-remove="canRemove",
|
||||
:notification="notification",
|
||||
:read-after-click="true",
|
||||
@click="action"
|
||||
)
|
||||
div(slot="content", v-html="achievementString")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
|
||||
export default {
|
||||
props: ['notification', 'canRemove'],
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
computed: {
|
||||
achievementString () {
|
||||
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementLostMasterclasser')}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
action () {
|
||||
this.$root.$emit('bv::show::modal', 'lost-masterclasser');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template lang="pug">
|
||||
base-notification(
|
||||
:can-remove="canRemove",
|
||||
:notification="notification",
|
||||
:read-after-click="true",
|
||||
@click="action"
|
||||
)
|
||||
div(slot="content", v-html="achievementString")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
|
||||
export default {
|
||||
props: ['notification', 'canRemove'],
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
computed: {
|
||||
achievementString () {
|
||||
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementMindOverMatter')}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
action () {
|
||||
this.$root.$emit('bv::show::modal', 'mind-over-matter');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template lang="pug">
|
||||
menu-dropdown.item-notifications(:right="true", @toggled="handleOpenStatusChange", :openStatus="openStatus")
|
||||
div(slot="dropdown-toggle")
|
||||
div(v-b-tooltip.hover.bottom="$t('notifications')")
|
||||
div(:aria-label="$t('notifications')", v-b-tooltip.hover.bottom="$t('notifications')")
|
||||
message-count(
|
||||
v-if='notificationsCount > 0',
|
||||
:count="notificationsCount",
|
||||
@@ -95,6 +95,9 @@ import NEW_INBOX_MESSAGE from './notifications/newInboxMessage';
|
||||
import NEW_CHAT_MESSAGE from './notifications/newChatMessage';
|
||||
import WORLD_BOSS from './notifications/worldBoss';
|
||||
import VERIFY_USERNAME from './notifications/verifyUsername';
|
||||
import ACHIEVEMENT_JUST_ADD_WATER from './notifications/justAddWater';
|
||||
import ACHIEVEMENT_LOST_MASTERCLASSER from './notifications/lostMasterclasser';
|
||||
import ACHIEVEMENT_MIND_OVER_MATTER from './notifications/mindOverMatter';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -106,6 +109,7 @@ export default {
|
||||
QUEST_INVITATION, GROUP_TASK_APPROVAL, GROUP_TASK_APPROVED, GROUP_TASK_ASSIGNED,
|
||||
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,
|
||||
WorldBoss: WORLD_BOSS,
|
||||
VERIFY_USERNAME,
|
||||
},
|
||||
@@ -130,6 +134,7 @@ export default {
|
||||
'QUEST_INVITATION', 'GROUP_TASK_ASSIGNED', 'GROUP_TASK_APPROVAL', 'GROUP_TASK_APPROVED',
|
||||
'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',
|
||||
'VERIFY_USERNAME',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template lang="pug">
|
||||
menu-dropdown.item-user(:right="true")
|
||||
div(slot="dropdown-toggle")
|
||||
div(v-b-tooltip.hover.bottom="$t('user')")
|
||||
div(:aria-label="$t('user')", v-b-tooltip.hover.bottom="$t('user')")
|
||||
message-count(v-if='user.inbox.newMessages > 0', :count="user.inbox.newMessages", :top="true")
|
||||
.top-menu-icon.svg-icon.user(v-html="icons.user")
|
||||
.user-dropdown(slot="dropdown-content")
|
||||
|
||||
@@ -26,6 +26,10 @@ div
|
||||
quest-completed
|
||||
quest-invitation
|
||||
verify-username
|
||||
generic-achievement(:data='notificationData')
|
||||
just-add-water
|
||||
lost-masterclasser
|
||||
mind-over-matter
|
||||
</template>
|
||||
|
||||
<style lang='scss'>
|
||||
@@ -118,6 +122,10 @@ import rebirth from './achievements/rebirth';
|
||||
import streak from './achievements/streak';
|
||||
import ultimateGear from './achievements/ultimateGear';
|
||||
import wonChallenge from './achievements/wonChallenge';
|
||||
import genericAchievement from './achievements/genericAchievement';
|
||||
import justAddWater from './achievements/justAddWater';
|
||||
import lostMasterclasser from './achievements/lostMasterclasser';
|
||||
import mindOverMatter from './achievements/mindOverMatter';
|
||||
import loginIncentives from './achievements/login-incentives';
|
||||
import verifyUsername from './settings/verifyUsername';
|
||||
|
||||
@@ -147,6 +155,16 @@ const NOTIFICATIONS = {
|
||||
label: ($t) => $t('modalContribAchievement'),
|
||||
modalId: 'contributor',
|
||||
},
|
||||
ACHIEVEMENT_ALL_YOUR_BASE: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('achievementAllYourBase')}`,
|
||||
modalId: 'generic-achievement',
|
||||
},
|
||||
ACHIEVEMENT_BACK_TO_BASICS: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('achievementBackToBasics')}`,
|
||||
modalId: 'generic-achievement',
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
@@ -176,6 +194,10 @@ export default {
|
||||
contributor,
|
||||
loginIncentives,
|
||||
verifyUsername,
|
||||
genericAchievement,
|
||||
lostMasterclasser,
|
||||
mindOverMatter,
|
||||
justAddWater,
|
||||
},
|
||||
data () {
|
||||
// Levels that already display modals and should not trigger generic Level Up
|
||||
@@ -197,7 +219,8 @@ export default {
|
||||
'GUILD_PROMPT', 'DROPS_ENABLED', 'REBIRTH_ENABLED', 'WON_CHALLENGE', 'STREAK_ACHIEVEMENT',
|
||||
'ULTIMATE_GEAR_ACHIEVEMENT', 'REBIRTH_ACHIEVEMENT', 'GUILD_JOINED_ACHIEVEMENT',
|
||||
'CHALLENGE_JOINED_ACHIEVEMENT', 'INVITED_FRIEND_ACHIEVEMENT', 'NEW_CONTRIBUTOR_LEVEL',
|
||||
'CRON', 'SCORED_TASK', 'LOGIN_INCENTIVE',
|
||||
'CRON', 'SCORED_TASK', 'LOGIN_INCENTIVE', 'ACHIEVEMENT_ALL_YOUR_BASE', 'ACHIEVEMENT_BACK_TO_BASICS',
|
||||
'GENERIC_ACHIEVEMENT',
|
||||
].forEach(type => {
|
||||
handledNotifications[type] = true;
|
||||
});
|
||||
@@ -342,8 +365,8 @@ export default {
|
||||
this.playSound('Death');
|
||||
this.$root.$emit('bv::show::modal', 'death');
|
||||
},
|
||||
showNotificationWithModal (type, forceToModal) {
|
||||
const config = NOTIFICATIONS[type];
|
||||
showNotificationWithModal (notification, forceToModal) {
|
||||
const config = NOTIFICATIONS[notification.type];
|
||||
|
||||
if (!config) {
|
||||
return;
|
||||
@@ -355,6 +378,10 @@ export default {
|
||||
this.playSound(config.sound);
|
||||
}
|
||||
|
||||
if (notification.data) {
|
||||
this.notificationData = notification.data;
|
||||
}
|
||||
|
||||
if (forceToModal) {
|
||||
this.$root.$emit('bv::show::modal', config.modalId);
|
||||
} else {
|
||||
@@ -566,7 +593,10 @@ export default {
|
||||
case 'CHALLENGE_JOINED_ACHIEVEMENT':
|
||||
case 'INVITED_FRIEND_ACHIEVEMENT':
|
||||
case 'NEW_CONTRIBUTOR_LEVEL':
|
||||
this.showNotificationWithModal(notification.type);
|
||||
case 'ACHIEVEMENT_ALL_YOUR_BASE':
|
||||
case 'ACHIEVEMENT_BACK_TO_BASICS':
|
||||
case 'GENERIC_ACHIEVEMENT':
|
||||
this.showNotificationWithModal(notification);
|
||||
break;
|
||||
case 'CRON':
|
||||
if (notification.data) {
|
||||
|
||||