增加探索时, 奖励的生成配置
This commit is contained in:
parent
4e48150c1e
commit
c84fe2a8a4
0
configs/game.json
Normal file
0
configs/game.json
Normal file
14
docs/uaw.md
14
docs/uaw.md
@ -403,10 +403,16 @@ body:
|
|||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
score: 20, //获得积分数量
|
score: 20, //获得积分数量
|
||||||
chest: [{
|
chest: [{ // 结构同 18.宝箱列表
|
||||||
id: '1112323131', // 获得宝箱id
|
id: 1, // 箱子id
|
||||||
level: 1, //宝箱品级
|
stat: 0, // 0: 锁定, 1: 正常
|
||||||
}]
|
shareCode: '箱子的分享码',
|
||||||
|
level: 1, // 箱子品级
|
||||||
|
maxBonus: 10, // 最大可助力数量
|
||||||
|
scoreInit: 5, // 初始可获得积分
|
||||||
|
scoreBonus: 10, // 助力增加的分数
|
||||||
|
bonusCount: 2, // 已助力次数
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -16,3 +16,14 @@ export const CONFIRM_MAIL_HTML = `
|
|||||||
`
|
`
|
||||||
// 是否需要手动开启游戏
|
// 是否需要手动开启游戏
|
||||||
export const MANUAL_OPEN_GAME = true
|
export const MANUAL_OPEN_GAME = true
|
||||||
|
|
||||||
|
// 每一步能获得的最小分数
|
||||||
|
export const STEP_SCORE_MIN = 1
|
||||||
|
// 每一步能获得的最大分数
|
||||||
|
export const STEP_SCORE_MAX = 5
|
||||||
|
// 每一步能获得的宝箱的概率
|
||||||
|
export const STEP_CHEST_RATE = 0.1
|
||||||
|
// 宝箱各等级的概率
|
||||||
|
export const STEP_CHEST_LEVEL = [70, 85, 95, 100]
|
||||||
|
// 低保步数
|
||||||
|
export const RESET_STEP = 10
|
||||||
|
@ -6,30 +6,7 @@ import { rankKey, rankLevel, updateRankScore } from 'services/rank.svr'
|
|||||||
import { formatDate } from 'zutils/utils/date.util'
|
import { formatDate } from 'zutils/utils/date.util'
|
||||||
import { ScoreRecord } from 'models/ScoreRecord'
|
import { ScoreRecord } from 'models/ScoreRecord'
|
||||||
import { ChestRecord } from 'models/chain/ChestRecord'
|
import { ChestRecord } from 'models/chain/ChestRecord'
|
||||||
const chestCfg = require('../../configs/chest.json')
|
import { generateNewChest } from 'services/game.svr'
|
||||||
const chestLevelMap = new Map()
|
|
||||||
|
|
||||||
for (let cfg of chestCfg.chests) {
|
|
||||||
chestLevelMap.set(cfg.level, cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateNewChest = (uid: string, activity: string, level = 1, status = ChestStatusEnum.LOCKED) => {
|
|
||||||
let cfg = chestLevelMap.get(level)
|
|
||||||
if (!cfg) {
|
|
||||||
throw new ZError(11, 'chest cfg not found')
|
|
||||||
}
|
|
||||||
let scoreInit = Math.floor(Math.random() * (cfg.scoreMax - cfg.scoreMin + 1) + cfg.scoreMin)
|
|
||||||
let chest = new ActivityChest({
|
|
||||||
user: uid,
|
|
||||||
activity: activity,
|
|
||||||
level: level,
|
|
||||||
maxBounsCount: cfg.maxBounsCount,
|
|
||||||
bounsCfg: cfg.bounsCfg,
|
|
||||||
scoreInit,
|
|
||||||
status,
|
|
||||||
})
|
|
||||||
return chest
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 宝箱相关接口
|
* 宝箱相关接口
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { MANUAL_OPEN_GAME } from 'common/Constants'
|
import { MANUAL_OPEN_GAME, RESET_STEP } from 'common/Constants'
|
||||||
import { ActivityGame } from 'models/ActivityGame'
|
import { ActivityGame } from 'models/ActivityGame'
|
||||||
import { DAILY_SIGN, SIGN_TOTAL, TicketRecord, USE_TICKET } from 'models/TicketRecord'
|
import { DAILY_SIGN, SIGN_TOTAL, TicketRecord, USE_TICKET } from 'models/TicketRecord'
|
||||||
import { queryCheckInList } from 'services/chain.svr'
|
import { queryCheckInList } from 'services/chain.svr'
|
||||||
import { checkInToday, seqSignCfg, seqSignScore, totalSignCfg, totalSignScore } from 'services/sign.svr'
|
import { checkInToday, seqSignCfg, seqSignScore, totalSignCfg, totalSignScore } from 'services/sign.svr'
|
||||||
import { ZError, SyncLocker, ZRedisClient, BaseController, ROLE_ANON, role, router } from 'zutils'
|
import { ZError, SyncLocker, BaseController, router } from 'zutils'
|
||||||
import { formatDate } from 'zutils/utils/date.util'
|
import { formatDate } from 'zutils/utils/date.util'
|
||||||
const chestCfg = require('../../configs/chest.json')
|
import { mongoose } from '@typegoose/typegoose'
|
||||||
|
import { generateChestLevel, generateNewChest, generateStepReward } from 'services/game.svr'
|
||||||
|
import { ChestStatusEnum } from 'models/ActivityChest'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 探索游戏相关接口
|
* 探索游戏相关接口
|
||||||
*/
|
*/
|
||||||
@ -193,27 +196,48 @@ class GameController extends BaseController {
|
|||||||
throw new ZError(11, 'invalid step')
|
throw new ZError(11, 'invalid step')
|
||||||
}
|
}
|
||||||
step = parseInt(step)
|
step = parseInt(step)
|
||||||
|
const session = await mongoose.startSession()
|
||||||
|
session.startTransaction()
|
||||||
|
try {
|
||||||
|
const record = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}).session(session)
|
||||||
|
if (MANUAL_OPEN_GAME && record.status === 0) {
|
||||||
|
throw new ZError(12, 'map not open')
|
||||||
|
}
|
||||||
|
if (record.tickets < step) {
|
||||||
|
throw new ZError(13, 'insufficient tickets')
|
||||||
|
}
|
||||||
|
record.tickets -= step
|
||||||
|
const ticketRecord = new TicketRecord({
|
||||||
|
user: user.id,
|
||||||
|
activity: user.activity,
|
||||||
|
type: USE_TICKET,
|
||||||
|
data: {},
|
||||||
|
score: -step,
|
||||||
|
})
|
||||||
|
let { score, chests } = generateStepReward(user.id, user.activity, step)
|
||||||
|
if (chests.length > 0) {
|
||||||
|
record.maxNoChestCount = 0
|
||||||
|
} else {
|
||||||
|
record.maxNoChestCount += step
|
||||||
|
if (record.maxNoChestCount >= RESET_STEP) {
|
||||||
|
record.maxNoChestCount = 0
|
||||||
|
const level = generateChestLevel()
|
||||||
|
chests.push(generateNewChest(user.id, user.activity, level, ChestStatusEnum.NORMAL))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let chest of chests) {
|
||||||
|
await chest.save({ session })
|
||||||
|
}
|
||||||
|
await ticketRecord.save({ session })
|
||||||
|
await record.save()
|
||||||
|
await session.commitTransaction()
|
||||||
|
|
||||||
const record = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {})
|
return { score, chests: chests.map(chest => chest.toJson()) }
|
||||||
if (MANUAL_OPEN_GAME && record.status === 0) {
|
} catch (e) {
|
||||||
throw new ZError(12, 'map not open')
|
session.abortTransaction()
|
||||||
|
throw e
|
||||||
|
} finally {
|
||||||
|
session.endSession()
|
||||||
}
|
}
|
||||||
if (record.tickets < step) {
|
|
||||||
throw new ZError(13, 'insufficient tickets')
|
|
||||||
}
|
|
||||||
record.tickets -= step
|
|
||||||
// TODO:: 生成奖励, 存入data, 并返回
|
|
||||||
const ticketRecord = new TicketRecord({
|
|
||||||
user: user.id,
|
|
||||||
activity: user.activity,
|
|
||||||
type: USE_TICKET,
|
|
||||||
data: {},
|
|
||||||
score: -step,
|
|
||||||
})
|
|
||||||
await ticketRecord.save()
|
|
||||||
await record.save()
|
|
||||||
let result = []
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ class ActivityGameClass extends BaseModule {
|
|||||||
@prop()
|
@prop()
|
||||||
public lastSignDay: string
|
public lastSignDay: string
|
||||||
|
|
||||||
|
// 最大宝箱无宝箱步数
|
||||||
|
@prop()
|
||||||
|
public maxNoChestCount: number
|
||||||
|
|
||||||
public toJson() {
|
public toJson() {
|
||||||
return {
|
return {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
55
src/services/game.svr.ts
Normal file
55
src/services/game.svr.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { STEP_CHEST_LEVEL, STEP_CHEST_RATE, STEP_SCORE_MAX, STEP_SCORE_MIN } from 'common/Constants'
|
||||||
|
import { ActivityChest, ChestStatusEnum } from 'models/ActivityChest'
|
||||||
|
import { ZError } from 'zutils'
|
||||||
|
|
||||||
|
const chestCfg = require('../../configs/chest.json')
|
||||||
|
const chestLevelMap = new Map()
|
||||||
|
|
||||||
|
for (let cfg of chestCfg.chests) {
|
||||||
|
chestLevelMap.set(cfg.level, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateNewChest = (uid: string, activity: string, level = 1, status = ChestStatusEnum.LOCKED) => {
|
||||||
|
let cfg = chestLevelMap.get(level)
|
||||||
|
if (!cfg) {
|
||||||
|
throw new ZError(11, 'chest cfg not found')
|
||||||
|
}
|
||||||
|
let scoreInit = Math.floor(Math.random() * (cfg.scoreMax - cfg.scoreMin + 1) + cfg.scoreMin)
|
||||||
|
let chest = new ActivityChest({
|
||||||
|
user: uid,
|
||||||
|
activity: activity,
|
||||||
|
level: level,
|
||||||
|
maxBounsCount: cfg.maxBounsCount,
|
||||||
|
bounsCfg: cfg.bounsCfg,
|
||||||
|
scoreInit,
|
||||||
|
status,
|
||||||
|
})
|
||||||
|
return chest
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateChestLevel = function (): number {
|
||||||
|
const levelDefine = STEP_CHEST_LEVEL
|
||||||
|
let randomLevel = Math.floor(Math.random() * levelDefine[levelDefine.length - 1])
|
||||||
|
let level = 1
|
||||||
|
for (let i = 0; i < levelDefine.length; i++) {
|
||||||
|
if (randomLevel < levelDefine[i]) {
|
||||||
|
level = i + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return level
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateStepReward = (uid: string, activity: string, step: number) => {
|
||||||
|
let score = 0
|
||||||
|
let chests = []
|
||||||
|
for (let i = 0; i < step; i++) {
|
||||||
|
score += Math.floor(Math.random() * (STEP_SCORE_MAX - STEP_SCORE_MIN + 1) + STEP_SCORE_MIN)
|
||||||
|
if (Math.random() < STEP_CHEST_RATE) {
|
||||||
|
let randomLevel = generateChestLevel()
|
||||||
|
let chest = generateNewChest(uid, activity, randomLevel, ChestStatusEnum.NORMAL)
|
||||||
|
chests.push(chest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { score, chests }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user