✨ feat(宝物): 添加宝物系统

This commit is contained in:
luying
2022-12-08 15:49:51 +08:00
parent b684307818
commit a83deeff5f
46 changed files with 15656 additions and 54 deletions
+107 -5
View File
@@ -1,11 +1,12 @@
import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE, ABI_TYPE_MAIN, LINEUP_NUM, SEID_TYPE, TALENT_RELATION_TYPE } from "../../consts";
import { ArtifactModelType } from "../../db/Artifact";
import { Connect, EPlace, HeroSkin, HeroType, HeroUpdate, Stone, Talent } from "../../db/Hero";
import { JewelType } from "../../db/Jewel";
import { RoleUpdate, Teraph } from "../../db/Role";
import { AttrCell, Attribute, EquipAttr, HeroAttr, RoleCeType, SchoolAttr, ScrollAttr } from "../../db/RoleCe";
import { TopHero } from "../../domain/dbGeneral";
import { AttributeCal } from "../../domain/roleField/attribute";
import { gameData, getEquipQualityIdByEquipIdAndPoint, getEquipStarAttrByStage, getEquipStrenthenAttr, getEquipSuitByHero, getFriendShipByIdAndLv, getHeroStarByQuality, getHeroWakeByQuality, getJewelConditionByLvAndSeId, getJobByGradeAndClass, getSchoolRateByStar, getScollByStar, getTeraph } from "../../pubUtils/data";
import { gameData, getDicArtifactLvByPlanId, getEquipQualityIdByEquipIdAndPoint, getEquipStarAttrByStage, getEquipStrenthenAttr, getEquipSuitByHero, getFriendShipByIdAndLv, getHeroStarByQuality, getHeroWakeByQuality, getJewelConditionByLvAndSeId, getJobByGradeAndClass, getSchoolRateByStar, getScollByStar, getTeraph } from "../../pubUtils/data";
import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool";
import { DicSe } from "../../pubUtils/dictionary/DicSe";
import { addToMap, deepCopy } from "../../pubUtils/util";
@@ -45,13 +46,13 @@ export class CalCe {
let lv = this.data.heroLv.get(hid)||1;
for(let attrId = ABI_TYPE.ABI_HP; attrId < ABI_TYPE.ABI_MAX; attrId++) {
if(!this.data.heroAttrs.has(`${hid}_${attrId}`) && !this.data.globalAttrs.has(attrId)) continue;
let { mainBase = 0, mainBaseUp = 0, subBase = 0, job = 0, starUp = 0, connect = 0, talent = 0, equipQuality = 0, equipStrength = 0, equipStar = 0, equipSuit = 0, jewel = 0, stone = 0 } = this.data.heroAttrs.get(`${hid}_${attrId}`)||{};
let { mainBase = 0, mainBaseUp = 0, subBase = 0, job = 0, starUp = 0, connect = 0, talent = 0, equipQuality = 0, equipStrength = 0, equipStar = 0, equipSuit = 0, jewel = 0, stone = 0, artifactLv = 0, artifactQuality = 0, artifactSeid = 0 } = this.data.heroAttrs.get(`${hid}_${attrId}`)||{};
let { school = 0, teraph = 0, title = 0, scroll = 0, skin = 0 } = this.data.getGlobalAttrById(attrId)||{};
let val = 0, str = '';
if(ABI_TYPE_MAIN.indexOf(attrId) != -1) {
// {[ hp1 + lv * hp2 ] * ( 1 + hp5 ) + [( hp6 + hp7 ) * ( 1 + hp8 )]} * ( 1 + hp9 ) + hp10 + hp11
val = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 ) + stone + teraph + title + scroll;
str += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100 )+${stone}+${teraph}+${title}+${scroll}`;
// {[ hp1 + lv * hp2 ] * ( 1 + hp5 ) + [( hp6 + hp7 ) * ( 1 + hp8 )]} * ( 1 + hp9 ) + hp10 + hp11 + hp14
val = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 + artifactSeid/100) + stone + teraph + title + scroll + artifactLv + artifactQuality;
str += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100+${artifactSeid}/100)+${stone}+${teraph}+${title}+${scroll}+${artifactLv}+${artifactQuality}`;
} else {
// attr1 + attr2 + attr4 + attr5 + attr6 + attr7 + attr9
val = subBase + job + teraph + school + title + jewel + equipStar;
@@ -511,6 +512,86 @@ export class CalCe {
}
}
// 卸下宝物
public setPutOffArtifact(hid: number) {
this.data.clearHeroAttrByHid(hid, 'artifactLv');
this.data.clearHeroAttrByHid(hid, 'artifactQuality');
this.data.clearHeroAttrByHid(hid, 'artifactSeid');
}
// 装备宝物
public setPutArtifact(hid: number, skinId: number, job: number, artifact: ArtifactModelType) {
this.data.clearHeroAttrByHid(hid, 'artifactLv');
this.data.clearHeroAttrByHid(hid, 'artifactQuality');
this.data.clearHeroAttrByHid(hid, 'artifactSeid');
if(artifact) {
this.setArtifactLv(hid, artifact.artifactId, artifact.lv);
this.setArtifactQuality(hid, artifact.artifactId);
this.setArtifactSeid(hid, skinId, job, artifact.lv);
}
}
// 宝物等级
public setArtifactLv(hid: number, artifactId: number, lv: number) {
this.data.clearHeroAttrByHid(hid, 'artifactLv');
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return;
let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv);
if(!dicArtifactLv) return;
let ceAttr = dicArtifactLv.attr||[];
for(let { id, attr } of ceAttr) {
let heroAttr = this.data.getHeroAttrByHidAndId(hid, id);
heroAttr.artifactLv = attr;
}
}
// 宝物品质
public setArtifactQuality(hid: number, artifactId: number) {
this.data.clearHeroAttrByHid(hid, 'artifactQuality');
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return;
// 基础属性
let dicArtifactQualityPlan = gameData.artifactQualityPlan.get(dicArtifact.qualityAttrPlan);
if(!dicArtifactQualityPlan) return;
let ceAttr = dicArtifactQualityPlan.attr||[];
for(let { id, attr } of ceAttr) {
let heroAttr = this.data.getHeroAttrByHidAndId(hid, id);
heroAttr.artifactQuality = attr;
}
}
// 宝物词条
public setArtifactSeid(hid: number, skinId: number, job: number, artifactId: number) {
this.data.clearHeroAttrByHid(hid, 'artifactSeid');
let dicArtifact = gameData.artifact.get(artifactId);
if(!dicArtifact) return;
let dicJob = gameData.job.get(job);
if(!dicJob) return;
let seids: number[] = []; // id, seids
for(let seid of dicArtifact.seids) {
let dicArtifactSeid = gameData.artifactSeid.get(seid);
if(!dicArtifactSeid) continue;
if(dicArtifactSeid.jobClass != 0 && dicArtifactSeid.jobClass != dicJob.job_class) continue;
if(dicArtifactSeid.hid != 0 && dicArtifactSeid.hid != skinId) continue;
if(dicArtifactSeid.quality > dicArtifact.quality) continue;
seids.push(dicArtifactSeid.seid);
}
let { ratioUp } = this.addSeidEffect(seids);
for(let [attrId, val] of ratioUp) {
let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId);
heroAttr.artifactSeid = val;
}
}
// 添加技能增加的被动属性
private addSeidEffect(seidList: number[]) {
let fixUp = new Map<number, number>(), ratioUp = new Map<number, number>();
@@ -991,6 +1072,9 @@ abstract class HeroAllAttr {
jewel: number = 0; // hp9 & attr7,天晶随机属性值(jewel的ranSe,对应dic_zyz_randomEffectPool)
stone: number = 0; // hp10, 地玉增加的固定值(dic_zyz_stone的attribute)
mainBaseUp: number = 0; // hp2, 基础成长(dic_zyz_hero的hp_up)
artifactLv: number = 0; // hp14 宝物等级(dic_zyz_artifactLvPlan的attr)
artifactQuality: number = 0; // hp14 宝物品质(dic_zyz_artifactQualityPlan的attr)
artifactSeid: number = 0; // hp9 宝物词条(dic_zyz_artifactSeid算出来的)
constructor(hid: number, attrId: number, ) {
this.hid = hid;
@@ -1041,6 +1125,12 @@ class HeroMainAttr extends HeroAllAttr {
this.stone = value; break;
case HERO_MAIN_ATTR_INDEX.BASE_UP:
this.mainBaseUp = value; break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV:
this.artifactLv = value; break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY:
this.artifactQuality = value; break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID:
this.artifactSeid = value; break;
}
}
}
@@ -1089,6 +1179,15 @@ class HeroMainAttr extends HeroAllAttr {
case HERO_MAIN_ATTR_INDEX.BASE_UP:
values.push(this.mainBaseUp);
break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV:
values.push(this.artifactLv);
break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY:
values.push(this.artifactQuality);
break;
case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID:
values.push(this.artifactSeid);
break;
}
}
return values;
@@ -1278,6 +1377,9 @@ enum HERO_MAIN_ATTR_INDEX {
JEWEL = 10, // hp9,天晶随机属性值(jewel的ranSe,对应dic_zyz_randomEffectPool)
STONE = 11, // hp10, 地玉增加的固定值(dic_zyz_stone的attribute)
BASE_UP = 12, // hp2, 角色基础属性成长(dic_zyz_hero的hp_up)
ARTIFACT_LV = 13, // hp14, 宝物等级
ARTIFACT_QUALITY = 14, // hp14, 宝物品质
ARTIFACT_SEID = 15, // hp9,宝物词条
END
}
+87 -19
View File
@@ -1,23 +1,18 @@
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE } from '../../consts';
import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandSingleEelm, getRandValueByMinMax, resResult } from '../../pubUtils/util';
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE } from '../../consts';
import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandValueByMinMax, } from '../../pubUtils/util';
import { RoleModel, RoleType } from '../../db/Role';
import { setAp } from '../actionPointService';
import { ItemModel, ItemType } from '../../db/Item';
import { STATUS } from '../../consts/statusCode';
import { pinus } from 'pinus';
import { ItemInter, RewardInter, } from '../../pubUtils/interface';
import { gameData } from '../../pubUtils/data';
import { ItemModel, } from '../../db/Item';
import { ItemInter, } from '../../pubUtils/interface';
import { gameData, getDefArtifactByGid } from '../../pubUtils/data';
import { uniq } from 'underscore';
import { EPlace, HeroModel, HeroType, HeroUpdate } from '../../db/Hero';
import { EPlace, HeroModel, HeroType, } from '../../db/Hero';
import { Figure } from '../../domain/dbGeneral';
import { CreateHeroParam, HeroShowParam, JewelParam } from '../../domain/roleField/hero';
import { ArtifactParam, JewelParam } from '../../domain/roleField/hero';
import { HeroSkin } from '../../db/Hero';
import { errlogger } from '../../util/logger';
import { BAG } from '../../pubUtils/dicParam';
import { sendMailByContent } from '../mailService';
import { SkinModel, SkinUpdate } from '../../db/Skin';
import { getInitHeroById } from '../roleService';
import { getActivities } from '../activity/activityService';
import { SkinModel, } from '../../db/Skin';
import { reportTAEvent, reportTAUserSet } from '../sdkService';
import { saveCoinChangeLog, saveFigureInfoLog, saveGoldChangeLog, saveItemChangeLog } from '../../pubUtils/logUtil';
import { JewelModel, JewelType, jewelUpdate, RandSe } from '../../db/Jewel';
@@ -25,16 +20,17 @@ import { updateEplaces } from '../equipService';
import { combineItems, getCoinEventProperties, getGoldEventProperties, sortItems } from './util';
import { nowSeconds } from '../../pubUtils/timeUtil';
import { calculateCeWithHero, calculateCeWithRole } from '../playerCeService';
import { sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from '../pushService';
import { sendMessageToUserWithSuc } from '../pushService';
import { filterGoods } from '../dataService';
import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from '../../db/Artifact';
export async function handleCost(roleId: string, sid: string, goods: Array<ItemInter>, reason: ITEM_CHANGE_REASON) {
let { items, jewels, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
let { items, jewels, gold, coin, artifacts } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
let jewelSeqIds = jewels.map(cur => cur.seqId);
let resJewels: JewelType[] = [];
let artifactSeqIds = artifacts.map(cur => cur.seqId);
let resArtifacts: ArtifactModelType[] = [];
// 检查货币是否充足
let role = await RoleModel.findByRoleId(roleId);
@@ -50,6 +46,12 @@ export async function handleCost(roleId: string, sid: string, goods: Array<ItemI
if (resJewels.length < jewels.length)
return false;
}
//检查宝物是否存在
if (artifacts.length > 0) {
resArtifacts = await ArtifactModel.findbySeqIds(roleId, artifactSeqIds);
if (resArtifacts.length < artifacts.length)
return false;
}
//检查并修改道具
if (items.length > 0) {
let { hasError, result } = await ItemModel.decreaseItems(roleId, items);
@@ -90,6 +92,25 @@ export async function handleCost(roleId: string, sid: string, goods: Array<ItemI
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_DEL, { jewels: jewels.map(jewel => ({ seqId: jewel.seqId, id: jewel.id, inc: -1, reason })) }, sid);
}
//删除宝物
if (resArtifacts.length > 0) {
let heroMap = new Map<number, { artifact: ArtifactModelType}>();
for(let artifact of resArtifacts) {
if(artifact.hid > 0) {
heroMap.set(artifact.hid, { artifact });
}
}
for(let [hid, { artifact } ] of heroMap) {
// 脱下天晶石
await ArtifactModel.putOnOrOff(roleId, artifact.id, 0);
await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, role.serverId, sid, hid, { artifact: 0 });
}
let artifacts = await ArtifactModel.deleteBySeqIds(roleId, artifactSeqIds);
saveItemChangeLog(roleId, artifacts.map(artifact => ({ id: artifact.id, count: 1, inc: -1 })), reason);
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_DEL, { artifacts: artifacts.map(artifact => ({ seqId: artifact.seqId, id: artifact.id, inc: -1, reason })) }, sid);
}
//消耗玩家货币
if (gold.length > 0 || coin.length > 0) {
let costGold = gold.reduce((pre, cur) => pre + cur.count, 0);
@@ -115,7 +136,7 @@ export async function handleCost(roleId: string, sid: string, goods: Array<ItemI
export async function addItems(roleId: string, roleName: string, sid: string, goods: Array<ItemInter>, reason: ITEM_CHANGE_REASON) {
goods = filterGoods(goods, obj => obj.id, roleId, reason);
let { items, jewels, gold, coin, ap, skins, figures } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE);
let { items, jewels, gold, coin, ap, skins, figures, artifacts } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE);
let showItems: { id: number, seqId?: number, count: number, isBag?: boolean }[] = [];
let role = await RoleModel.findByRoleId(roleId);
// 1. 装备处理
@@ -130,7 +151,7 @@ export async function addItems(roleId: string, roleName: string, sid: string, go
}
// 直接加的
let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number, hid?: number}[]>incJewels, reason);
let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number }[]>incJewels, reason);
for (let jewel of jewelInfos) {
showItems.push({ seqId: jewel.seqId, id: jewel.id, count: 1, isBag: true });
}
@@ -229,6 +250,39 @@ export async function addItems(roleId: string, roleName: string, sid: string, go
}
}
// 6. 宝物处理
if(artifacts.length > 0) {
let { artifactCount = 0 } = role;
let incArtifacts = artifacts, mailArtifacts: { id?: number, seqId?: number }[] = [];
if(artifacts.length + artifactCount > BAG.BAG_ARTIFACT_UPLIMITED) { // 装备上限
let inc = BAG.BAG_ARTIFACT_UPLIMITED - artifactCount;
if(inc < 0) inc = 0;
incArtifacts = artifacts.slice(0, inc);
mailArtifacts = artifacts.slice(inc);
}
// 直接加的
let { artifacts: artifactInfos } = await addArtifacts(roleId, roleName, <{id: number}[]>incArtifacts, reason);
for (let artifact of artifactInfos) {
showItems.push({ seqId: artifact.seqId, id: artifact.id, count: 1, isBag: true });
}
for(let artifact of combineItems(mailArtifacts)) {
showItems.push({ id: artifact.id, count: artifact.count, isBag: false });
}
//装备推送
if (!!artifactInfos.length)
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_ADD, { artifacts: artifactInfos }, sid);
//统计装备
if (artifactInfos.length > 0) {
saveItemChangeLog(roleId, artifactInfos, reason);
}
// 发邮件的
if(mailArtifacts.length > 0) {
await sendMailByContent(MAIL_TYPE.ARTIFACT_OVER, roleId, { goods: combineItems(mailArtifacts) });
}
}
return showItems;
}
@@ -437,6 +491,20 @@ export function getJewelRandSe(id: number, seid: number) {
return new RandSe(id, dicRandom.id, rand);
}
export async function addArtifacts(roleId: string, roleName: string, artifacts: { id: number, }[], reason: number) {
let artifactInfos: ArtifactModelUpdate[] = [];
for(let { id } of artifacts) {
let dicArtifact = getDefArtifactByGid(id);
if(dicArtifact) {
let { goodId, artifactId, quality, qualityStage } = dicArtifact;
artifactInfos.push({ roleId, roleName, id: goodId, artifactId, quality, qualityStage });
}
}
const artifactResult = await ArtifactModel.createArtifacts(roleId, artifactInfos);
return { artifacts: artifactResult.map(artifact => new ArtifactParam(artifact, true, reason))}
}
export function getGoldId() {
return CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD);
}
+13 -2
View File
@@ -6,6 +6,7 @@ import { errlogger } from '../../util/logger';
export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
let items: { id: number, count: number }[] = []; // 可叠加道具
let jewels: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备
let artifacts: { seqId?: number, id?: number }[] = []; // 不可叠加宝物
let gold: { count: number, isPay: boolean }[] = []; // 金币
let coin: number[] = [];
let ap: number = 0;
@@ -74,11 +75,21 @@ export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
}
}
}
} else if (table == ITEM_TABLE.ARTIFACT) {
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
for(let i = 0; i < good.count; i++) {
artifacts.push({ id: good.id })
}
} else {
if(!!good.seqId) {
artifacts.push({ seqId: good.seqId });
}
}
}
}
return { items, jewels, gold, coin, ap, skins, figures }
return { items, jewels, gold, coin, ap, skins, figures, artifacts }
}
export function getGoldEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) {
@@ -98,7 +109,7 @@ export function combineItems(items: { id?: number, count?: number, seqId?: numbe
for(let { id, count = 1, seqId, isBag } of items) {
let dicGoods = gameData.goods.get(id);
let dicItid = ITID.get(dicGoods.itid);
if(dicItid.table != 'jewel') {
if(dicItid.table != 'jewel' && dicItid.table != 'artifact') {
let index = result.findIndex(cur => cur.id == id);
if(index == -1) {
result.push({ id, count, seqId, isBag });