修改抽卡的接口

This commit is contained in:
zhl 2021-01-22 18:47:16 +08:00
parent 79e8075102
commit 6cf709ff64
8 changed files with 240 additions and 177 deletions

View File

@ -178,64 +178,33 @@
根据errcode判断成功or失败 根据errcode判断成功or失败
### ~~7. 解锁英雄~~
### 8. 抽卡
1. Method: POST 1. Method: POST
2. URI: /api/:accountid/hero/unlock/:heroid 2. URI: /api/:accountid/card/draw
| 字段 | 说明 | | 字段 | 说明 |
| -------- | -------------------------------------- | | -------- | -------------------------------------- |
| accountid | 帐号id | | accountid | 帐号id |
| heroid | 英雄id |
> POST参数 > POST参数
| 字段 | 说明 | | 字段 | 说明 |
| -------- | -------------------------------------- | | -------- | -------------------------------------- |
| type | 类型 0: 碎片, 1: 试用 | | count | 类型 1 或 10 |
|itemid| 抽卡使用的物品id |
3. Response: JSON
> 说明: 解锁成功的话, 会返回当前解锁英雄的数据
```js
[{
heroid: 1022, // 英雄id
owned: true, // 是否已拥有
ban: false, // 是否被禁用
usetype: 1, // 赛季专属, 0: 通用, 1: 赛季排位专用, 2: 匹配专用
free: false, // 是否免费
trial: false, // 是否是试用
trial_expire: 1609919293 // 试用到期时间, 0: 说明是永久
level: 1, // 等级
exp: 0, // 当前的经验值
}]
```
### 8. 抽卡
1. Method: POST
2. URI: /api/:accountid/card/draw/:count
| 字段 | 说明 |
| -------- | -------------------------------------- |
| accountid | 帐号id |
| count | 抽卡数量 |
3. Response: JSON 3. Response: JSON
```js ```js
[{ [{
cardid: 1022, // 卡牌id id: 11022, // 卡牌id
isnew: true, // 是否是新获得的卡 used: 1, // 是否已经自动激活卡或英雄, 1: 已自动激活 0: 未激活
expdust: '', // 分解可获得的英雄经验的item id heroid: 111, // 激活的英雄id, 可能为空
dustcount: 100 // 可获得数量 cardid: 100 // 激活的卡id, 可能为空
}] }]
``` ```
@ -521,6 +490,44 @@
``` ```
### 3. 解锁英雄
1. Method: POST
2. URI: /svr/:accountid/hero/unlock/:heroid
| 字段 | 说明 |
| -------- | -------------------------------------- |
| accountid | 帐号id |
| heroid | 英雄id |
> POST参数
| 字段 | 说明 |
| -------- | -------------------------------------- |
| type | 类型 0: 碎片, 1: 试用 |
3. Response: JSON
> 说明: 解锁成功的话, 会返回当前解锁英雄的数据
```js
[{
heroid: 1022, // 英雄id
owned: true, // 是否已拥有
ban: false, // 是否被禁用
usetype: 1, // 赛季专属, 0: 通用, 1: 赛季排位专用, 2: 匹配专用
free: false, // 是否免费
trial: false, // 是否是试用
trial_expire: 1609919293 // 试用到期时间, 0: 说明是永久
level: 1, // 等级
exp: 0, // 当前的经验值
}]
```

View File

@ -7,6 +7,7 @@ import { BaseConst } from '../constants/BaseConst'
import { Hero } from '../models/subdoc/Hero' import { Hero } from '../models/subdoc/Hero'
import { CardGroup } from '../models/CardGroup' import { CardGroup } from '../models/CardGroup'
import { BagItem, ItemType } from '../models/BagItem' import { BagItem, ItemType } from '../models/BagItem'
import { addHeroDefaultCardGroup } from '../dao/CardGroupDao'
export default class AccountController extends BaseController { export default class AccountController extends BaseController {
@role('anon') @role('anon')
@ -48,27 +49,7 @@ export default class AccountController extends BaseController {
hero.exp = 0 hero.exp = 0
if (!account.heros.has(cfg.id + '')) { if (!account.heros.has(cfg.id + '')) {
account.heros.set(cfg.id + '', hero) account.heros.set(cfg.id + '', hero)
let cardgroup = new CardGroup({}) await addHeroDefaultCardGroup(accountid, hero.heroid, cardMap)
let cards: Card[] = []
for (let i = 1; i <= 4; i++) {
const cardid = cfg[`follower${ i }id`]
const owned = cardMap.has(cardid)
const card = new Card()
card.cardid = cardid
card.owned = owned
card.ban = false
card.usetype = 0
card.free = !owned
card.free_expire = 0
card.time = Date.now()
cards.push(card)
}
cardgroup.accountid = account.id
cardgroup.heroid = cfg.id
cardgroup.selected = false
cardgroup.isdefault = true
cardgroup.cards = cards
await cardgroup.save()
} }
} }
} }

View File

@ -7,6 +7,10 @@ import { MoneyTypeConst } from '../constants/MoneyTypeConst'
import { BaseConst } from '../constants/BaseConst' import { BaseConst } from '../constants/BaseConst'
import { BagItem, ItemType } from '../models/BagItem' import { BagItem, ItemType } from '../models/BagItem'
import ItemCtrl from '../logic/ItemCtrl' import ItemCtrl from '../logic/ItemCtrl'
import { error } from '../common/Debug'
import { ItemFuncCfg } from '../cfg/parsers/ItemFuncCfg'
import { addHeroDefaultCardGroup } from '../dao/CardGroupDao'
import { ItemInfo } from '../logic/ItemDef'
export default class CardController extends BaseController { export default class CardController extends BaseController {
@router('post /api/:accountid/card_group/:heroid') @router('post /api/:accountid/card_group/:heroid')
@ -123,56 +127,102 @@ export default class CardController extends BaseController {
return {} return {}
} }
@router('post /api/:accountid/card/draw/:count') @router('post /api/:accountid/card/draw')
async drawCard(req: any) { async drawCard(req: any) {
let { count } = req.params let { count, accountid, itemid } = req.params
if (count < 10) { count = count << 0
count = 1 itemid = itemid << 0
if (count != 10 && count != 1) {
throw new ZError(101, '参数不正确')
} }
if (count > 10) { let cfg: ItemFuncCfg = count == 10 ?
count = 10 global.$cfg.get(BaseConst.ITEMFUNC).get(90002):
global.$cfg.get(BaseConst.ITEMFUNC).get(90001)
if (!cfg) {
error(`抽卡 ${accountid} : [${count}, 无法找到抽卡配置`)
throw new ZError(102, '无法找到对应的配置')
}
let itemInfo = ItemCtrl.getItemsByInfo(cfg.consume1)
if (count == 1 && itemInfo.length == 0) {
throw new ZError(103, '无法找到对应的配置')
}
if (count == 1 && itemInfo[0].id !== itemid) {
throw new ZError(104, '解锁物品与配置不符')
}
if (count == 10) {
if (itemid != itemInfo[0].id) {
itemInfo = ItemCtrl.getItemsByInfo(cfg.consume2)
if (itemInfo.length == 0 || itemInfo[0].id != itemid) {
throw new ZError(104, '解锁物品与配置不符')
}
}
}
let record = await BagItem.findOne({accountid, itemid})
if (!record || record.count < count) {
throw new ZError(105, '解锁物品数量不足')
}
const items: ItemInfo[] = []
for (let z = 0 ; z < count; z ++) {
items.push(ItemCtrl.getItemsByInfo(cfg.get)[0])
} }
let account = req.user let account = req.user
if (!account.moneys.has(MoneyTypeConst.CARD_SCROLL)) { const cfgMap = global.$cfg.get(BaseConst.ITEMCARD)
throw new ZError(101, '卷轴不足')
}
let money = account.moneys.get(MoneyTypeConst.CARD_SCROLL)
if (money < count) {
throw new ZError(101, '卷轴不足')
}
account.moneys.set(MoneyTypeConst.CARD_SCROLL, money - count)
// TODO: 根据配置的概率获取卡
let cardMap = global.$cfg.get(BaseConst.UNIT)
let cards: any[] = []
for (let [id, card] of cardMap) {
if (card.unittypei_id == 2) {
cards.push(card)
}
}
let cardsgetd: number[] = cards.randomGet(count).map((o: any) => o.id)
let totalCards = account.cards.union(cardsgetd)
let dulpSet = new Set(account.cards.intersect(cardsgetd))
let results: any = [] let results: any = []
let expHero = account.moneys.get(MoneyTypeConst.HERO_EXP) || 0 const cardMap = account.cardMap
//TODO: 根据配置设置每张卡分解后得到的经验 for (let item of items) {
const expPreCard = 10 if (item.type != ItemType.CARD) {
for (let id of cardsgetd) { results.push({
let data: any = { id } id: item.id,
if (dulpSet.has(id)) { used: 0,
data.isnew = false count: item.count
data.expdust = MoneyTypeConst.HERO_EXP });
data.dustcount = expPreCard continue
expHero += expPreCard }
} else { if (item.type == ItemType.CARD &&!cfgMap.has(item.id)) {
data.isnew = true error(`抽卡 ${item.id} 的配置不存在`)
continue
}
const data = cfgMap.get(item.id)
if (data.unlocking >= 30000 ) { // 英雄
for (let i = 0; i < item.count; i ++) {
let result = account.unlockHero(data.unlocking, data.unlockingtimes)
if (result == 1) {
await addHeroDefaultCardGroup(accountid, data.unlocking, cardMap)
}
if (result > 0) {
results.push({
id: item.id,
used: 1,
heroid: data.unlocking
})
} else {
results.push({
id: item.id,
used: 0
})
}
}
} else { // 随从卡
for (let i = 0; i < item.count; i ++) {
const result = account.unlockCard(data.unlocking, data.unlockingtimes)
if (result > 0) {
results.push({
id: item.id,
used: 1,
cardid: data.unlocking
})
} else {
results.push({
id: item.id,
used: 0,
})
}
}
} }
results.push(data)
} }
account.moneys.set(MoneyTypeConst.HERO_EXP, expHero)
account.cards = totalCards
await account.save() await account.save()
record.count -= count
await record.save()
return results return results
} }

View File

@ -7,6 +7,7 @@ import { Card } from '../models/subdoc/Card'
import { HeroCfg } from '../cfg/parsers/HeroCfg' import { HeroCfg } from '../cfg/parsers/HeroCfg'
import { Hero } from '../models/subdoc/Hero' import { Hero } from '../models/subdoc/Hero'
import { BagItem, ItemType } from '../models/BagItem' import { BagItem, ItemType } from '../models/BagItem'
import { addHeroDefaultCardGroup } from '../dao/CardGroupDao'
export default class HeroController extends BaseController { export default class HeroController extends BaseController {
@router('post /api/:accountid/heros') @router('post /api/:accountid/heros')
@ -20,7 +21,6 @@ export default class HeroController extends BaseController {
return heros return heros
} }
@router('post /api/:accountid/hero/unlock/:heroid')
@router('post /svr/:accountid/hero/unlock/:heroid') @router('post /svr/:accountid/hero/unlock/:heroid')
async unlockHero(req: any) { async unlockHero(req: any) {
let account = req.user let account = req.user
@ -30,36 +30,11 @@ export default class HeroController extends BaseController {
} }
let hero let hero
if (!type) { if (!type) {
let userMoney = !req.url.startsWith('/svr') hero = await account.unlockHero(heroid, 1)
hero = await account.unlockHero(heroid, userMoney)
// 将该英雄的默认卡组添加到玩家的卡组中, // 将该英雄的默认卡组添加到玩家的卡组中,
// 将默认卡组里的卡添加到玩家可用卡牌中 // 将默认卡组里的卡添加到玩家可用卡牌中
let cardMap = account.cardMap let cardMap = account.cardMap
let cfg = global.$cfg.get(BaseConst.HERO).get(parseInt(hero.heroid)) await addHeroDefaultCardGroup(account.id, hero.heroid, cardMap)
let cardgroup = new CardGroup({})
let cards: Card[] = []
for (let i = 1; i < 10; i++) {
if (!cfg[`follower${ i }id`]) {
break
}
const cardid = cfg[`follower${ i }id`]
const owned = cardMap.has(cardid)
const card = new Card()
card.cardid = cardid
card.owned = owned
card.ban = false
card.usetype = 0
card.free = !owned
card.free_expire = 0
card.time = Date.now()
cards.push(card)
}
cardgroup.accountid = account.id
cardgroup.heroid = hero.heroid
cardgroup.selected = false
cardgroup.isdefault = true
cardgroup.cards = cards
await cardgroup.save()
await account.save() await account.save()
} else { } else {
hero = await account.tryHero(heroid) hero = await account.tryHero(heroid)

28
src/dao/CardGroupDao.ts Normal file
View File

@ -0,0 +1,28 @@
import { BaseConst } from '../constants/BaseConst'
import { CardGroup } from '../models/CardGroup'
import { Card } from '../models/subdoc/Card'
export async function addHeroDefaultCardGroup(accountid: string, heroid: number, cardMap: Map<string, Card>) {
const heroCfg = global.$cfg.get(BaseConst.HERO).get(heroid)
let cardgroup = new CardGroup({})
let cards: Card[] = []
for (let i = 1; i <= 4; i++) {
const cardid = heroCfg[`follower${ i }id`]
const owned = cardMap.has(cardid)
const card = new Card()
card.cardid = cardid
card.owned = owned
card.ban = false
card.usetype = 0
card.free = !owned
card.free_expire = 0
card.time = Date.now()
cards.push(card)
}
cardgroup.accountid = accountid
cardgroup.heroid = heroCfg.id
cardgroup.selected = false
cardgroup.isdefault = true
cardgroup.cards = cards
await cardgroup.save()
}

View File

@ -148,61 +148,64 @@ class UserClass extends FindOrCreate {
return fc.get(70021).number + this.season_score * (fc.get(70020).number / 100 + twp) return fc.get(70021).number + this.season_score * (fc.get(70020).number / 100 + twp)
} }
public async unlockHero(heroid: number, useMoney: boolean) { public unlockHero(heroid: number, maxCount: number) {
if (this.heros.has(heroid + '')) { let hero = this.heros.get(heroid + '')
if (!this.heros.get(heroid + '').trial) { let result = 0
throw new ZError(102, '你已经解锁了该英雄') if (hero && !hero.trial && hero.count >= maxCount) {
} return result
} }
if (useMoney) { if (!hero) {
let money0 = MoneyTypeConst.getHeroShard(heroid) hero = new Hero()
let money1 = MoneyTypeConst.HERO_SHARD hero.heroid = heroid
let count0 = this.moneys.has(money0) ? this.moneys.get(money0) : 0 hero.free = false
let count1 = this.moneys.has(money1) ? this.moneys.get(money1) : 0 hero.trial = false
// TODO:: 根据配置获取解锁英雄需要的碎片数量 hero.level = 1
let needCount = 30 hero.trial_expire = 0
if (count0 + count1 < needCount) { hero.exp = 0
throw new ZError(102, '碎片数量不足') hero.slot = 1
} hero.count = 1
if (count0 > 0) { hero.time = Date.now()
let rest = needCount - count0 } else {
if (rest >= 0) { hero.count += 1
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() result = hero.count
hero.heroid = heroid
hero.free = false
hero.trial = false
hero.level = 1
hero.trial_expire = 0
hero.exp = 0
hero.slot = 1
hero.time = Date.now()
this.heros.set(heroid + '', hero) this.heros.set(heroid + '', hero)
return hero return result
}
public async unlockCard(cardid: number, maxCount: number) {
let card = this.cardMap.get(cardid + '')
let result = 0
if (card && card.count >= maxCount) {
return result
}
if (!card) {
const card = new Card()
card.cardid = cardid
card.owned = true
card.ban = false
card.usetype = 0
card.free = false
card.count = 0
card.free_expire = 0
card.time = Date.now()
} else {
card.count += 1
}
this.cardMap.set(card.cardid + '', card)
return card.count
} }
public async tryHero(heroid: number) { public async tryHero(heroid: number) {
if (this.heros.has(heroid + '')) { if (this.heros.has(heroid + '')) {
throw new ZError(102, '你已经解锁了该英雄') throw new ZError(102, '你已经解锁了该英雄')
} }
//TODO:: 根据配置查看该英雄是否可使用
let hero = new Hero() let hero = new Hero()
hero.heroid = heroid hero.heroid = heroid
hero.free = false hero.free = false
hero.trial = true hero.trial = true
hero.level = 1 hero.level = 1
hero.count = 0
hero.trial_expire = 0 hero.trial_expire = 0
hero.exp = 0 hero.exp = 0
this.heros.set(heroid + '', hero) this.heros.set(heroid + '', hero)

View File

@ -32,6 +32,13 @@ export class Card {
*/ */
@prop() @prop()
public free_expire: number public free_expire: number
/**
*
* @type {number}
*/
@prop({default: 1})
public count: number
/** /**
* *
* @type {number} * @type {number}
@ -47,7 +54,8 @@ export class Card {
usetype: this.usetype, usetype: this.usetype,
free: this.free, free: this.free,
free_expire: this.free_expire, free_expire: this.free_expire,
time: this.time time: this.time,
count: this.count
} }
} }
} }

View File

@ -31,10 +31,20 @@ export class Hero {
*/ */
@prop({default: 1}) @prop({default: 1})
public slot: number public slot: number
/**
*
* @type {number}
*/
@prop() @prop()
public time: number public time: number
/**
*
* @type {number}
*/
@prop({default: 1})
public count: number
public toJson() { public toJson() {
let data: any = { let data: any = {
heroid: this.heroid, heroid: this.heroid,
@ -46,7 +56,8 @@ export class Hero {
trial_expire: this.trial_expire, trial_expire: this.trial_expire,
slot: this.slot, slot: this.slot,
time: this.time, time: this.time,
ban: false ban: false,
count: this.count
} }
data.owned = !this.trial data.owned = !this.trial
return data return data