finish unlock hero

This commit is contained in:
zhl 2021-01-08 11:34:44 +08:00
parent dd5c51c722
commit c4c3ba8ac1
6 changed files with 241 additions and 164 deletions

View File

@ -244,8 +244,7 @@
| 字段 | 说明 |
| -------- | -------------------------------------- |
| moneyid |代币的item id |
| count |试用数量 |
| count |使用数量 |
3. Response: JSON
@ -258,7 +257,25 @@
```
### 11. 将专属英雄碎片转化成经验
1. Method: POST
2. URI: /api/:accountid/hero/toexp/:heroid
| 字段 | 说明 |
| -------- | -------------------------------------- |
| accountid | 帐号id |
| heroid | 英雄id |
3. Response: JSON
```json
{
exp: 1022, // 当前经验值
exp_POST: 100, // 本次获得的经验
level: 1 // 当前等级
}
```
## 三. 服务端接口列表
@ -277,3 +294,5 @@
```
```

View File

@ -1,18 +1,15 @@
import BaseController from "../common/base.controller";
import {role, router} from "../decorators/router";
import {Account} from "../models/Account";
import {User} from "../models/User";
import {ZError} from "../common/ZError";
import {Hero} from "../models/subdoc/Hero";
import {Card} from "../models/subdoc/Card";
import {CardGroup} from "../models/CardGroup";
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
export default class AccountController extends BaseController {
@role('anon')
@router('post /api/:accountid/uinfo')
async info(req: any) {
let {accountid} = req.params;
let account = (await Account.findOrCreate({_id: accountid})).doc;
let account = (await User.findOrCreate({_id: accountid})).doc;
let result: any = {accountid: account.id};
if (account.locked) {
throw new ZError(4, 'account locked');
@ -63,69 +60,5 @@ export default class AccountController extends BaseController {
return result;
}
@router('post /api/:accountid/heros')
async herolist(req: any) {
let account = req.user;
let heros: any[] = [];
for(let [key, hero] of account.heros) {
heros.push({
heroid: hero.heroid,
owned: true,
usetype: 0,
level: hero.level,
exp: hero.exp,
free: hero.free,
free_expire: 0
});
}
//TODO:: 添加限免英雄和免费英雄
return heros;
}
@router('post /api/:accountid/hero/unlock/:heroid')
async unlockHero(req: any) {
let account = req.user;
let {heroid, type} = req.params;
if (!heroid) {
throw new ZError(101, '未指定heroid');
}
if (account.heros.has(heroid + '')) {
if (!account.heros.get(heroid + '').free) {
throw new ZError(102, '你已经解锁了该英雄');
}
}
let money0 = MoneyTypeConst.getHeroShard(heroid);
let money1 = MoneyTypeConst.HERO_SHARD;
let count0 = account.moneys.has(money0) ? account.moneys.get(money0) : 0;
let count1 = account.moneys.has(money1) ? account.moneys.get(money1) : 0;
// TODO:: 根据配置获取解锁英雄需要的碎片数量
let needCount = 30;
if (count0 + count1 < needCount) {
throw new ZError(102, '碎片数量不足');
}
if (count0 > 0) {
let rest = needCount - count0;
if (rest >= 0) {
needCount = rest;
account.moneys.set(money0, 0);
} else {
needCount = 0;
account.moneys.set(money0, Math.abs(rest));
}
}
// 上面已经过滤了 count0 + count1 > needcount, 所以这里不需要判断碎片是否足够
if (needCount > 0) {
count1 = count1 - needCount;
account.moneys.set(money1, count1);
}
let hero = new Hero();
hero.heroid = heroid;
hero.free = false;
hero.level = 1;
hero.exp = 0;
account.heros.set(heroid + '', hero);
return {};
}
}

View File

@ -0,0 +1,70 @@
import BaseController from "../common/base.controller";
import {router} from "../decorators/router";
import {ZError} from "../common/ZError";
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
import {Hero} from "../models/subdoc/Hero";
import {User} from "../models/User";
export default class HeroController extends BaseController {
@router('post /api/:accountid/heros')
async herolist(req: any) {
let account = req.user;
let heros: any[] = [];
for(let [key, hero] of account.heros) {
heros.push({
heroid: hero.heroid,
owned: true,
usetype: 0,
level: hero.level,
exp: hero.exp,
free: hero.free,
free_expire: 0
});
}
//TODO:: 添加限免英雄和免费英雄
return heros;
}
@router('post /api/:accountid/hero/unlock/:heroid')
async unlockHero(req: any) {
let account = req.user;
let {heroid, type} = req.params;
if (!heroid) {
throw new ZError(101, '未指定heroid');
}
try {
if (!type) {
let hero = await account.unlockHero(heroid);
await account.save();
return hero;
} else {
let hero = await account.tryHero(heroid);
await account.save();
return hero;
}
} catch (err) {
throw err;
}
}
@router('post /api/:accountid/hero/update/:heroid')
async updateHero(req: any) {
let account = req.user;
let {heroid, count} = req.params;
if (!heroid) {
throw new ZError(101, '未指定heroid');
}
if (!account.heros.has(heroid + '')) {
throw new ZError(102, '你未解锁该英雄');
}
}
@router('post /api/:accountid/hero/toexp/:heroid')
async shardToExp(req: any) {
let account = req.user;
let {heroid} = req.params;
}
}

View File

@ -1,91 +0,0 @@
import {
prop,
getModelForClass,
modelOptions,
index,
plugin,
mongoose
} from '@typegoose/typegoose';
import {dbconn} from '../decorators/dbconn';
// @ts-ignore
import findOrCreate from 'mongoose-findorcreate';
import {
Base,
FindOrCreate,
TimeStamps
} from "@typegoose/typegoose/lib/defaultClasses";
import {Card} from "./subdoc/Card";
import {Hero} from "./subdoc/Hero";
interface AccountClass extends Base<string>, TimeStamps {}
@dbconn()
// @index({ _id: 1}, { unique: true })
@plugin(findOrCreate)
@modelOptions({schemaOptions:
{collection: "account", timestamps: true}
})
class AccountClass extends FindOrCreate{
@prop()
public _id: string;
@prop({default: false})
public locked: boolean;
@prop()
public lockedtime?: number;
@prop()
public comment?: string;
@prop()
public lastLogin?: Date;
/**
*
*/
@prop({ type: () => [Number] })
public cards: number[];
/**
*
*/
@prop({ type: Hero, default: new Map() })
public heros: Map<string, Hero>;
/**
*
* coin: 金币
* diamond: 钻石
* hero_shard: 通用英雄碎片
* hero_exp: 通用英雄经验
* hero_shard_heroid: 英雄专用碎片
* hero_exp_heroid: 英雄专用经验
* card_scroll: 抽卡卷轴
*/
@prop({ type: Number, default: new Map() })
public moneys: Map<string, number>;
/**
* 匹配: 胜利场数, , , 线
*/
@prop({type: Number, default: [0,0,0,0]})
public normal_stat: number[];
/**
* 当前赛季: 胜利场数, , , 线
*/
@prop({type: Number, default: [0,0,0,0]})
public season_stat: number[];
/**
* ,
*/
@prop({type: mongoose.Schema.Types.Mixed})
public extinfo: any;
public toJson() {
return {
accountid: this._id,
}
}
}
export const Account = getModelForClass(AccountClass,
// @ts-ignore
{existingConnection: AccountClass['db']});

146
src/models/User.ts Normal file
View File

@ -0,0 +1,146 @@
import {
prop,
getModelForClass,
modelOptions,
index,
plugin,
mongoose
} from '@typegoose/typegoose';
import {dbconn} from '../decorators/dbconn';
// @ts-ignore
import findOrCreate from 'mongoose-findorcreate';
import {
Base,
FindOrCreate,
TimeStamps
} from "@typegoose/typegoose/lib/defaultClasses";
import {Card} from "./subdoc/Card";
import {Hero} from "./subdoc/Hero";
import {ZError} from "../common/ZError";
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
interface AccountClass extends Base<string>, TimeStamps {}
@dbconn()
// @index({ _id: 1}, { unique: true })
@plugin(findOrCreate)
@modelOptions({schemaOptions:
{collection: "account", timestamps: true}
})
class UserClass extends FindOrCreate{
@prop()
public _id: string;
@prop({default: false})
public locked: boolean;
@prop()
public lockedtime?: number;
@prop()
public comment?: string;
@prop()
public lastLogin?: Date;
/**
*
*/
@prop({ type: () => [Number] })
public cards: number[];
/**
*
*/
@prop({ type: Hero, default: new Map() })
public heros: Map<string, Hero>;
/**
*
* coin: 金币
* diamond: 钻石
* hero_shard: 通用英雄碎片
* hero_exp: 通用英雄经验
* hero_shard_heroid: 英雄专用碎片
* hero_exp_heroid: 英雄专用经验
* card_scroll: 抽卡卷轴
*/
@prop({ type: Number, default: new Map() })
public moneys: Map<string, number>;
/**
* 匹配: 胜利场数, , , 线
*/
@prop({type: Number, default: [0,0,0,0]})
public normal_stat: number[];
/**
* 当前赛季: 胜利场数, , , 线
*/
@prop({type: Number, default: [0,0,0,0]})
public season_stat: number[];
/**
* ,
*/
@prop({type: mongoose.Schema.Types.Mixed})
public extinfo: any;
public toJson() {
return {
accountid: this._id,
}
}
public async unlockHero(heroid: number) {
if (this.heros.has(heroid + '')) {
if (!this.heros.get(heroid + '').free) {
throw new ZError(102, '你已经解锁了该英雄');
}
}
let money0 = MoneyTypeConst.getHeroShard(heroid);
let money1 = MoneyTypeConst.HERO_SHARD;
let count0 = this.moneys.has(money0) ? this.moneys.get(money0) : 0;
let count1 = this.moneys.has(money1) ? this.moneys.get(money1) : 0;
// TODO:: 根据配置获取解锁英雄需要的碎片数量
let needCount = 30;
if (count0 + count1 < needCount) {
throw new ZError(102, '碎片数量不足');
}
if (count0 > 0) {
let rest = needCount - count0;
if (rest >= 0) {
needCount = rest;
this.moneys.set(money0, 0);
} else {
needCount = 0;
this.moneys.set(money0, Math.abs(rest));
}
}
// 上面已经过滤了 count0 + count1 > needcount, 所以这里不需要判断碎片是否足够
if (needCount > 0) {
count1 = count1 - needCount;
this.moneys.set(money1, count1);
}
let hero = new Hero();
hero.heroid = heroid;
hero.free = false;
hero.level = 1;
hero.exp = 0;
this.heros.set(heroid + '', hero);
return hero;
}
public async tryHero(heroid: number) {
if (this.heros.has(heroid + '')) {
throw new ZError(102, '你已经解锁了该英雄');
}
//TODO:: 根据配置查看该英雄是否可使用
let hero = new Hero();
hero.heroid = heroid;
hero.free = true;
hero.level = 1;
hero.exp = 0;
this.heros.set(heroid+'', hero);
return hero;
}
}
export const User = getModelForClass(UserClass,
// @ts-ignore
{existingConnection: UserClass['db']});

View File

@ -4,7 +4,7 @@ import {
FastifyRequest,
} from 'fastify';
import fastifyPlugin from 'fastify-plugin';
import {Account} from '../models/Account';
import {User} from '../models/User';
import {ZError} from "../common/ZError";
declare module 'fastify' {
@ -41,7 +41,7 @@ const apiAuthPlugin: FastifyPluginAsync = async function(
// if (!data || !data.id) {
// return reply.send({code: 10, msg: 'need login'});
// }
let account = await Account.findById(accountid);
let account = await User.findById(accountid);
if (!account) {
return reply.send({code: 5, msg: 'account not found'});
}