商店:基础数据及购买

This commit is contained in:
luying
2022-07-25 17:41:04 +08:00
parent 4bf75fcda5
commit 4cf4511ee7
13 changed files with 952 additions and 565 deletions

View File

@@ -56,6 +56,7 @@ export enum ACTIVITY_TYPE {
TIME_LIMIT_RANK = 41, // 限时排行榜
TASK_PASS = 42, // 战令活动
GUILD_PAY = 43, // 军团充值人数
SHOP = 44, // 限时商店
}
/**

View File

@@ -493,7 +493,7 @@ export const FILENAME = {
DIC_CITY_ACTIVITY_REWARD: 'dic_zyz_cityActivityReward',
DIC_RACE_ACTIVITY: 'dic_zyz_raceActivity',
DIC_SHOP: 'dic_zyz_shop',
DIC_SHOP_LIST: 'dic_zyz_shopList',
DIC_SHOP_TYPE: 'dic_zyz_shopType',
DIC_RANK: 'dic_zyz_rankingType',
DIC_RANK_REWARD: 'dic_zyz_rankingReward',
DIC_MAIN_TASK: 'dic_zyz_mainTask',

View File

@@ -3,7 +3,6 @@ import { index, getModelForClass, prop, DocumentType, modelOptions } from '@type
import { genCode } from '../pubUtils/util';
import { getZeroPointD } from '../pubUtils/timeUtil';
import { SHOP_REFRESH_TYPE } from '../consts';
import { DicShop } from '../pubUtils/dictionary/DicShop';
/**
* 玩家购买商店记录表,每个商品一条,每次刷新新建一条
@@ -22,7 +21,13 @@ export default class UserShop extends BaseModel {
roleName: string; // 玩家名
@prop({ required: true })
shopId: number; // 商店id
activityId: number; // 商店id
@prop({ required: true })
shop: number; // 商店id
@prop({ required: true })
type: number; // 商店页签id
@prop({ required: true })
itemId: number; // 商品id
@@ -50,36 +55,34 @@ export default class UserShop extends BaseModel {
}
public static async findByShopId(roleId: string, shopId: number) {
public static async findByShopType(roleId: string, shopId: number, typeId: number) {
let timeCondition = this.getRefreshCondition();
let rec: UserShopType[] = await UserShopModel.find({ shopId, roleId, $or: timeCondition }).lean();
let rec: UserShopType[] = await UserShopModel.find({ shopId, typeId, roleId, $or: timeCondition }).lean();
return rec;
}
public static async findMapByShopId(roleId: string, shopId: number) {
let rec = await this.findByShopId(roleId, shopId);
let map = new Map<number, UserShopType>();
for(let userShop of rec) {
map.set(userShop.itemId, userShop);
}
return map
}
public static async findByRoleAndItem(roleId: string, itemId: number) {
public static async findByRoleId(roleId: string) {
let timeCondition = this.getRefreshCondition();
let rec: UserShopType = await UserShopModel.findOne({ roleId, itemId, $or: timeCondition }).lean();
let rec: UserShopType[] = await UserShopModel.find({ roleId, $or: timeCondition }).lean();
return rec;
}
public static async purchase(roleId: string, roleName: string, dicShopItem: DicShop, inc: number) {
public static async findByRoleAndItem(roleId: string, activityId: number, dicShopItem: { id: number, shop: number, type: number }) {
let timeCondition = this.getRefreshCondition();
let { id, shop, type } = dicShopItem;
let rec: UserShopType = await UserShopModel.findOne({ roleId, itemId: id, shop, type, activityId, $or: timeCondition }).lean();
return rec;
}
public static async purchase(roleId: string, roleName: string, activityId: number, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number }, inc: number) {
let code = genCode(8);
let timeCondition = this.getRefreshCondition();
let { id, goodid, refreshType, shop } = dicShopItem;
let { id, goodId, refreshType, shop, type } = dicShopItem;
let rec: UserShopType = await UserShopModel.findOneAndUpdate(
{ roleId, itemId: id, $or: timeCondition },
{ $setOnInsert: { roleName, code, goodId: goodid, refreshType, shopId: shop }, $inc: { count: inc } },
{ roleId, itemId: id, $or: timeCondition, activityId, shop, type },
{ $setOnInsert: { roleName, code, goodId, refreshType }, $inc: { count: inc } },
{ new: true, upsert: true }
).lean();
return rec;

View File

@@ -1,17 +1,134 @@
import { SHOP_REFRESH_TYPE } from "../../consts";
import { ActivityModelType } from "../../db/Activity";
import { UserShopType } from "../../db/UserShop";
import { ActivityBase } from "../activityField/activityField";
// hero表内属性基础格式
export class ShopItemListParam {
interface ShopInDb {
shop: number;
type: number;
list: ShopItemInDb[];
}
interface ShopItemInDb {
id: number;
goodId: number;
goodName: string;
guildLvLimit: number;
lvLimit: number;
purchaseLimit: number;
vipPurchaseLimit: number;
refreshType: number;
money: number;
price: string;
productID: string;
chosen: number;
indirectId: number;
createTime: number;
beginTime: number;
endTime: number;
}
export class ShopData extends ActivityBase {
shop: number;
type: number;
list: ShopDicData[] = [];
constructor(activityData: ActivityModelType, createTime: number, serverTime: number) {
super(activityData, createTime, serverTime)
this.initData(activityData.data)
}
public initData(data: string) {
let result: ShopInDb = JSON.parse(data);
if(result) {
this.shop = result.shop;
this.type = result.type;
for (let obj of result.list) {
this.list.push(new ShopDicData(obj))
}
}
}
public findByItemId(itemId: number) {
let item = this.list.find(cur => cur.id == itemId);
if(!item) return null;
return {...item, shop: this.shop, type: this.type};
}
}
export class ShopDicData {
isNew: boolean = false;
id: number;
goodId: number;
goodName: string;
guildLvLimit: number;
lvLimit: number;
purchaseLimit: number;
vipPurchaseLimit: number;
refreshType: SHOP_REFRESH_TYPE;
money: number;
price: string;
productID: string = '';
chosen: number;
indirectId: number;
createTime: number;
beginTime: number;
endTime: number;
constructor(obj: ShopItemInDb) {
this.id = obj.id;
this.goodId = obj.goodId;
this.goodName = obj.goodName;
this.guildLvLimit = obj.guildLvLimit;
this.lvLimit = obj.lvLimit;
this.purchaseLimit = obj.purchaseLimit;
this.vipPurchaseLimit = obj.vipPurchaseLimit;
this.refreshType = obj.refreshType;
this.money = obj.money;
this.price = obj.price;
this.productID = obj.productID;
this.chosen = obj.chosen;
this.indirectId = obj.indirectId;
this.createTime = obj.createTime;
this.beginTime = obj.beginTime;
this.endTime = obj.endTime;
}
}
export class ShopReturnData {
activityId: number = 0;
shop: number;
type: number;
dic: ShopDicData[] = [];
records: ShopReturnRecordData[] = [];
constructor(shop: number, type: number) {
this.shop = shop;
this.type = type;
}
public setDicByActivity(activityData: ShopData) {
if(!activityData || activityData.shop != this.shop || activityData.type != this.type) return;
this.activityId = activityData.activityId;
this.dic.push(...activityData.list)
}
public setUserRecords(record: UserShopType) {
if(!record || record.shop != this.shop || record.type != this.type) return;
let recordResult = new ShopReturnRecordData(record);
if(recordResult && recordResult.shopItemId) this.records.push(recordResult)
}
}
export class ShopReturnRecordData {
shopItemId: number;
discount: number;
typeId: number;
buyCount: number;
order: number;
constructor(shopItemId: number, discount: number, typeId: number, buyCount: number, order: number) {
this.shopItemId = shopItemId;
this.discount = discount;
this.typeId = typeId;
this.buyCount = buyCount;
this.order = order;
constructor(record: UserShopType) {
if(!record) return;
this.shopItemId = record.itemId;
this.buyCount = record.count;
}
}

View File

@@ -59,8 +59,8 @@ import { GUILDACTIVITY, RECRUIT } from "./dicParam";
import * as param from "./dicParam";
import { decodeIdCntArrayStr, parseGoodStr, decodeArrayListStr, getRandEelm, readTsFile, getRandEelmWithWeight } from "./util";
import { RACE_EVENT_TYPE } from "../consts";
import { dicShop, dicShopItem, loadShop } from "./dictionary/DicShop";
import { dicShopList, loadShopList } from "./dictionary/DicShopList";
import { dicShopByType, dicShopItem, loadShop } from "./dictionary/DicShop";
import { dicShopType, loadShopType } from "./dictionary/DicShopType";
import { dicRank, loadRank } from "./dictionary/DicRank";
import { dicRankReward, loadRankReward } from "./dictionary/DicRankReward";
import { dicTaskType, taskMap, dicMainTask, dicDailyTask, dicAchievement, loadTask, dicPvpDailyTask } from "./dictionary/DicTask";
@@ -198,9 +198,9 @@ export const gameData = {
raceActivityEncounter: { events: new Map<number, number>(), eventNum: 0 },
raceNormalItems: new Array<{id: number, total: number, max: number}>(),
raceEventItems: new Array<{id: number, count: number}>(),
shop: dicShop,
shopItemByType: dicShopByType,
shopItem: dicShopItem,
shopList: dicShopList,
shopType: dicShopType,
rank: dicRank,
generalRankReward: dicRankReward,
taskType: dicTaskType,
@@ -1010,6 +1010,15 @@ export function getLadderRankReward(myRank: number) {
return null
}
export function hasShopType(shop: number, type: number) {
return gameData.shopType.has(`${shop}_${type}`);
}
export function getShopType(shop: number, type: number) {
let key = `${shop}_${type}`;
return gameData.shopType.get(key)||null;
}
// 初始加载
function initDatas() {
parseDicParam();
@@ -1138,7 +1147,7 @@ function loadDatas() {
loadCityActivityReward();
loadRaceActivity();
loadShop();
loadShopList();
loadShopType();
loadRank();
loadRankReward();
loadTask();

View File

@@ -7,9 +7,9 @@ export interface DicShop {
// 商品id
readonly id: number;
// 物品表id
readonly goodid: number;
readonly goodId: number;
// 物品表名
readonly goodname: number;
readonly goodName: number;
// 商店id 对应 dic_zyz_shoplist的id
readonly shop: number;
// 商店标签 对应 dic_zyz_shopType的id
@@ -17,7 +17,7 @@ export interface DicShop {
// 军团等级需求
readonly guildLvLimit: number;
// 玩家等级需求
readonly lvlimit: number;
readonly lvLimit: number;
// 购买次数限制
readonly purchaseLimit: number;
// vip购买次数限制
@@ -27,26 +27,27 @@ export interface DicShop {
// 用于购买的货币
readonly money: number;
// 价格
readonly price: number;
readonly price: string;
}
export const dicShopItem = new Map<number, DicShop>(); // itemid => DicShop
export const dicShop = new Map<number, DicShop[]>(); // shop => DicShop[]
export const dicShopByType = new Map<string, { shop: number, type: number, items: DicShop[] }>(); // shop + type => DicShop[]
export function loadShop() {
dicShopItem.clear();
dicShop.clear();
dicShopByType.clear();
let arr = readFileAndParse(FILENAME.DIC_SHOP);
arr.forEach(o => {
o.guildLvLimit = o.guildlvlimit == '&'?0: o.guildlvlimit;
o.lvlimit = o.lvlimit == '&'?0: o.lvlimit;
o.purchaseLimit = o.purchaselimit == '&'?-1: (o.purchaselimit||0);
o.vipPurchaseLimit = o.vipPurchaseLimit == '&'?-1: (o.vipPurchaseLimit||0);
if(!dicShop.has(o.shop)) {
dicShop.set(o.shop, [o]);
o.guildLvLimit = o.guildLvLimit == '&'?0: o.guildLvLimit;
o.lvLimit = o.lvLimit == '&'?0: o.lvLimit;
o.purchaseLimit = o.purchaseLimit == '&'?-1: (o.purchaseLimit||0);
o.vipPurchaseLimit = o.vipPurchaseLimit == '&'? 0: (o.vipPurchaseLimit||0);
let key = `${o.shop}_${o.type}`;
if(!dicShopByType.has(key)) {
dicShopByType.set(key, { shop: o.shop, type: o.type, items: [] });
} else {
dicShop.get(o.shop).push(o);
dicShopByType.get(key).items.push(o);
}
dicShopItem.set(o.id, o);
});

View File

@@ -1,28 +0,0 @@
// 商店表
import { readFileAndParse, parseNumberList } from '../util'
import { FILENAME } from '../../consts'
export interface DicShopList {
// 商店id
readonly shopid: number;
// 商店名
readonly shopname: number;
// 商店内标签,小分类
readonly type: number[];
// 使用的货币
readonly money: number[];
}
export const dicShopList = new Map<number, DicShopList>();
export function loadShopList() {
dicShopList.clear();
let arr = readFileAndParse(FILENAME.DIC_SHOP_LIST);
arr.forEach(o => {
o.type = parseNumberList(o.typeid);
o.money = parseNumberList(o.moneyid);
dicShopList.set(o.shopid, o);
});
arr = undefined;
}

View File

@@ -0,0 +1,26 @@
// 商店表
import { readFileAndParse } from '../util'
import { FILENAME } from '../../consts'
export interface DicShopType {
// 商店id
readonly shop: number;
// 商店内标签,小分类
readonly type: number;
// 是否限时
readonly isLimit: boolean;
}
export const dicShopType = new Map<string, DicShopType>(); // shop+type => DicShopType
export function loadShopType() {
dicShopType.clear();
let arr = readFileAndParse(FILENAME.DIC_SHOP_TYPE);
arr.forEach(o => {
o.type = o.typeid;
if(o.shop != '&') {
dicShopType.set(`${o.shop}_${o.type}`, o);
}
});
arr = undefined;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +1,146 @@
[
{
"id": 1,
"typeid": 1,
"name": "武器"
"name": "武器",
"shop": "&",
"isLimit": 0,
"openLimit": "&"
},
{
"id": 2,
"typeid": 2,
"name": "宝石"
"name": "宝石",
"shop": 7,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 3,
"typeid": 3,
"name": "藏宝图"
"name": "藏宝图",
"shop": 6,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 4,
"typeid": 4,
"name": "精魄"
"name": "精魄",
"shop": "&",
"isLimit": 0,
"openLimit": "&"
},
{
"id": 5,
"typeid": 5,
"name": "奇珍"
"name": "奇珍",
"shop": 1,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 6,
"typeid": 6,
"name": "防具"
"name": "防具",
"shop": "&",
"isLimit": 0,
"openLimit": "&"
},
{
"id": 7,
"typeid": 7,
"name": "臻选"
"name": "臻选",
"shop": 5,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 8,
"typeid": 9,
"name": "将魂回收"
"name": "将魂回收",
"shop": 8,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 9,
"typeid": 10,
"name": "将魂兑换"
"name": "将魂兑换",
"shop": 8,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 10,
"typeid": 11,
"name": "图纸"
"name": "图纸",
"shop": 7,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 11,
"typeid": 12,
"name": "竞技"
"name": "竞技",
"shop": 5,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 12,
"typeid": 13,
"name": "名将擂台",
"shop": 4,
"isLimit": 0,
"openLimit": "0&124"
},
{
"id": 13,
"typeid": 14,
"name": "擂台限定",
"shop": 4,
"isLimit": 0,
"openLimit": "0&124"
},
{
"id": 14,
"typeid": 15,
"name": "巅峰演武",
"shop": 4,
"isLimit": 0,
"openLimit": "50&"
},
{
"id": 15,
"typeid": 11,
"name": "图纸",
"shop": 2,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 16,
"typeid": 5,
"name": "奇珍",
"shop": 2,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 17,
"typeid": 5,
"name": "奇珍",
"shop": 3,
"isLimit": 0,
"openLimit": "&"
},
{
"id": 18,
"typeid": 16,
"name": "限时",
"shop": 5,
"isLimit": 1,
"openLimit": "&"
}
]