gameMethod.ts 109 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937
  1. import * as Xys from "./Xys";
  2. import Gamecfg from "./gameCfg";
  3. const gezi: number[] = [
  4. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
  5. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
  6. ];
  7. class GameMethod {
  8. /**
  9. * 钻石购买金币获得道具公式
  10. * @param id 配置表档位ID
  11. * @param level 角色等级
  12. */
  13. shopCoinItem(id: string, level: number): Xys.KindItem {
  14. let cfg = Gamecfg.shopCoin.getItem(id);
  15. if (cfg == null) {
  16. return [1, 2, 1];
  17. }
  18. let count = cfg.rate * Math.min(10 + Math.floor(level / 10), 50);
  19. return [1, 2, count];
  20. }
  21. /**
  22. * 两个对象合并
  23. * @param obj1 from object
  24. * @param obj2 to object
  25. * @return obj2
  26. */
  27. objMerge(obj1: any, obj2: any) {
  28. obj1 = typeof obj1 != "object" ? {} : obj1;
  29. obj2 = typeof obj2 != "object" ? {} : obj2;
  30. for (const key in obj2) {
  31. if (obj1[key] == null) {
  32. obj1[key] = obj2[key];
  33. continue;
  34. }
  35. if (typeof obj2[key] == "object") {
  36. this.objMerge(obj1[key], obj2[key]);
  37. continue;
  38. }
  39. obj1[key] = obj2[key];
  40. }
  41. return obj1; //然后在把复制好的对象给return出去
  42. }
  43. /**
  44. * 两个对象合并 值相加
  45. */
  46. objMergeNum(_eps1: { [key: string]: number }, _eps2: { [key: string]: number }): { [key: string]: number } {
  47. let eps: any = this.objCopy(_eps1);
  48. let ep2: any = this.objCopy(_eps2);
  49. for (const key in ep2) {
  50. if (eps[key] == null) {
  51. eps[key] = 0;
  52. }
  53. eps[key] += ep2[key];
  54. }
  55. return eps;
  56. }
  57. /**
  58. * 数组合并
  59. */
  60. addArr(arr1: any[], arr2: any[]) {
  61. let _arr1 = JSON.parse(JSON.stringify(arr1));
  62. let _arr2 = JSON.parse(JSON.stringify(arr2));
  63. for (const arr of _arr2) {
  64. _arr1.push(arr);
  65. }
  66. return _arr1;
  67. }
  68. /**
  69. * 业务判空 以下情况返回true
  70. * 字符串 : 空字符的为空
  71. * 数值: 0 为空 负数不为空
  72. * 数组: 长度为0
  73. * 对象: 没有节点
  74. * 布尔型 false
  75. */
  76. isEmpty(value: any): boolean {
  77. if (value == null) {
  78. return true;
  79. }
  80. switch (typeof value) {
  81. case "string":
  82. if (value.length == null || value.length <= 0) {
  83. return true;
  84. }
  85. break;
  86. case "object":
  87. if (Object.keys(value).length > 0) {
  88. return false;
  89. }
  90. return true;
  91. case "number":
  92. if (value == 0) {
  93. return true;
  94. }
  95. break;
  96. case "boolean":
  97. if (value == false) {
  98. return true;
  99. }
  100. break;
  101. }
  102. return false;
  103. }
  104. /**
  105. * 通用深拷贝函数。
  106. * @param obj from object
  107. * @return obj2
  108. */
  109. objCopy<T>(obj: T): T {
  110. return JSON.parse(JSON.stringify(obj));
  111. }
  112. /**
  113. * 相同kind 和 itemid 数组合并
  114. */
  115. mergeArr(arrs: Xys.KindItem[]) {
  116. let resObj: { [kind: number]: { [itemid: number]: number } } = {};
  117. for (const arr of arrs) {
  118. if (resObj[arr[0]] == null) {
  119. resObj[arr[0]] = {};
  120. }
  121. if (resObj[arr[0]][arr[1]] == null) {
  122. resObj[arr[0]][arr[1]] = 0;
  123. }
  124. resObj[arr[0]][arr[1]] += arr[2];
  125. }
  126. let resArr = [];
  127. for (const kind in resObj) {
  128. for (const id in resObj[kind]) {
  129. resArr.push([parseInt(kind), parseInt(id), resObj[kind][id]]);
  130. }
  131. }
  132. return resArr;
  133. }
  134. // 判断字符长度
  135. getStrCharacterLength(str: string): number {
  136. let patternChinese = new RegExp("[\u4E00-\u9FA5]+"); // 中文
  137. let leng = 0;
  138. for (let index = 0; index < str.length; index++) {
  139. if (patternChinese.test(str[index])) {
  140. leng += 2;
  141. } else {
  142. leng += 1;
  143. }
  144. }
  145. return leng;
  146. }
  147. /**
  148. * 随机数
  149. * @param min
  150. * @param max
  151. */
  152. rand(min: number, max: number) {
  153. return Math.round((max - min + 1) * Math.random() - 0.5) + min;
  154. }
  155. //判断uuid是否npc
  156. isNpc(fuuid: string): boolean {
  157. if (Number(fuuid) < 10000) {
  158. return true;
  159. }
  160. return false;
  161. }
  162. hdDiZiModelRate(out: Xys.HdDiZiOut, data: Xys.HdDiZiData, actDiZiList: { [dzid: string]: Xys.ActDiZi_Info }) {
  163. let rate = 0;
  164. let zRate = 0;
  165. for (const pzid in out.tree.list) {
  166. if (!data.list[pzid]) {
  167. console.error(`hd_cfg_err:hdQiYuanModelRate: 无效的品质ID ${pzid}`);
  168. continue;
  169. }
  170. for (let ygzid = 1; ygzid <= out.tree.list[pzid].open; ygzid++) {
  171. let _rate = 0;
  172. let _zRate = 0;
  173. let dzid = out.tree.list[pzid].dzList[ygzid];
  174. if (!dzid || !actDiZiList[dzid]) {
  175. _rate += Number(data.make["2"].item[0]);
  176. _zRate += Number(data.make["2"].zItem[0]);
  177. continue;
  178. }
  179. let dzInfo = actDiZiList[dzid];
  180. let cfgDzInfo = Gamecfg.huobanBase.getItem(dzInfo.id);
  181. if (!cfgDzInfo) {
  182. continue;
  183. }
  184. let dzpinzhi = cfgDzInfo.pinzhi;
  185. // 等级加成
  186. for (let chanchu of data.make[dzpinzhi.toString()].levelItem) {
  187. if (chanchu[0] <= dzInfo.level && dzInfo.level <= chanchu[1]) {
  188. _rate += Number(chanchu[2]);
  189. break;
  190. }
  191. }
  192. for (let chanchu of data.make[dzpinzhi.toString()].levelZItem) {
  193. if (chanchu[0] <= dzInfo.level && dzInfo.level <= chanchu[1]) {
  194. _zRate += Number(chanchu[2]);
  195. break;
  196. }
  197. }
  198. // 星级加成
  199. for (let chanchu of data.make[dzpinzhi.toString()].starItem) {
  200. if (chanchu[0] <= dzInfo.star && dzInfo.star <= chanchu[1]) {
  201. _rate += Number(chanchu[2]);
  202. break;
  203. }
  204. }
  205. for (let chanchu of data.make[dzpinzhi.toString()].starZItem) {
  206. if (chanchu[0] <= dzInfo.star && dzInfo.star <= chanchu[1]) {
  207. _zRate += Number(chanchu[2]);
  208. break;
  209. }
  210. }
  211. if (Number(cfgDzInfo.liupai) === Number(pzid)) {
  212. _rate *= Number(data.make[dzpinzhi.toString()].item[2]);
  213. _zRate *= Number(data.make[dzpinzhi.toString()].zItem[2]);
  214. } else {
  215. _rate *= Number(data.make[dzpinzhi.toString()].item[1]);
  216. _zRate *= Number(data.make[dzpinzhi.toString()].zItem[1]);
  217. }
  218. rate += _rate;
  219. zRate += _zRate;
  220. }
  221. }
  222. return { rate, zRate };
  223. }
  224. //根据速度和 当前XX 计算出当前总积分 兽灵
  225. hdDiZiModelTotol(out: Xys.HdDiZiOut, data: Xys.HdDiZiData, rate: number, zRate: number, nowTime: number) {
  226. //过了多长时间
  227. let dtime = nowTime - out.tree.s_time;
  228. //根据速度 掉落
  229. //现在改为限制产出时间,而不是限制产出数量
  230. dtime = Math.min(dtime, data.tree.scoreTimeMax);
  231. let score = Math.round((rate * dtime) / 3600);
  232. let totol = score + out.tree.s_num;
  233. const zScore = Math.round((zRate * dtime) / 3600);
  234. let zTotal = zScore + out.tree.z_num;
  235. // if (totol > data.tree.scoreMax) {
  236. // //实际产出
  237. // let sj = data.tree.scoreMax - out.tree.s_num;
  238. // //实际产出 所需时间
  239. // dtime = Math.round((sj / rate) * 3600);
  240. // //获得的总产出
  241. // totol = data.tree.scoreMax;
  242. // }
  243. //根据速率 结算
  244. return {
  245. totol: totol, //当前总产出
  246. zTotal: zTotal, //起源之征总产出
  247. dtime: dtime, //本次计算 实际产出时长
  248. };
  249. }
  250. /**
  251. * 计算心魔积分范围
  252. */
  253. hdShouLingScore(
  254. xmId: string,
  255. cfg: Xys.HdShouLingData,
  256. actShouLing: { [gzid: string]: Omit<Xys.ActShouLing_ListOne, 'sk'> } = {},
  257. gzids: string[] = []
  258. ): [number, number] {
  259. let shoulingCfg = cfg.shouling[xmId];
  260. if (shoulingCfg == null) {
  261. console.error(`xmId_err :${xmId}`);
  262. return [0, 0];
  263. }
  264. //初始积分: 心魔积分
  265. let scores: [number, number] = [shoulingCfg.score[0], shoulingCfg.score[1]];
  266. for (let i = 0; i < gzids.length; i++) {
  267. let gzid = gzids[i];
  268. let addOne = gameMethod.hdShouLingScoreOne(cfg, actShouLing, gzid);
  269. scores[0] += addOne[0];
  270. scores[1] += addOne[1];
  271. }
  272. return scores;
  273. }
  274. /**
  275. * 心魔计算 一个宠物加的积分
  276. */
  277. hdShouLingScoreOne(cfg: Xys.HdShouLingData, slinfo: { [gzid: string]: Omit<Xys.ActShouLing_ListOne, 'sk'> }, gzid: string): [number, number] {
  278. //初始积分: 心魔积分
  279. let sadd: [number, number] = [0, 0];
  280. //是否存在
  281. if (slinfo[gzid] == null) {
  282. console.error(`fzInfo_null :${gzid}`);
  283. return sadd;
  284. }
  285. //获取法阵等级配置
  286. let cfgsl = Gamecfg.shoulingInfo.getItem(slinfo[gzid].slid);
  287. if (cfgsl == null) {
  288. console.error(`cfgsl_null :${gzid}`);
  289. return sadd;
  290. }
  291. //等级积分累加
  292. if (cfg.sMath[cfgsl.pinzhi.toString()] != null) {
  293. //[积分价值,积分下限,积分上限,系数下限,系数上限]
  294. let pzcfg = cfg.sMath[cfgsl.pinzhi.toString()];
  295. //积分价值
  296. sadd[0] += pzcfg.xishu[0];
  297. sadd[1] += pzcfg.xishu[0];
  298. //积分上下限
  299. sadd[0] += pzcfg.xishu[1];
  300. sadd[1] += pzcfg.xishu[2];
  301. //积分系数 * 等级(saveId)
  302. sadd[0] += slinfo[gzid].level * pzcfg.xishu[3];
  303. sadd[1] += slinfo[gzid].level * pzcfg.xishu[4];
  304. //积分系数 * 星级(saveId)
  305. sadd[0] += slinfo[gzid].star * pzcfg.xishu[5];
  306. sadd[1] += slinfo[gzid].star * pzcfg.xishu[6];
  307. }
  308. return sadd;
  309. }
  310. /**
  311. * 计算灵脉积分产出
  312. */
  313. lingMaiScore(jingjieId: string, chenghaoId: string): number {
  314. let cfgBase = Gamecfg.mathInfo.getItem("lingmai_base_score");
  315. if (cfgBase == null || cfgBase.pram == null || cfgBase.pram.count == null) {
  316. return 0;
  317. }
  318. //计算境界加成
  319. let jingjieAdd = 0;
  320. let jingjieCfg = Gamecfg.jingjieStep.getItem(jingjieId);
  321. if (jingjieCfg != null) {
  322. jingjieAdd = jingjieCfg.lmjc;
  323. }
  324. //计算称号加成
  325. let titleAdd = 0;
  326. let titleCfg = Gamecfg.chenghaoInfo.getItem(chenghaoId);
  327. if (titleCfg != null) {
  328. titleAdd = titleCfg.jc;
  329. }
  330. //初始积分: 心魔积分
  331. let scores = Math.round(cfgBase.pram.count * (1 + jingjieAdd / 100) * (1 + titleAdd / 100));
  332. return scores;
  333. }
  334. //--------------属性计算 (主角基础属性 ) -------------------------
  335. // (天赋数值+装备数值+基础属性)*(1+百分比加成)=面板属性
  336. /**
  337. * 属性合并
  338. */
  339. ep_merge(_eps1: { [key: string]: number }, _eps2: { [key: string]: number }): { [key: string]: number } {
  340. let eps: any = this.objCopy(_eps1);
  341. let ep2: any = this.objCopy(_eps2);
  342. for (const key in ep2) {
  343. if (eps[key] == null) {
  344. eps[key] = 0;
  345. }
  346. eps[key] += ep2[key];
  347. }
  348. eps.hp = eps.hp_max || 0;
  349. return eps;
  350. }
  351. /**
  352. * {[key:string]:number} 属性合并 _eps2的key _eps1没有就不加
  353. */
  354. ep_mergeKv_has(_eps1: { [key: string]: number }, _eps2: { [key: string]: number }): { [key: string]: number } {
  355. let eps: any = this.objCopy(_eps1);
  356. let ep2: any = this.objCopy(_eps2);
  357. for (const key in ep2) {
  358. if (eps[key] == null) {
  359. continue;
  360. }
  361. eps[key] += ep2[key];
  362. }
  363. eps["hp"] = eps["hp_max"]; //不要删
  364. return eps;
  365. }
  366. /**
  367. * {[key:string]:number} 属性合并 x 系数
  368. */
  369. ep_KvRate(_eps1: { [key: string]: number }, rate: number): { [key: string]: number } {
  370. let eps: any = this.objCopy(_eps1);
  371. for (const key in eps) {
  372. eps[key] = Math.floor(eps[key] * rate);
  373. }
  374. return eps;
  375. }
  376. /**
  377. * 属性初始化
  378. */
  379. ep_init(): { [key: string]: number } {
  380. let eps: any = {};
  381. let userEpPool = Gamecfg.userEp.pool;
  382. for (const key in userEpPool) {
  383. eps[userEpPool[key].key] = 0;
  384. }
  385. return eps;
  386. }
  387. /**
  388. * 角色基础属性
  389. */
  390. ep_user(): { [key: string]: number } {
  391. let eps: { [key: string]: number } = {};
  392. let userEpPool = Gamecfg.userEp.pool;
  393. for (const key in userEpPool) {
  394. eps[userEpPool[key].key] = userEpPool[key].initEp;
  395. }
  396. return eps;
  397. }
  398. /**
  399. * 属性展示总属性
  400. */
  401. ep_all_base(sevBack: Xys.SevBack): { [key: string]: number } {
  402. //属性初始化
  403. let eps: { [key: string]: number } = this.ep_init();
  404. //+角色基础属性
  405. eps = this.ep_merge(eps, this.ep_user());
  406. //后端记录的属性
  407. if (sevBack.actEps != null && sevBack.actEps.a != null) {
  408. for (const kid in sevBack.actEps.a) {
  409. eps = gameMethod.ep_merge(eps, sevBack.actEps.a[kid]);
  410. }
  411. }
  412. eps["hp"] = Math.round(eps["hp"]);
  413. eps["atk"] = Math.round(eps["atk"]);
  414. eps["def"] = Math.round(eps["def"]);
  415. return gameMethod.objCopy(eps);
  416. }
  417. /**
  418. * 属性展示总属性 (面板属性)
  419. * 面板属性 = 角色基础属性
  420. */
  421. ep_all(sevBack: Xys.SevBack): { [key: string]: number } {
  422. let eps = this.ep_all_base(sevBack);
  423. //攻速
  424. eps.speed += Math.floor((eps.speed * eps.speed_per) / 10000);
  425. //攻击
  426. eps.atk += Math.floor((eps.atk * eps.atk_per) / 10000);
  427. eps.atk += Math.floor((eps.atk * eps.finally_atk_per) / 10000);
  428. //防御
  429. eps.def += Math.floor((eps.def * eps.def_per) / 10000);
  430. eps.def += Math.floor((eps.def * eps.finally_def_per) / 10000);
  431. //血量
  432. eps.hp_max += Math.floor((eps.hp_max * eps.hp_max_per) / 10000);
  433. eps.hp_max += Math.floor((eps.hp_max * eps.finally_hp_max_per) / 10000);
  434. eps.hp = eps.hp_max;
  435. //攻速
  436. eps.speed_per = 0;
  437. //攻击
  438. eps.atk_per = 0
  439. eps.finally_atk_per = 0
  440. //防御
  441. eps.def_per = 0
  442. eps.finally_def_per = 0;
  443. //血量
  444. eps.hp_max_per = 0;
  445. eps.finally_hp_max_per = 0;
  446. return gameMethod.objCopy(eps);
  447. }
  448. /**
  449. * 属性展示总属性 (面板属性)
  450. * 面板属性 = 角色基础属性
  451. */
  452. ep_all_fight(eps: { [key: string]: number }): { [key: string]: number } {
  453. eps = gameMethod.objCopy(eps)
  454. //攻速
  455. eps.speed += Math.floor((eps.speed * eps.speed_per) / 10000);
  456. //攻击
  457. eps.atk += Math.floor((eps.atk * eps.atk_per) / 10000);
  458. eps.atk += Math.floor((eps.atk * eps.finally_atk_per) / 10000);
  459. eps.atk += eps.finally_atk
  460. //防御
  461. eps.def += Math.floor((eps.def * eps.def_per) / 10000);
  462. eps.def += Math.floor((eps.def * eps.finally_def_per) / 10000);
  463. eps.def += eps.finally_def
  464. //血量
  465. eps.hp_max += Math.floor((eps.hp_max * eps.hp_max_per) / 10000);
  466. eps.hp_max += Math.floor((eps.hp_max * eps.finally_hp_max_per) / 10000);
  467. eps.hp_max += eps.finally_hp_max
  468. eps.hp = eps.hp_max;
  469. //攻速
  470. eps.speed_per = 0;
  471. //攻击
  472. eps.atk_per = 0
  473. eps.finally_atk_per = 0
  474. eps.finally_atk = 0
  475. //防御
  476. eps.def_per = 0
  477. eps.finally_def_per = 0;
  478. eps.finally_def = 0;
  479. //血量
  480. eps.hp_max_per = 0;
  481. eps.finally_hp_max_per = 0;
  482. eps.finally_hp_max = 0;
  483. return eps;
  484. }
  485. /**
  486. * 属性展示总属性 (面板属性)显示最终属性
  487. */
  488. ep_all_zz(eps: { [key: string]: number }): { [key: string]: number } {
  489. eps = gameMethod.objCopy(eps)
  490. //攻击
  491. let atk:number = eps.atk
  492. atk += eps.atk_per? Math.floor((atk * eps.atk_per) / 10000):0;
  493. atk += eps.finally_atk_per?Math.floor((atk * eps.finally_atk_per) / 10000):0;
  494. atk += eps.finally_atk
  495. //防御
  496. let def:number = eps.def
  497. def += eps.def_per? Math.floor((def * eps.def_per) / 10000):0;
  498. def += eps.finally_def_per?Math.floor((def * eps.finally_def_per) / 10000):0;
  499. def += eps.finally_def
  500. //血量
  501. let hp_max:number = eps.hp_max
  502. hp_max += eps.hp_max_per?Math.floor((hp_max * eps.hp_max_per) / 10000):0;
  503. hp_max += eps.finally_hp_max_per?Math.floor((hp_max * eps.finally_hp_max_per) / 10000):0;
  504. hp_max += eps.finally_hp_max
  505. return {
  506. "finally_atk":atk,
  507. "finally_def":def,
  508. "finally_hp_max":hp_max,
  509. };
  510. }
  511. /**
  512. * 主角战斗属性
  513. */
  514. ep_fight(sevBack: Xys.SevBack): { [key: string]: number } {
  515. let eps = this.ep_all(sevBack);
  516. //攻速
  517. eps.speed_per = 0;
  518. //攻击
  519. eps.atk_per = 0
  520. eps.finally_atk_per = 0
  521. //防御
  522. eps.def_per = 0
  523. eps.finally_def_per = 0;
  524. //血量
  525. eps.hp_max_per = 0;
  526. eps.finally_hp_max_per = 0;
  527. return eps;
  528. }
  529. /**
  530. * 弟子战斗属性
  531. * @param dzInfo 弟子信息
  532. * @param eps 主角属性
  533. * @returns
  534. */
  535. ep_fight_dizi(dzInfo: Xys.ActDiZi_Info, epsAll: { [key: string]: number }): { [key: string]: number } {
  536. let dzEps: { [key: string]: number } = gameMethod.ep_init(); //初始化属性
  537. let cfgdz = Gamecfg.huobanBase.getItem(dzInfo.id);
  538. if (cfgdz == null) {
  539. return dzEps;
  540. }
  541. let cfgZhongZu = Gamecfg.huobanZhongzu.getItem(cfgdz.pinzhi, cfgdz.zhongzu.toString());
  542. if (cfgZhongZu == null) {
  543. return dzEps;
  544. }
  545. dzEps = gameMethod.ep_merge(dzEps, cfgdz.eps);
  546. for (const key in cfgZhongZu.inherit_attr) {
  547. //继承主角属性
  548. dzEps[key] += Math.floor((epsAll[key] * cfgZhongZu.inherit_attr[key]) / 10000);
  549. }
  550. for (const key in cfgZhongZu.inherit_attr_hide) {
  551. //继承主角属性
  552. dzEps[key] += Math.floor((epsAll[key] * cfgZhongZu.inherit_attr_hide[key]) / 10000);
  553. }
  554. dzEps.hp = dzEps.hp_max;
  555. return dzEps;
  556. }
  557. /**
  558. * 阵法
  559. */
  560. ep_zhenfa(actZhenfa: Xys.ActZhenfaNew): { [key: string]: number } {
  561. let eps: { [key: string]: number } = {};
  562. const chuanKeys = Object.keys(actZhenfa.chuan);
  563. for (let i = 0; i < chuanKeys.length; i++) {
  564. const buwei = chuanKeys[i];
  565. //装备属性
  566. eps = this.ep_merge(eps, actZhenfa.chuan[buwei].eps);
  567. //附魔属性
  568. let addEps: { [key: string]: number } = {};
  569. for (const fmEps of actZhenfa.chuan[buwei].fmEps) {
  570. if (addEps[fmEps[0]] == null) {
  571. addEps[fmEps[0]] = 0;
  572. }
  573. addEps[fmEps[0]] += fmEps[1];
  574. }
  575. // 洗练属性
  576. for (const posId in actZhenfa.chuan[buwei].xilianEps) {
  577. if (actZhenfa.chuan[buwei].xilianEps[posId].id == null || actZhenfa.chuan[buwei].xilianEps[posId].id == "") {
  578. continue;
  579. }
  580. let xilian_c = Gamecfg.zhenfaXilianWord.getItem(actZhenfa.chuan[buwei].xilianEps[posId].id);
  581. if (xilian_c != null) {
  582. eps = this.ep_merge(eps, xilian_c.attr);
  583. }
  584. }
  585. eps = this.ep_merge(eps, addEps);
  586. }
  587. return eps;
  588. }
  589. /**
  590. * 阵法
  591. */
  592. ep_zhenfa_list(actZhenfa: Xys.ActZhenfaNew): { [key: string]: number } {
  593. let eps: { [key: string]: number } = {};
  594. // 阵法New
  595. let keys = Object.keys(actZhenfa.zfList);
  596. for (let i = 0; i < keys.length; i++) {
  597. let zfBase = Gamecfg.zfxtZfbase.getItem(keys[i]);
  598. if (zfBase != null) {
  599. let zfShengji = Gamecfg.zfxtZfshengji.getItem(zfBase.pinzhi, actZhenfa.zfList[keys[i]].level.toString());
  600. if (zfShengji != null) {
  601. eps = this.ep_merge(eps, zfShengji.attr);
  602. }
  603. }
  604. }
  605. return eps;
  606. }
  607. /**
  608. * 大帝古字
  609. */
  610. ep_dadiguzi(actDadiGuzi: Xys.ActDadiGuzi, mfList: { [mfid: string]: Xys.mfInfo }): { [key: string]: number } {
  611. let eps: { [key: string]: number } = {};
  612. const keys = Object.keys(actDadiGuzi.mpList[actDadiGuzi.mpXhid]);
  613. for (let i = 0; i < keys.length; i++) {
  614. const buwei = keys[i];
  615. if (gameMethod.isEmpty(actDadiGuzi.mpList[actDadiGuzi.mpXhid][buwei]) == true) {
  616. continue;
  617. }
  618. eps = this.ep_merge(eps, actDadiGuzi.mpList[actDadiGuzi.mpXhid][buwei].eps);
  619. }
  620. //上阵列表
  621. let szMfids: string[] = [];
  622. const mfZhanKeys = Object.keys(actDadiGuzi.mfZhan);
  623. for (let i = 0; i < mfZhanKeys.length; i++) {
  624. const _type = mfZhanKeys[i];
  625. if (actDadiGuzi.mfZhan[_type] == "") {
  626. continue;
  627. }
  628. szMfids.push(actDadiGuzi.mfZhan[_type]);
  629. }
  630. //仙法 + 铭文
  631. const mfListKeys = Object.keys(mfList);
  632. for (let i = 0; i < mfListKeys.length; i++) {
  633. const mfid = mfListKeys[i];
  634. let cfgXfInfo = Gamecfg.dadiguziXfinfo.getItem(mfid);
  635. if (cfgXfInfo == null) {
  636. continue;
  637. }
  638. let cfg = Gamecfg.dadiguziXflv.getItem(cfgXfInfo.pinzhi.toString(), mfList[mfid].level.toString());
  639. if (cfg != null) {
  640. if (eps["hp_max"] == null) {
  641. eps["hp_max"] = 0;
  642. }
  643. if (eps["atk"] == null) {
  644. eps["atk"] = 0;
  645. }
  646. if (eps["def"] == null) {
  647. eps["def"] = 0;
  648. }
  649. eps["hp_max"] += cfg.hp_max;
  650. eps["atk"] += cfg.atk;
  651. eps["def"] += cfg.def;
  652. }
  653. if (szMfids.indexOf(mfid) == -1) {
  654. continue; //没上阵 不加铭文属性
  655. }
  656. for (const mwid of mfList[mfid].mwLock) {
  657. if (mwid == null || mwid == "") {
  658. continue;
  659. }
  660. let cfgMw = Gamecfg.dadiguziMingwen.getItem(mwid);
  661. if (cfgMw != null) {
  662. eps = this.ep_merge(eps, cfgMw.eps);
  663. }
  664. }
  665. }
  666. //图鉴
  667. const tjlistKeys = Object.keys(actDadiGuzi.tjlist);
  668. for (let i = 0; i < tjlistKeys.length; i++) {
  669. const _key = tjlistKeys[i];
  670. let cfgtjNew = Gamecfg.dadiguziXftj.getItem(_key, actDadiGuzi.tjlist[_key].toString());
  671. if (cfgtjNew == null) {
  672. continue;
  673. }
  674. eps = this.ep_merge(eps, cfgtjNew.eps);
  675. }
  676. return eps;
  677. }
  678. /**
  679. * 计算弟子全局属性 弟子加成只有突破属性和图鉴加成
  680. */
  681. ep_dizi_base(actDiZi: Xys.ActDiZi, actDiZiList: { [dizi: string]: Xys.ActDiZi_Info}): { [key: string]: number } {
  682. let eps: { [key: string]: number } = {};
  683. const dzListKeys = Object.keys(actDiZiList);
  684. for (let i = 0; i < dzListKeys.length; i++) {
  685. const dzid = dzListKeys[i];
  686. //计算弟子阶级属性
  687. let dizi = actDiZiList[dzid];
  688. // let num = dizi.level % 5;
  689. const diZiStar_c = Gamecfg.huobanStar.getItem(dzid, dizi.star.toString());
  690. if (diZiStar_c != null) {
  691. for (let i = 0; i <= Number(diZiStar_c.star); i++) {
  692. const cfgStep = Gamecfg.huobanStar.getItem(dzid, i.toString());
  693. if (cfgStep != null) {
  694. let stepEps = cfgStep.attr;
  695. eps = this.ep_merge(eps, stepEps);
  696. }
  697. }
  698. }
  699. }
  700. //计算弟子图鉴属性
  701. const tujianKeys = Object.keys(actDiZi.tujian);
  702. for (let i = 0; i < tujianKeys.length; i++) {
  703. const tujianKey = tujianKeys[i];
  704. const diziTuJian_c = Gamecfg.huobanTujian.getItem(tujianKey, actDiZi.tujian[tujianKey].toString());
  705. if (diziTuJian_c == null) {
  706. continue;
  707. }
  708. eps = this.ep_merge(eps, diziTuJian_c.attr);
  709. }
  710. //皮肤属性
  711. for (let i = 0; i < dzListKeys.length; i++) {
  712. const dzid = dzListKeys[i];
  713. let dizi = actDiZiList[dzid];
  714. if(!actDiZiList[dzid].skins){
  715. continue;
  716. }
  717. for (const key in actDiZiList[dzid].skins) {
  718. let level = actDiZiList[dzid].skins[key].level;
  719. let skinCfg = Gamecfg.huobanSkinlevel.getItem(key, level.toString());
  720. if(skinCfg){
  721. eps = this.ep_merge(eps, skinCfg.levelEps);
  722. }
  723. }
  724. }
  725. return eps;
  726. }
  727. ep_shouling_shengxiao(actShouLingList: { [gzid: string]: Xys.ActShouLing_ListOne }) {
  728. let shoulingList: { [slid: string]: number } = {};
  729. let gzList: { [slid: string]: string } = {};
  730. const listKeys = Object.keys(actShouLingList);
  731. for (let i = 0; i < listKeys.length; i++) {
  732. const index = listKeys[i];
  733. if (actShouLingList[index] != null && gameMethod.isEmpty(actShouLingList[index].slid) == false) {
  734. const slid = actShouLingList[index].slid;
  735. const eps = this.ep_shouling_gezi(actShouLingList[index]);
  736. const zhanli = eps["hp_max_per"];
  737. const existingZhanli = shoulingList[slid];
  738. if (existingZhanli === undefined || zhanli > existingZhanli) {
  739. shoulingList[slid] = zhanli;
  740. gzList[slid] = index;
  741. }
  742. }
  743. }
  744. let gzIdlist: any[] = [];
  745. let gzListKeys = Object.keys(gzList);
  746. for (let i = 0; i < gzListKeys.length; i++) {
  747. gzIdlist.push(gzList[gzListKeys[i]]);
  748. }
  749. return gzIdlist;
  750. }
  751. /**
  752. * 计算兽灵总属性加成
  753. */
  754. ep_shouling(actShouLingList: { [gzid: string]: Xys.ActShouLing_ListOne }, actShouLing: Xys.ActShouLing, jiuxiao: number = 0): { [key: string]: number } {
  755. let eps: { [key: string]: number } = {};
  756. //计算兽灵属性总加成(不包含技能)
  757. let shoulingList: { [slid: string]: number } = {};
  758. let gzList: { [slid: string]: string } = {};
  759. //遍历出最高属性的兽灵的格子id
  760. const listKeys = Object.keys(actShouLingList);
  761. for (let i = 0; i < listKeys.length; i++) {
  762. const index = listKeys[i];
  763. if (actShouLingList[index] != null && gameMethod.isEmpty(actShouLingList[index].slid) == false) {
  764. const slid = actShouLingList[index].slid;
  765. const eps = this.ep_shouling_gezi(actShouLingList[index]);
  766. const zhanli = eps["hp_max_per"];
  767. const existingZhanli = shoulingList[slid];
  768. if (existingZhanli === undefined || zhanli > existingZhanli) {
  769. shoulingList[slid] = zhanli;
  770. gzList[slid] = index;
  771. }
  772. }
  773. }
  774. const gzListKeys = Object.keys(gzList);
  775. for (let i = 0; i < gzListKeys.length; i++) {
  776. const gz = gzListKeys[i];
  777. if (gameMethod.isEmpty(gzList[gz]) == false) {
  778. eps = this.ep_merge(eps, this.ep_shouling_gezi(actShouLingList[gzList[gz]], jiuxiao));
  779. }
  780. }
  781. //羁绊属性加成
  782. let jiban = actShouLing.jiban;
  783. const jibanKeys = Object.keys(actShouLing.jiban);
  784. for (let i = 0; i < jibanKeys.length; i++) {
  785. const jbid = jibanKeys[i];
  786. if (gameMethod.isEmpty(jiban[jbid].level)) {
  787. continue;
  788. }
  789. let cfgJiBan = Gamecfg.shoulingJiban.getItem(jbid, jiban[jbid].level.toString());
  790. if (cfgJiBan == null || cfgJiBan.eps == null) {
  791. continue;
  792. }
  793. eps = this.ep_merge(eps, cfgJiBan.eps);
  794. }
  795. //上阵兽灵被动属性加成
  796. const useGzIdKeys = Object.keys(actShouLing.useGzId);
  797. for (let i = 0; i < useGzIdKeys.length; i++) {
  798. const useGzId = useGzIdKeys[i];
  799. let skBdeps: { [key: string]: number } = {};
  800. let gzid = actShouLing.useGzId[useGzId];
  801. if (gzid == null || gzid == "") {
  802. continue;
  803. }
  804. let shouling = actShouLingList[gzid];
  805. if (shouling == null) {
  806. continue;
  807. }
  808. let cfg = Gamecfg.shoulingInfo.getItem(shouling.slid);
  809. if (cfg == null) {
  810. continue;
  811. }
  812. let pinzhiCfg = Gamecfg.shoulingPinzhi.getItem(cfg.pinzhi);
  813. if (pinzhiCfg == null) {
  814. continue;
  815. }
  816. //主站
  817. if (useGzId == "0") {
  818. const skBdKeys = Object.keys(shouling.skBd);
  819. for (let i = 0; i < skBdKeys.length; i++) {
  820. let caoId = skBdKeys[i];
  821. let skill = shouling.skBd[caoId];
  822. let cfgEffect = Gamecfg.shoulingBeidong.getItem(skill.skillId.toString());
  823. if (cfgEffect == null) {
  824. continue;
  825. }
  826. let newEps: { [key: string]: number } = {};
  827. newEps[cfgEffect.type] = cfgEffect.esp[skill.lv - 1];
  828. skBdeps = this.ep_merge(skBdeps, newEps);
  829. }
  830. } else {
  831. const skBdKeys = Object.keys(shouling.skBd);
  832. for (let i = 0; i < skBdKeys.length; i++) {
  833. let caoId = skBdKeys[i];
  834. let skill = shouling.skBd[caoId];
  835. let cfgEffect = Gamecfg.shoulingBeidong.getItem(skill.skillId.toString());
  836. if (cfgEffect == null) {
  837. continue;
  838. }
  839. let newEps: { [key: string]: number } = {};
  840. newEps[cfgEffect.type] = cfgEffect.esp[skill.lv - 1];
  841. let bdEps = gameMethod.objCopy(newEps);
  842. let bdEpsKeys = Object.keys(bdEps);
  843. for (let i = 0; i < bdEpsKeys.length; i++) {
  844. let key = bdEpsKeys[i];
  845. bdEps[key] = Math.round((bdEps[key] * pinzhiCfg.skOdds) / 100);
  846. }
  847. skBdeps = this.ep_merge(skBdeps, bdEps);
  848. }
  849. }
  850. eps = this.ep_merge(eps, skBdeps);
  851. }
  852. return eps;
  853. }
  854. /**
  855. * 单个道友的属性
  856. */
  857. ep_daoyou(daoyou: Xys.ActDaoyou): { [key: string]: number } {
  858. let eps: { [key: string]: number } = {};
  859. for (let one in daoyou.daoyouMap) {
  860. let dyid = daoyou.daoyouMap[one].did;
  861. let level = daoyou.daoyouMap[one].favorLv;
  862. let skkills = daoyou.daoyouMap[one].skill;
  863. //计算等级属性加成
  864. for (let i = 1; i <= level; i++) {
  865. let cfg = Gamecfg.daoyouFavorLv.getItem(dyid, i.toString());
  866. if (cfg != null) {
  867. eps = this.ep_merge(eps, cfg.eps);
  868. }
  869. }
  870. //计算技能属性加成
  871. for (let sk of skkills) {
  872. let cfgSkill = Gamecfg.daoyouSkillLv.getItem(sk.toString());
  873. if (cfgSkill != null) {
  874. let cfgSkillType = Gamecfg.daoyouSkillType.getItem(cfgSkill.sid);
  875. if (cfgSkillType != null && cfgSkillType.type == 2) {
  876. for (let key of Object.keys(cfgSkillType.param)) {
  877. let num = cfgSkill.value[Object.keys(cfgSkillType.param).indexOf(key)];
  878. cfgSkillType.param[key] = num;
  879. }
  880. eps = this.ep_merge(eps, cfgSkillType.param);
  881. }
  882. }
  883. }
  884. }
  885. return eps;
  886. }
  887. /**
  888. * 单个法宝的属性
  889. */
  890. ep_fabao(actFaBao: Xys.ActFaBao): { [key: string]: number } {
  891. let eps = {};
  892. for (const fabao of Object.values(actFaBao.fabaoList)) {
  893. // 基础属性
  894. let cfgFbInfo = Gamecfg.fabaoInfo.getItem(fabao.fbId);
  895. if (cfgFbInfo != null) {
  896. eps = this.ep_merge(eps, cfgFbInfo.attributes);
  897. }
  898. // 升级属性
  899. for (const cfg of Object.values(Gamecfg.fabaoUplevel.pool)) {
  900. if (cfg.id.toString() === fabao.fbId && cfg.level <= fabao.level) {
  901. eps = this.ep_merge(eps, cfg.attributes);
  902. }
  903. }
  904. // 升星属性
  905. for (const cfg of Object.values(Gamecfg.fabaoUpstar.pool)) {
  906. if (cfg.id.toString() === fabao.fbId && cfg.level <= fabao.star) {
  907. eps = this.ep_merge(eps, cfg.attributes);
  908. }
  909. }
  910. }
  911. return eps;
  912. }
  913. /**
  914. * 法宝羁绊的属性
  915. */
  916. ep_fabaoJiban(actFaBao: Xys.ActFaBao): { [key: string]: number } {
  917. let eps = {};
  918. const jibanListKeys = Object.keys(actFaBao.jibanList);
  919. for (let i = 0; i < jibanListKeys.length; i++) {
  920. const jbId = jibanListKeys[i];
  921. // 羁绊属性
  922. let cfgJbInfo = Gamecfg.fabaoJiban.getItem(jbId, actFaBao.jibanList.star.toString());
  923. if (cfgJbInfo !== null) {
  924. eps = this.ep_merge(eps, cfgJbInfo.attributes);
  925. }
  926. }
  927. return eps;
  928. }
  929. /**
  930. * 当前境界的属性
  931. */
  932. ep_jingjie(actJingJie: Xys.ActJingJie, jingjieId: string): { [key: string]: number } {
  933. let eps: { [key: string]: number } = {};
  934. //突破后获得属性
  935. let pool = Gamecfg.jingjieStep.pool
  936. let maxLv:number = 0
  937. for (const key in pool) {
  938. //境界属性(目标型)
  939. if(Number(jingjieId) == Number(pool[key].id)){
  940. eps = this.ep_merge(eps, pool[key].tp_eps);
  941. }
  942. let addCount = 0
  943. for (let i = maxLv+1; i <= pool[key].maxlv; i++) {
  944. if(i > actJingJie.level){
  945. break
  946. }
  947. let cfg = Gamecfg.jingjieLevel.getItem(i.toString());
  948. if (cfg == null) {
  949. continue;
  950. }
  951. //等级获得属性(目标型)
  952. if(i == actJingJie.level){
  953. eps = this.ep_merge(eps, cfg.eps);
  954. }
  955. if(i == actJingJie.level){
  956. addCount += Math.round(actJingJie.exp /cfg.exp[2]);
  957. }else{
  958. addCount += Math.round(cfg.needExp /cfg.exp[2]);
  959. }
  960. }
  961. //因为属性是3次一个循环
  962. // 计算每个 eps 的执行次数
  963. const eps1Count = Math.floor((addCount + 2) / 3); // eps1 应用的次数
  964. const eps2Count = Math.floor((addCount + 1) / 3); // eps2 应用的次数
  965. const eps3Count = Math.floor(addCount / 3); // eps3 应用的次数
  966. eps = this.ep_merge(eps, this.ep_KvRate(pool[key].eps1,eps1Count));
  967. eps = this.ep_merge(eps, this.ep_KvRate(pool[key].eps2,eps2Count));
  968. eps = this.ep_merge(eps, this.ep_KvRate(pool[key].eps3,eps3Count));
  969. maxLv = pool[key].maxlv
  970. if(maxLv >= actJingJie.level){
  971. break
  972. }
  973. }
  974. return eps;
  975. }
  976. /**
  977. * 世家秘术
  978. *
  979. */
  980. ep_clubMiShu(actClubMiShu: Xys.ActClubMiShu): { [key: string]: number } {
  981. let eps: { [key: string]: number } = {};
  982. // 世家筋骨
  983. const jinGuKeys = Object.keys(actClubMiShu.jinGu);
  984. for (let i = 0; i < jinGuKeys.length; i++) {
  985. const type = jinGuKeys[i];
  986. let lv = actClubMiShu.jinGu[type];
  987. let cfg = Gamecfg.clubMiShuJinGu.getItem(type, lv.toString());
  988. if (cfg != null) {
  989. eps = this.ep_merge(eps, cfg.eps);
  990. }
  991. }
  992. // 世家秘术筋骨筋骨全等级达到 ,额外加成属性
  993. let minLvKey = Object.keys(actClubMiShu.jinGu).reduce((pre, cur) => {
  994. if (actClubMiShu.jinGu[cur] < actClubMiShu.jinGu[pre]) {
  995. return cur;
  996. }
  997. return pre;
  998. });
  999. let minLv1 = actClubMiShu.jinGu[minLvKey];
  1000. // 0,10,20,30...
  1001. let JinGuJc = Gamecfg.clubMiShuJinGuJc.getItem((Math.floor(minLv1 / 10) * 10).toString());
  1002. if (JinGuJc != null) {
  1003. eps = this.ep_merge(eps, JinGuJc.eps);
  1004. }
  1005. // 世家经络
  1006. let jlList = actClubMiShu.jllist;
  1007. for (let jlid in jlList) {
  1008. let cfgJl = Gamecfg.clubMiShuJingluo.getItem(jlid, jlList[jlid].level.toString());
  1009. if (cfgJl != null) {
  1010. eps = this.ep_merge(eps, cfgJl.addEp);
  1011. }
  1012. }
  1013. let cfgJlQ = Gamecfg.clubMiShuJlquality.getItem(actClubMiShu.curJlQuality.toString());
  1014. if (cfgJlQ != null) {
  1015. eps = this.ep_merge(eps, cfgJlQ.qualityEp);
  1016. }
  1017. return eps;
  1018. }
  1019. /**
  1020. * 世家圣兵
  1021. *
  1022. */
  1023. ep_clubShengB(actClubShengB: Xys.ActClubShengB): { [key: string]: number } {
  1024. let eps: { [key: string]: number } = {};
  1025. // 获取当前方案的所有位置的词条
  1026. for (let posId in actClubShengB.plan[actClubShengB.curPlan]) {
  1027. // 获取词条配置
  1028. let cfg = Gamecfg.clubShengBWord.getItem(actClubShengB.plan[actClubShengB.curPlan][posId].id);
  1029. if (cfg != null) {
  1030. // 算一下第一个属性的值
  1031. let n = cfg.attr[Object.keys(cfg.attr)[0]] + actClubShengB.plan[actClubShengB.curPlan][posId].range;
  1032. eps = this.ep_merge(eps, { [Object.keys(cfg.attr)[0]]: n });
  1033. }
  1034. }
  1035. return eps;
  1036. }
  1037. /**
  1038. * 宗门-门徒
  1039. *
  1040. */
  1041. eps_zongMen_mentu(mentu: Xys.mentu, jiuxiao: number = 0){
  1042. let mentu_eps: { [key: string]: number } = {};
  1043. if(!mentu.basicAttr){
  1044. return mentu_eps
  1045. }
  1046. mentu_eps = mentu.basicAttr
  1047. let _mentu = mentu.married?.[Object.keys(mentu.married)[0]]?.mentuInfo;
  1048. if (_mentu && _mentu.basicAttr) {
  1049. // _mentu.basicAttr的值最多不超过mentu.basicAttr的300%
  1050. for (const key in _mentu.basicAttr) {
  1051. if (mentu.basicAttr[key] == null) {
  1052. mentu.basicAttr[key] = 0;
  1053. }
  1054. if (_mentu.basicAttr[key] == null) {
  1055. _mentu.basicAttr[key] = 0;
  1056. }
  1057. let nCfg = Gamecfg.mathInfo.getItem("zongMen_add_basicAttr_limit");
  1058. if (nCfg != null && nCfg.pram != null && nCfg.pram.count != null) {
  1059. _mentu.basicAttr[key] = Math.min( Math.floor(mentu.basicAttr[key] * nCfg.pram.count), _mentu.basicAttr[key] );
  1060. }
  1061. }
  1062. mentu_eps = this.ep_merge(mentu_eps, _mentu.basicAttr);
  1063. }
  1064. return this.ep_KvRate(mentu_eps, 1 + jiuxiao);
  1065. }
  1066. /**
  1067. * 宗门
  1068. *
  1069. */
  1070. ep_zongMen(
  1071. _actZongMenMentuLs1: { [id: string]: Xys.mentu },
  1072. _actZongMenMentuLs2: { [id: string]: Xys.mentu },
  1073. _actZongMen: Xys.ActZongMen,showBasicAttr:boolean = true,
  1074. jiuxiao: number = 0
  1075. ): { [key: string]: number } {
  1076. // 记录基础
  1077. let eps: { [key: string]: number } = {};
  1078. // 记录委任的特殊属性
  1079. let speEps: { [key: string]: number } = {};
  1080. // 拷贝一份数据
  1081. let actZongMenMentuLs1 = gameMethod.objCopy(_actZongMenMentuLs1);
  1082. let actZongMenMentuLs2 = gameMethod.objCopy(_actZongMenMentuLs2);
  1083. let actZongMen = gameMethod.objCopy(_actZongMen);
  1084. // 获取宗门等级配置
  1085. let zm_cfg = Gamecfg.zongMenInfo.getItem(actZongMen.level.toString());
  1086. if (zm_cfg == null) return eps;
  1087. // 委任加属性
  1088. for (const id in actZongMen.appointPos) {
  1089. let mentuId = actZongMen.appointPos[id].mentuId;
  1090. // 获取未结好的门徒信息
  1091. let mentu = actZongMen.mentu[mentuId] || actZongMenMentuLs1[mentuId];
  1092. // 如果获取不到门徒信息,说明是已经结好的门徒,从已结好的门徒列表中获取
  1093. // --------------------------------已经结好的门徒Start--------------------------------
  1094. if (mentu == null) {
  1095. // 结好的门徒有两个门徒,需要分别计算 一个是自己,一个是配偶
  1096. // 1. 特殊属性
  1097. //自己
  1098. mentu = actZongMenMentuLs2[mentuId];
  1099. if (mentu == null) continue;
  1100. let speAttr1 = mentu.speAttr || [];
  1101. // 配偶
  1102. let _mentu = mentu.married?.[Object.keys(mentu.married)[0]]?.mentuInfo;
  1103. let speAttr2 = _mentu?.speAttr || [];
  1104. for (const attrId of speAttr1.concat(speAttr2)) {
  1105. let cfg = Gamecfg.zongMenSpeAttr.getItem(attrId);
  1106. if (cfg != null) {
  1107. if (cfg != null) {
  1108. let [attrKey, attrValue] = Object.entries(cfg.attr)[0];
  1109. const EpsObj = { [attrKey]: attrValue };
  1110. speEps = this.ep_merge(speEps, EpsObj);
  1111. }
  1112. }
  1113. }
  1114. // 2. 出师属性
  1115. let graduateAttr1 = mentu.graduateAttr || {};
  1116. let graduateAttr2 = _mentu?.graduateAttr || {};
  1117. // 先确定值-graduateAttr2不超过graduateAttr1的x倍
  1118. let nCfg = Gamecfg.mathInfo.getItem("zongMen_add_graduateAttr_limit");
  1119. if (nCfg != null && nCfg.pram != null && nCfg.pram.count != null) {
  1120. let value = graduateAttr1[Object.keys(graduateAttr1)[0]]
  1121. graduateAttr2[Object.keys(graduateAttr2)[0]] = Math.min(value * nCfg.pram.count, graduateAttr2[Object.keys(graduateAttr2)[0]]);
  1122. }
  1123. // 根据委任的位置id获取加成配置
  1124. let cfg = Gamecfg.zongMenAppointPos.getItem(id);
  1125. if (cfg == null) continue;
  1126. for (const key in graduateAttr1) {
  1127. graduateAttr1[key] = Math.floor(graduateAttr1[key] * (1 + cfg.add / 100));
  1128. }
  1129. speEps = this.ep_merge(speEps, graduateAttr1);
  1130. for (const key in graduateAttr2) {
  1131. graduateAttr2[key] = Math.floor(graduateAttr2[key] * (1 + cfg.add / 100));
  1132. }
  1133. speEps = this.ep_merge(speEps, graduateAttr2);
  1134. }
  1135. // --------------------------------已经结好的门徒End--------------------------------
  1136. // --------------------------------未结好的门徒Start--------------------------------
  1137. else {
  1138. // 特殊属性
  1139. let speAttr = mentu.speAttr || [];
  1140. for (const attrId of speAttr) {
  1141. let cfg = Gamecfg.zongMenSpeAttr.getItem(attrId);
  1142. if (cfg != null) {
  1143. let [attrKey, attrValue] = Object.entries(cfg.attr)[0];
  1144. const EpsObj = { [attrKey]: attrValue };
  1145. speEps = this.ep_merge(speEps, EpsObj);
  1146. }
  1147. }
  1148. let graduateAttr = mentu.graduateAttr || {};
  1149. // 根据id获取配置
  1150. let cfg = Gamecfg.zongMenAppointPos.getItem(id);
  1151. if (cfg == null) continue;
  1152. for (const key in graduateAttr) {
  1153. graduateAttr[key] = Math.floor(graduateAttr[key] * (1 + cfg.add / 100));
  1154. }
  1155. speEps = this.ep_merge(speEps, graduateAttr);
  1156. }
  1157. // --------------------------------未结好的门徒End--------------------------------
  1158. }
  1159. // 每个门徒的基础属性全部加起来给主角
  1160. if(showBasicAttr){
  1161. for (const id in actZongMen.mentu) {
  1162. eps = this.ep_merge(eps, this.eps_zongMen_mentu(actZongMen.mentu[id], jiuxiao));
  1163. }
  1164. for (const id in actZongMenMentuLs1) {
  1165. eps = this.ep_merge(eps, this.eps_zongMen_mentu(actZongMenMentuLs1[id], jiuxiao));
  1166. }
  1167. for (const id in actZongMenMentuLs2) {
  1168. eps = this.ep_merge(eps, this.eps_zongMen_mentu(actZongMenMentuLs2[id], jiuxiao));
  1169. }
  1170. }
  1171. // 每一条委任的特殊属性都不能超过配置的最大值 zm_cfg.maxSpeAttrAdd
  1172. for (const key in speEps) {
  1173. speEps[key] = Math.min(speEps[key], zm_cfg.maxSpeAttrAdd);
  1174. }
  1175. eps = this.ep_merge(eps, speEps);
  1176. return eps;
  1177. }
  1178. /**
  1179. * 道纹
  1180. * 镶嵌道纹的基础属性 + 词条属性 + 解封等级的属性 + 套装buff
  1181. */
  1182. ep_daowen(actDaoWen: Xys.ActDaoWen, actDdaoWenList: { [iid: string]: Xys.DaoWen_Stone }): { [key: string]: number } {
  1183. let eps_zhu: { [key: string]: number } = this.ep_daowen_zhu(actDaoWen, actDdaoWenList); //主属性
  1184. let eps_other: { [key: string]: number } = this.ep_daowen_other(actDaoWen, actDdaoWenList);; //副属性
  1185. return this.ep_merge(eps_zhu, eps_other);
  1186. }
  1187. /**
  1188. * 道纹
  1189. * 镶嵌道纹的主属性
  1190. */
  1191. ep_daowen_zhu(actDaoWen: Xys.ActDaoWen, actDdaoWenList: { [iid: string]: Xys.DaoWen_Stone }): { [key: string]: number } {
  1192. let eps_zhu: { [key: string]: number } = {}; //主属性
  1193. let real_dc = actDaoWen.dc || "1";
  1194. if (actDaoWen.dcs[real_dc] != null) {
  1195. const slotKeys = Object.keys(actDaoWen.dcs[real_dc].slot);
  1196. for (let i = 0; i < slotKeys.length; i++) {
  1197. const slot = slotKeys[i];
  1198. let iid = actDaoWen.dcs[real_dc].slot[slot];
  1199. let stone = actDdaoWenList[iid.toString()];
  1200. if (stone == null) {
  1201. continue;
  1202. }
  1203. const base_eps_c = Gamecfg.daowenZhushuxing.getItem(stone.baseEps.sxid, stone.baseEps.level.toString());
  1204. if (base_eps_c != null) {
  1205. eps_zhu = this.ep_merge(eps_zhu, base_eps_c.eps);
  1206. }
  1207. }
  1208. }
  1209. return eps_zhu;
  1210. }
  1211. /**
  1212. * 道纹
  1213. * 镶嵌道纹的其他属性
  1214. */
  1215. ep_daowen_other(actDaoWen: Xys.ActDaoWen, actDdaoWenList: { [iid: string]: Xys.DaoWen_Stone }): { [key: string]: number } {
  1216. let eps_fu: { [key: string]: number } = {}; //副属性
  1217. let eps_level: { [key: string]: number } = {}; //解封等级属性
  1218. let real_dc = actDaoWen.dc || "1";
  1219. if (actDaoWen.dcs[real_dc] != null) {
  1220. const slotKeys = Object.keys(actDaoWen.dcs[real_dc].slot);
  1221. for (let i = 0; i < slotKeys.length; i++) {
  1222. const slot = slotKeys[i];
  1223. let iid = actDaoWen.dcs[real_dc].slot[slot];
  1224. let stone = actDdaoWenList[iid.toString()];
  1225. if (stone == null) {
  1226. continue;
  1227. }
  1228. //词条属性
  1229. const fuEpsKeys = Object.keys(stone.fuEps);
  1230. for (let i = 0; i < fuEpsKeys.length; i++) {
  1231. const eps_id = fuEpsKeys[i];
  1232. const ct_info_c = Gamecfg.daowenFushuxing.getItem(
  1233. eps_id,
  1234. stone.fuEps[eps_id].pinzhi.toString(),
  1235. stone.fuEps[eps_id].level.toString()
  1236. );
  1237. if (ct_info_c != null) {
  1238. eps_fu = this.ep_merge(eps_fu, ct_info_c.eps);
  1239. }
  1240. }
  1241. }
  1242. }
  1243. //解封等级的属性
  1244. let level = actDaoWen.unlockLevel;
  1245. const unlock_level_c = Gamecfg.daowenUnlock_level.getItem(level.toString());
  1246. if (unlock_level_c != null) {
  1247. eps_level = this.ep_merge(eps_level, unlock_level_c.eps); //镶嵌效果
  1248. }
  1249. return this.ep_merge(eps_fu, eps_level);
  1250. }
  1251. /**
  1252. * 计算兽灵单个格子属性加成
  1253. */
  1254. ep_shouling_gezi(actShouLingOne: Xys.ActShouLing_ListOne, jiuxiao: number = 0): { [key: string]: number } {
  1255. let eps: { [key: string]: number } = {};
  1256. if (actShouLingOne == null || actShouLingOne.slid == "") {
  1257. return eps;
  1258. }
  1259. let slid = actShouLingOne.slid;
  1260. let cfgInfo = Gamecfg.shoulingInfo.getItem(slid);
  1261. if (cfgInfo == null) {
  1262. return eps;
  1263. }
  1264. let cfgPinzhi = Gamecfg.shoulingPinzhi.getItem(cfgInfo.pinzhi);
  1265. if (cfgPinzhi == null) {
  1266. return eps;
  1267. }
  1268. //兽灵基础属性
  1269. eps = this.ep_merge(eps, cfgPinzhi.eps);
  1270. //九霄天枢对兽灵基本属性加成
  1271. if(jiuxiao > 0){
  1272. eps = this.ep_KvRate(eps, 1 + jiuxiao);
  1273. }
  1274. //升级属性加成
  1275. const level = actShouLingOne.level;
  1276. let levelEps: { [key: string]: number } = {};
  1277. for (let i = 1; i <= level; i++) {
  1278. let lv = Gamecfg.shoulingLevel.getItem(cfgPinzhi.id, i.toString());
  1279. if (lv == null) {
  1280. continue;
  1281. }
  1282. levelEps = this.ep_merge(levelEps, lv.levelEps);
  1283. }
  1284. eps = this.ep_merge(eps, levelEps);
  1285. //计算升星属性加成
  1286. const star = actShouLingOne.star;
  1287. let starEps: { [key: string]: number } = {};
  1288. for (let index = star; index >= 0; index--) {
  1289. let star_c = Gamecfg.shoulingStar.getItem(cfgPinzhi.id, index.toString());
  1290. if (star_c == null) {
  1291. continue;
  1292. }
  1293. starEps = this.ep_merge(starEps, star_c.starEps);
  1294. }
  1295. eps = this.ep_merge(eps, starEps);
  1296. //计算觉醒属性加成
  1297. let stepEps: { [key: string]: number } = {};
  1298. const step = actShouLingOne.step;
  1299. let jueXingCfg = Gamecfg.shoulingJuexing.getItem(step.toString());
  1300. if(jueXingCfg){
  1301. stepEps = this.ep_merge(stepEps, jueXingCfg.eps);
  1302. }
  1303. eps = this.ep_merge(eps, stepEps);
  1304. //皮肤属性
  1305. let skinEps: { [key: string]: number } = {};
  1306. if (actShouLingOne.skins == null) {
  1307. return eps;
  1308. }
  1309. for (const skinId in actShouLingOne.skins) {
  1310. let skin = actShouLingOne.skins[skinId];
  1311. let skinCfg = Gamecfg.shoulingLevel.getItem(skinId, skin.level.toString());
  1312. if (skinCfg) {
  1313. skinEps = this.ep_merge(skinEps, skinCfg.levelEps);
  1314. }
  1315. }
  1316. eps = this.ep_merge(eps, skinEps);
  1317. return eps;
  1318. }
  1319. /**
  1320. * 计算异象属性加成
  1321. */
  1322. ep_yixiang(actYiXiang: Xys.ActYiXiang): { [key: string]: number } {
  1323. let eps: { [key: string]: number } = {};
  1324. //计算升级升阶异象属性
  1325. const cfg = Gamecfg.yixiangLevel.getItem(actYiXiang.id.toString());
  1326. if (cfg == null) {
  1327. return eps;
  1328. }
  1329. const cfgJieJi = Gamecfg.yixiangJieji.getItem(cfg.step.toString());
  1330. if (cfgJieJi == null) {
  1331. return eps;
  1332. }
  1333. eps = this.ep_merge(eps, cfg.ep0);
  1334. eps = this.ep_merge(eps, cfgJieJi.ep1);
  1335. //计算上阵异象属性
  1336. const cfgStep = Gamecfg.yixiangStep.getItem(actYiXiang.hh, cfg.step.toString());
  1337. if (cfgStep == null) {
  1338. return eps;
  1339. }
  1340. // 计算化形属性
  1341. for(let id in actYiXiang.hxData){
  1342. let cfgHx = Gamecfg.yixiangHuaxing.getItem(id,actYiXiang.hxData[id].level.toString())
  1343. if(cfgHx != null){
  1344. eps = this.ep_merge(eps, cfgHx.levelEps);
  1345. }
  1346. }
  1347. eps = this.ep_merge(eps, cfgStep.ep);
  1348. return eps;
  1349. }
  1350. /**
  1351. * 计算皮肤属性加成
  1352. */
  1353. ep_pifu(actPifu: Xys.ActPifu): { [key: string]: number } {
  1354. let eps: { [key: string]: number } = {};
  1355. for (const key in actPifu.list) {
  1356. let pifu = actPifu.list[key];
  1357. if(!pifu){
  1358. continue;
  1359. }
  1360. if(!pifu.level){
  1361. pifu.level = 1;
  1362. }
  1363. //计算皮肤属性属性
  1364. const cfg = Gamecfg.skinSkinlevel.getItem(key.toString(), pifu.level.toString());
  1365. if (cfg == null) {
  1366. continue;
  1367. }
  1368. eps = this.ep_merge(eps, cfg.levelEps);
  1369. }
  1370. return eps;
  1371. }
  1372. /**
  1373. * 计算洞天道童属性加成
  1374. */
  1375. ep_dongtian(actDongTian: Xys.ActDongTian): { [key: string]: number } {
  1376. let eps: { [key: string]: number } = {};
  1377. //计算道童等级属性加成
  1378. const xlLvKeys = Object.keys(actDongTian.xlLv);
  1379. for (let i = 0; i < xlLvKeys.length; i++) {
  1380. const type = xlLvKeys[i];
  1381. let cfg = Gamecfg.dongtianXlLv.getItem(type, actDongTian.xlLv[type].toString());
  1382. if (cfg == null) {
  1383. continue;
  1384. }
  1385. eps = this.ep_merge(eps, cfg.eps);
  1386. }
  1387. let cfgStep = Gamecfg.dongtianXlStep.getItem(actDongTian.xlStep.toString());
  1388. if (cfgStep == null) {
  1389. return eps;
  1390. }
  1391. const epsKeys = Object.keys(eps);
  1392. for (let i = 0; i < epsKeys.length; i++) {
  1393. const key = epsKeys[i];
  1394. eps[key] *= cfgStep.eps / 10000;
  1395. }
  1396. return eps;
  1397. }
  1398. /**
  1399. * 计算药田属性加成
  1400. */
  1401. ep_yaotian(actYaoTianEps: Xys.ActYaoTianEps): { [key: string]: number } {
  1402. let eps: { [key: string]: number } = {};
  1403. for (let key in actYaoTianEps) {
  1404. eps[key] = Math.floor(actYaoTianEps[key]);
  1405. }
  1406. return eps;
  1407. }
  1408. /**
  1409. * 计算称号属性加成
  1410. */
  1411. ep_chenghao(actChenghao: Xys.ActChenghao): { [key: string]: number } {
  1412. let eps: { [key: string]: number } = {};
  1413. for(let id in actChenghao.list){
  1414. let cfg = Gamecfg.chenghaoShuxing.getItem(id)
  1415. if(cfg != null){
  1416. eps = this.ep_merge(eps, cfg.eps)
  1417. }
  1418. }
  1419. return eps;
  1420. }
  1421. // /**
  1422. // * 分别统计主角和弟子的的战斗属性
  1423. // */
  1424. ep_userAndDiZi(sevBack: Xys.SevBack) {
  1425. let allEps: any = {};
  1426. let userBase = gameMethod.ep_all_base(sevBack);
  1427. allEps["user"] = userBase
  1428. let userEps = gameMethod.ep_all_fight(userBase);
  1429. for (let gzid in sevBack.actDiZi?.a?.shangZhen) {
  1430. let eps: { [key: string]: number } = {};
  1431. let dzId = sevBack.actDiZi?.a?.shangZhen[gzid];
  1432. if (dzId == null || dzId == "") {
  1433. continue;
  1434. }
  1435. let cfgdz = Gamecfg.huobanBase.getItem(dzId);
  1436. let dizi = sevBack.actDiZiList?.a?.[dzId];
  1437. if (cfgdz == null || dizi == null || cfgdz.zhanli == 0) {
  1438. continue;
  1439. }
  1440. let cfgZhongZu = Gamecfg.huobanZhongzu.getItem(cfgdz.pinzhi, cfgdz.zhongzu.toString());
  1441. if (cfgZhongZu == null) {
  1442. continue;
  1443. }
  1444. //计算弟子升级属性
  1445. let levelEps: { [key: string]: number } = {};
  1446. for (let i = 1; i <= dizi.level; i++) {
  1447. const diziLevel = Gamecfg.huobanShengji.getItem(cfgdz.pinzhi, i.toString());
  1448. if (diziLevel == null) {
  1449. continue;
  1450. }
  1451. levelEps = this.ep_merge(levelEps, diziLevel.attr);
  1452. }
  1453. //九霄天枢对弟子基础属性加成
  1454. for (const hdcid in sevBack.hdJiuXiaoTianShu) {
  1455. // 检查属性是否存在
  1456. if (!Object.prototype.hasOwnProperty.call(sevBack.hdJiuXiaoTianShu, hdcid)) {
  1457. continue;
  1458. }
  1459. let jiuxiao = sevBack.hdJiuXiaoTianShu?.[hdcid]?.a;
  1460. if (!jiuxiao) {
  1461. continue;
  1462. }
  1463. // 检查伙伴属性加成是否大于0
  1464. if (jiuxiao.huoBanEps > 0) {
  1465. let rate = 1 + (jiuxiao.huoBanEps / 100);
  1466. levelEps = this.ep_KvRate(levelEps, rate);
  1467. }
  1468. }
  1469. eps = this.ep_merge(eps, levelEps);
  1470. //计算弟子升星的基础属性加成
  1471. let starEps: { [key: string]: number } = {};
  1472. for (let i = 1; i <= dizi.star; i++) {
  1473. const diziStar = Gamecfg.huobanStar.getItem(cfgdz.id, i.toString());
  1474. if (diziStar == null) {
  1475. continue;
  1476. }
  1477. starEps = this.ep_merge(starEps, diziStar.attr2);
  1478. }
  1479. eps = this.ep_merge(eps, starEps);
  1480. //计算弟子境界属性
  1481. let jingjieEps: { [key: string]: number } = {};
  1482. for (let i = 1; i <= dizi.jingjie; i++) {
  1483. const diziJingjie = Gamecfg.huobanTupo.getItem(cfgdz.pinzhi, i.toString());
  1484. if (diziJingjie == null) {
  1485. continue;
  1486. }
  1487. jingjieEps = this.ep_merge(jingjieEps, diziJingjie.attr);
  1488. }
  1489. eps = this.ep_merge(eps, jingjieEps);
  1490. let dzEps: { [key: string]: number } = gameMethod.ep_init(); //初始化属性
  1491. dzEps = gameMethod.ep_merge(dzEps, cfgdz.eps);
  1492. for (const key in cfgZhongZu.inherit_attr) {
  1493. //继承主角属性
  1494. dzEps[key] += Math.floor((userEps[key] * cfgZhongZu.inherit_attr[key]) / 10000);
  1495. }
  1496. for (const key in cfgZhongZu.inherit_attr_hide) {
  1497. //继承主角属性
  1498. dzEps[key] += Math.floor((userEps[key] * cfgZhongZu.inherit_attr_hide[key]) / 10000);
  1499. }
  1500. eps = gameMethod.ep_merge(eps, dzEps);
  1501. allEps[`${dzId}_${cfgdz.dzName}`] = eps;
  1502. }
  1503. return allEps;
  1504. }
  1505. /**
  1506. * 计算角色总战力
  1507. * jiuxiao: 对弟子基础属性加成
  1508. */
  1509. ep_power_all(sevBack: Xys.SevBack, ep_all_base: { [key: string]: number } = {}) {
  1510. let userBase: { [key: string]: number } = {};
  1511. if (gameMethod.isEmpty(ep_all_base) == false) {
  1512. userBase = ep_all_base;
  1513. } else {
  1514. userBase = gameMethod.ep_all_base(sevBack);
  1515. }
  1516. let userEps = gameMethod.ep_all_fight(userBase)
  1517. let diziPower: number = 0;
  1518. for (let gzid in sevBack.actDiZi?.a?.shangZhen) {
  1519. let diziEps: { [key: string]: number } = {};
  1520. let dzId = sevBack.actDiZi?.a?.shangZhen[gzid];
  1521. if (dzId == null || dzId == "") {
  1522. continue;
  1523. }
  1524. let cfgdz = Gamecfg.huobanBase.getItem(dzId);
  1525. let dizi = sevBack.actDiZiList?.a?.[dzId];
  1526. if (cfgdz == null || dizi == null || cfgdz.zhanli == 0) {
  1527. continue;
  1528. }
  1529. let cfgZhongZu = Gamecfg.huobanZhongzu.getItem(cfgdz.pinzhi, cfgdz.zhongzu.toString());
  1530. if (cfgZhongZu == null) {
  1531. continue;
  1532. }
  1533. //计算弟子升级属性
  1534. let levelEps: { [key: string]: number } = {};
  1535. for (let i = 1; i <= dizi.level; i++) {
  1536. const diziLevel = Gamecfg.huobanShengji.getItem(cfgdz.pinzhi, i.toString());
  1537. if (diziLevel == null) {
  1538. continue;
  1539. }
  1540. levelEps = this.ep_merge(levelEps, diziLevel.attr);
  1541. }
  1542. //九霄天枢对弟子基础属性加成
  1543. for (const hdcid in sevBack.hdJiuXiaoTianShu) {
  1544. // 检查属性是否存在
  1545. if (!Object.prototype.hasOwnProperty.call(sevBack.hdJiuXiaoTianShu, hdcid)) {
  1546. continue;
  1547. }
  1548. let jiuxiao = sevBack.hdJiuXiaoTianShu?.[hdcid]?.a;
  1549. if (!jiuxiao) {
  1550. continue;
  1551. }
  1552. // 检查伙伴属性加成是否大于0
  1553. if (jiuxiao.huoBanEps > 0) {
  1554. let rate = 1 + (jiuxiao.huoBanEps / 100);
  1555. levelEps = this.ep_KvRate(levelEps, rate);
  1556. }
  1557. }
  1558. diziEps = this.ep_merge(diziEps, levelEps);
  1559. //计算弟子升星的基础属性加成
  1560. let starEps: { [key: string]: number } = {};
  1561. for (let i = 1; i <= dizi.star; i++) {
  1562. const diziStar = Gamecfg.huobanStar.getItem(cfgdz.id, i.toString());
  1563. if (diziStar == null) {
  1564. continue;
  1565. }
  1566. starEps = this.ep_merge(starEps, diziStar.attr2);
  1567. }
  1568. diziEps = this.ep_merge(diziEps, starEps);
  1569. //计算弟子境界属性
  1570. let jingjieEps: { [key: string]: number } = {};
  1571. for (let i = 1; i <= dizi.jingjie; i++) {
  1572. const diziJingjie = Gamecfg.huobanTupo.getItem(cfgdz.pinzhi, i.toString());
  1573. if (diziJingjie == null) {
  1574. continue;
  1575. }
  1576. jingjieEps = this.ep_merge(jingjieEps, diziJingjie.attr);
  1577. }
  1578. diziEps = this.ep_merge(diziEps, jingjieEps);
  1579. let dzEps: { [key: string]: number } = gameMethod.ep_init(); //初始化属性
  1580. dzEps = gameMethod.ep_merge(dzEps, cfgdz.eps);
  1581. for (const key in cfgZhongZu.inherit_attr) {
  1582. //继承主角属性
  1583. dzEps[key] += Math.floor((userEps[key] * cfgZhongZu.inherit_attr[key]) / 10000);
  1584. }
  1585. for (const key in cfgZhongZu.inherit_attr_hide) {
  1586. //继承主角属性
  1587. dzEps[key] += Math.floor((userEps[key] * cfgZhongZu.inherit_attr_hide[key]) / 10000);
  1588. }
  1589. diziEps = this.ep_merge(diziEps, dzEps);
  1590. diziPower += gameMethod.ep_power(0, diziEps);
  1591. }
  1592. // 兽灵战力
  1593. let slPower: number = 0;
  1594. if (sevBack.actShouLing != null && sevBack.actShouLingList != null && sevBack.actShouLing.a && sevBack.actShouLingList.a) {
  1595. const useGzIdKeys = Object.keys(sevBack.actShouLing.a.useGzId);
  1596. for (let i = 0; i < useGzIdKeys.length; i++) {
  1597. const useGzId = useGzIdKeys[i];
  1598. let gzid = sevBack.actShouLing.a.useGzId[useGzId];
  1599. if (gzid == null || gzid == "") {
  1600. continue;
  1601. }
  1602. let shouling = sevBack.actShouLingList.a[gzid];
  1603. if (shouling == null) {
  1604. continue;
  1605. }
  1606. /*let cfg = Gamecfg.shoulingInfo.getItem(shouling.slid);
  1607. if (cfg == null) {
  1608. continue;
  1609. }
  1610. let pinzhiCfg = Gamecfg.shoulingPinzhi.getItem(cfg.pinzhi);
  1611. if (pinzhiCfg == null) {
  1612. continue;
  1613. }*/
  1614. //主战
  1615. if (useGzId == "0") {
  1616. let skill = shouling.sk;
  1617. let step = shouling.step
  1618. let skillCfg = Gamecfg.spellSkill.getItem(skill.skillId, skill.lv.toString(), step.toString());
  1619. if (skillCfg == null) {
  1620. continue;
  1621. }
  1622. slPower += skillCfg.zhanli;
  1623. } else {
  1624. // 助战位
  1625. let skill = shouling.sk;
  1626. let step = shouling.step
  1627. let skillCfg = Gamecfg.spellSkill.getItem(skill.skillId, skill.lv.toString(), step.toString());
  1628. if (skillCfg == null) {
  1629. continue;
  1630. }
  1631. slPower += skillCfg.zhanli;
  1632. }
  1633. }
  1634. }
  1635. return diziPower + gameMethod.ep_power(0, userBase) + slPower;
  1636. }
  1637. ep_power_dizi(sevBack: Xys.SevBack, dzId: string) {
  1638. let userEps = gameMethod.ep_all(sevBack);
  1639. let diziEps: { [key: string]: number } = {};
  1640. if (dzId == null || dzId == "") {
  1641. return 0;
  1642. }
  1643. let cfgdz = Gamecfg.huobanBase.getItem(dzId);
  1644. let dizi = sevBack.actDiZiList?.a?.[dzId];
  1645. if (cfgdz == null || dizi == null || cfgdz.zhanli == 0) {
  1646. return 0;
  1647. }
  1648. let cfgZhongZu = Gamecfg.huobanZhongzu.getItem(cfgdz.pinzhi, cfgdz.zhongzu.toString());
  1649. if (cfgZhongZu == null) {
  1650. return 0;
  1651. }
  1652. //计算弟子升级属性
  1653. let levelEps: { [key: string]: number } = {};
  1654. for (let i = 1; i <= dizi.level; i++) {
  1655. const diziLevel = Gamecfg.huobanShengji.getItem(cfgdz.pinzhi, i.toString());
  1656. if (diziLevel == null) {
  1657. continue;
  1658. }
  1659. levelEps = this.ep_merge(levelEps, diziLevel.attr);
  1660. }
  1661. //九霄天枢对弟子基础属性加成
  1662. for (const hdcid in sevBack.hdJiuXiaoTianShu) {
  1663. // 检查属性是否存在
  1664. if (!Object.prototype.hasOwnProperty.call(sevBack.hdJiuXiaoTianShu, hdcid)) {
  1665. continue;
  1666. }
  1667. let jiuxiao = sevBack.hdJiuXiaoTianShu?.[hdcid]?.a;
  1668. if (!jiuxiao) {
  1669. continue;
  1670. }
  1671. // 检查伙伴属性加成是否大于0
  1672. if (jiuxiao.huoBanEps > 0) {
  1673. let rate = 1 + (jiuxiao.huoBanEps / 100);
  1674. levelEps = this.ep_KvRate(levelEps, rate);
  1675. }
  1676. }
  1677. diziEps = this.ep_merge(diziEps, levelEps);
  1678. //计算弟子升星的基础属性加成
  1679. let starEps: { [key: string]: number } = {};
  1680. for (let i = 1; i <= dizi.star; i++) {
  1681. const diziStar = Gamecfg.huobanStar.getItem(cfgdz.id, i.toString());
  1682. if (diziStar == null) {
  1683. continue;
  1684. }
  1685. starEps = this.ep_merge(starEps, diziStar.attr2);
  1686. }
  1687. diziEps = this.ep_merge(diziEps, starEps);
  1688. //计算弟子境界属性
  1689. let jingjieEps: { [key: string]: number } = {};
  1690. for (let i = 1; i <= dizi.jingjie; i++) {
  1691. const diziJingjie = Gamecfg.huobanTupo.getItem(cfgdz.pinzhi, i.toString());
  1692. if (diziJingjie == null) {
  1693. continue;
  1694. }
  1695. jingjieEps = this.ep_merge(jingjieEps, diziJingjie.attr);
  1696. }
  1697. diziEps = this.ep_merge(diziEps, jingjieEps);
  1698. let dzEps: { [key: string]: number } = gameMethod.ep_init(); //初始化属性
  1699. dzEps = gameMethod.ep_merge(dzEps, cfgdz.eps);
  1700. for (const key in cfgZhongZu.inherit_attr) {
  1701. //继承主角属性
  1702. dzEps[key] += Math.floor((userEps[key] * cfgZhongZu.inherit_attr[key]) / 10000);
  1703. }
  1704. for (const key in cfgZhongZu.inherit_attr_hide) {
  1705. //继承主角属性
  1706. dzEps[key] += Math.floor((userEps[key] * cfgZhongZu.inherit_attr_hide[key]) / 10000);
  1707. }
  1708. diziEps = this.ep_merge(diziEps, dzEps);
  1709. return gameMethod.ep_power(0, diziEps);
  1710. }
  1711. /**
  1712. * 计算阵法更换的战力变化值 (弃用)
  1713. */
  1714. ep_power_zhenfa(sevBack: Xys.SevBack, linshi: { pfid: string; level: number; eps: { [key: string]: number }; pinzhi: string }): number {
  1715. //原本的战力
  1716. const initPower = this.ep_power_all(sevBack);
  1717. let newSevBack = gameMethod.objCopy(sevBack);
  1718. if (newSevBack.actZhenfa == null || newSevBack.actZhenfa.a == null) {
  1719. return 0;
  1720. }
  1721. let cfgpf = Gamecfg.zhenfaPifu.getItem(linshi.pfid);
  1722. if (cfgpf == null) {
  1723. return 0;
  1724. }
  1725. if (newSevBack.actZhenfa.a.chuan[cfgpf.buwei] == null) {
  1726. newSevBack.actZhenfa.a.chuan[cfgpf.buwei] = {
  1727. pfid: "",
  1728. level: 0,
  1729. eps: {},
  1730. fmLv: 0,
  1731. fmBd: 0,
  1732. fmEps: [],
  1733. fmZhBd: [],
  1734. fmZhls: [],
  1735. pinzhi: "",
  1736. };
  1737. }
  1738. newSevBack.actZhenfa.a.chuan[cfgpf.buwei].pfid = linshi.pfid;
  1739. newSevBack.actZhenfa.a.chuan[cfgpf.buwei].level = linshi.level;
  1740. newSevBack.actZhenfa.a.chuan[cfgpf.buwei].eps = linshi.eps;
  1741. newSevBack.actZhenfa.a.chuan[cfgpf.buwei].pinzhi = linshi.pinzhi;
  1742. const newPower = this.ep_power_all(newSevBack);
  1743. return newPower - initPower;
  1744. }
  1745. /**
  1746. * 计算阵法更换的战力变化值
  1747. */
  1748. ep_power_zhenfaNew(sevBack: Xys.SevBack, linshi: { pfid: string; level: number; eps: { [key: string]: number }; pinzhi: string }): number {
  1749. if (sevBack.actZhenfaNew == null || sevBack.actZhenfaNew.a == null || sevBack.actZhenfaNew.a.chuan == null) {
  1750. return 0;
  1751. }
  1752. let cfgpf = Gamecfg.zhenfaPifu.getItem(linshi.pfid);
  1753. if (cfgpf == null) {
  1754. return 0;
  1755. }
  1756. let oldCeps: { [key: string]: number } = {};
  1757. if (sevBack.actZhenfaNew.a.chuan[cfgpf.buwei] != null) {
  1758. oldCeps = sevBack.actZhenfaNew.a.chuan[cfgpf.buwei].eps;
  1759. }
  1760. //原本的战力
  1761. const initPower = this.ep_power_all(sevBack);
  1762. let ep_base = this.ep_all_base(sevBack);
  1763. for (const key in oldCeps) {
  1764. ep_base[key] -= oldCeps[key];
  1765. }
  1766. for (const key in linshi.eps) {
  1767. ep_base[key] += linshi.eps[key];
  1768. }
  1769. const newPower = this.ep_power_all(sevBack, ep_base);
  1770. return newPower - initPower;
  1771. }
  1772. /**
  1773. * 计算已经穿戴的装备属性
  1774. */
  1775. ep_power_zhenfaNew_chuan(sevBack: Xys.SevBack, buwei:string): number {
  1776. if (sevBack.actZhenfaNew == null || sevBack.actZhenfaNew.a == null || sevBack.actZhenfaNew.a.chuan == null) {
  1777. return 0;
  1778. }
  1779. //原本的战力
  1780. const initPower = this.ep_power_all(sevBack);
  1781. let oldCeps: { [key: string]: number } = {};
  1782. if (sevBack.actZhenfaNew.a.chuan[buwei] != null) {
  1783. let chuan = sevBack.actZhenfaNew.a.chuan[buwei]
  1784. oldCeps = this.ep_merge(oldCeps, chuan.eps);
  1785. for (const fmEps of chuan.fmEps) {
  1786. if (oldCeps[fmEps[0]] == null) {
  1787. oldCeps[fmEps[0]] = 0;
  1788. }
  1789. oldCeps[fmEps[0]] += fmEps[1];
  1790. }
  1791. // 洗练属性
  1792. for (const posId in chuan.xilianEps) {
  1793. if (chuan.xilianEps[posId].id == null || chuan.xilianEps[posId].id == "") {
  1794. continue;
  1795. }
  1796. let xilian_c = Gamecfg.zhenfaXilianWord.getItem(chuan.xilianEps[posId].id);
  1797. if (xilian_c != null) {
  1798. oldCeps = this.ep_merge(oldCeps, xilian_c.attr);
  1799. }
  1800. }
  1801. }
  1802. let ep_base = this.ep_all_base(sevBack);
  1803. for (const key in oldCeps) {
  1804. ep_base[key] -= oldCeps[key];
  1805. }
  1806. const newPower = this.ep_power_all(sevBack, ep_base);
  1807. return newPower - initPower;
  1808. }
  1809. /**
  1810. * 计算阵法更换的战力变化值
  1811. */
  1812. ep_power_guzi(sevBack: Xys.SevBack, linshi: Xys.lishiGZInfo): number {
  1813. //原本的战力
  1814. let oldCeps: { [key: string]: number } = {};
  1815. if (
  1816. sevBack.actDadiGuzi != null &&
  1817. sevBack.actDadiGuzi.a != null &&
  1818. sevBack.actDadiGuzi.a.mpList != null &&
  1819. sevBack.actDadiGuzi.a.mpXhid != null &&
  1820. sevBack.actDadiGuzi.a.mpList[sevBack.actDadiGuzi.a.mpXhid] != null &&
  1821. sevBack.actDadiGuzi.a.mpList[sevBack.actDadiGuzi.a.mpXhid][linshi.buwei] != null
  1822. ) {
  1823. oldCeps = sevBack.actDadiGuzi.a.mpList[sevBack.actDadiGuzi.a.mpXhid][linshi.buwei].eps;
  1824. }
  1825. let ep_base = this.ep_all_base(sevBack);
  1826. let ep_base2 = gameMethod.objCopy(ep_base);
  1827. ep_base.atk += Math.floor((ep_base.atk * ep_base.atk_per) / 10000);
  1828. ep_base.def += Math.floor((ep_base.def * ep_base.def_per) / 10000);
  1829. ep_base.hp_max += Math.floor((ep_base.hp_max * ep_base.hp_max_per) / 10000);
  1830. ep_base.hp = ep_base.hp_max;
  1831. const initPower = this.ep_power(0, ep_base);
  1832. for (const key in oldCeps) {
  1833. ep_base2[key] -= oldCeps[key];
  1834. }
  1835. for (const key in linshi.eps) {
  1836. ep_base2[key] += linshi.eps[key];
  1837. }
  1838. ep_base2.atk += Math.floor((ep_base2.atk * ep_base2.atk_per) / 10000);
  1839. ep_base2.def += Math.floor((ep_base2.def * ep_base2.def_per) / 10000);
  1840. ep_base2.hp_max += Math.floor((ep_base2.hp_max * ep_base2.hp_max_per) / 10000);
  1841. ep_base2.hp = ep_base2.hp_max;
  1842. const newPower = this.ep_power(0, ep_base2);
  1843. return newPower - initPower;
  1844. }
  1845. // 计算门徒的战力
  1846. ep_power_mentu(mentu: Xys.mentu) {
  1847. let power = 0;
  1848. // 基础属性
  1849. power += this.ep_power(0, mentu.basicAttr);
  1850. // 特殊属性
  1851. if (mentu.speAttr != null) {
  1852. for (const id of mentu.speAttr) {
  1853. let specialCfg = Gamecfg.zongMenSpeAttr.getItem(id + "");
  1854. if (specialCfg == null) {
  1855. continue;
  1856. }
  1857. power += this.ep_power(0, specialCfg.attr);
  1858. }
  1859. }
  1860. return power;
  1861. }
  1862. /**
  1863. * 属性转化成战力
  1864. * @param type 默认 0默认 1怪物
  1865. * @param eps 属性消息
  1866. * @returns
  1867. */
  1868. ep_power(type: number, _eps: { [key: string]: number } | any): number {
  1869. let eps = gameMethod.ep_init();
  1870. eps = gameMethod.ep_merge(eps, _eps);
  1871. eps = gameMethod.ep_all_fight(eps)
  1872. let power: number = 0;
  1873. let cfgEpPool = Gamecfg.userEp.pool;
  1874. for (const key in cfgEpPool) {
  1875. let rpKey = cfgEpPool[key].key;
  1876. if (eps[rpKey] == null || typeof eps[rpKey] != "number") {
  1877. continue;
  1878. }
  1879. let xishu = 0;
  1880. switch (type) {
  1881. case 1:
  1882. if (gameMethod.isEmpty(cfgEpPool[key].momPower) == true) {
  1883. continue;
  1884. }
  1885. xishu = cfgEpPool[key].momPower;
  1886. break;
  1887. default:
  1888. if (gameMethod.isEmpty(cfgEpPool[key].power) == true) {
  1889. continue;
  1890. }
  1891. xishu = cfgEpPool[key].power;
  1892. break;
  1893. }
  1894. let addPower = Math.floor(xishu * eps[rpKey]);
  1895. power += addPower;
  1896. }
  1897. return power;
  1898. }
  1899. //获取药田吃药加成的属性
  1900. eps_yaofang(count: number, danyao: { naiyao: number; shiyong: number }, yx: number[], eps: { [key: string]: number }) {
  1901. let needCount = count;
  1902. let shiyong: any = {};
  1903. while (needCount > 0) {
  1904. //要降级
  1905. if (danyao.shiyong + needCount >= yx[0] && danyao.naiyao > yx[2]) {
  1906. needCount -= yx[0] - danyao.shiyong;
  1907. //记录食用
  1908. shiyong[danyao.naiyao] = yx[0] - danyao.shiyong;
  1909. danyao.shiyong = 0;
  1910. danyao.naiyao -= yx[1];
  1911. danyao.naiyao = Math.max(danyao.naiyao, yx[2]);
  1912. } else {
  1913. if (danyao.naiyao == 100) {
  1914. //耐药等于最低的时候不加shiyong数量只加count数量
  1915. shiyong[danyao.naiyao] = needCount;
  1916. needCount -= needCount;
  1917. } else {
  1918. danyao.shiyong += needCount;
  1919. //记录食用
  1920. shiyong[danyao.naiyao] = needCount;
  1921. needCount -= needCount;
  1922. }
  1923. }
  1924. }
  1925. let epsAll: any = {};
  1926. for (let naiyao in shiyong) {
  1927. //遍历食用加属性
  1928. for (let key in eps) {
  1929. if (epsAll[key] == null) {
  1930. epsAll[key] = 0;
  1931. }
  1932. epsAll[key] += (eps[key] * shiyong[naiyao] * Number(naiyao)) / 10000;
  1933. }
  1934. }
  1935. for (let key in epsAll) {
  1936. epsAll[key] = Math.floor(epsAll[key]);
  1937. }
  1938. return epsAll;
  1939. }
  1940. //计算弟子战斗自身属性(不包括继承主角的属性)
  1941. ep_diziEps(sevBack: Xys.SevBack, dzId: string): { [key: string]: number } {
  1942. let diziEps: { [key: string]: number } = gameMethod.ep_init(); //初始化属性
  1943. if (dzId == null || dzId == "") {
  1944. return diziEps;
  1945. }
  1946. let cfgdz = Gamecfg.huobanBase.getItem(dzId);
  1947. let dizi = sevBack.actDiZiList?.a?.[dzId];
  1948. if (cfgdz == null || dizi == null || cfgdz.zhanli == 0) {
  1949. return diziEps;
  1950. }
  1951. //弟子基础属性
  1952. diziEps = this.ep_merge(diziEps, cfgdz.eps);
  1953. let cfgZhongZu = Gamecfg.huobanZhongzu.getItem(cfgdz.pinzhi, cfgdz.zhongzu.toString());
  1954. if (cfgZhongZu == null) {
  1955. return diziEps;
  1956. }
  1957. //计算弟子升级属性
  1958. let levelEps: { [key: string]: number } = {};
  1959. for (let i = 1; i <= dizi.level; i++) {
  1960. const diziLevel = Gamecfg.huobanShengji.getItem(cfgdz.pinzhi, i.toString());
  1961. if (diziLevel == null) {
  1962. continue;
  1963. }
  1964. levelEps = this.ep_merge(levelEps, diziLevel.attr);
  1965. }
  1966. //九霄天枢对弟子基础属性加成
  1967. for (const hdcid in sevBack.hdJiuXiaoTianShu) {
  1968. // 检查属性是否存在
  1969. if (!Object.prototype.hasOwnProperty.call(sevBack.hdJiuXiaoTianShu, hdcid)) {
  1970. continue;
  1971. }
  1972. let jiuxiao = sevBack.hdJiuXiaoTianShu?.[hdcid]?.a;
  1973. if (!jiuxiao) {
  1974. continue;
  1975. }
  1976. // 检查伙伴属性加成是否大于0
  1977. if (jiuxiao.huoBanEps > 0) {
  1978. let rate = 1 + (jiuxiao.huoBanEps / 100);
  1979. levelEps = this.ep_KvRate(levelEps, rate);
  1980. }
  1981. }
  1982. diziEps = this.ep_merge(diziEps, levelEps);
  1983. //计算弟子升星的基础属性加成
  1984. let starEps: { [key: string]: number } = {};
  1985. for (let i = 1; i <= dizi.star; i++) {
  1986. const diziStar = Gamecfg.huobanStar.getItem(cfgdz.id, i.toString());
  1987. if (diziStar == null) {
  1988. continue;
  1989. }
  1990. starEps = this.ep_merge(starEps, diziStar.attr2);
  1991. }
  1992. diziEps = this.ep_merge(diziEps, starEps);
  1993. //计算弟子境界属性
  1994. let jingjieEps: { [key: string]: number } = {};
  1995. for (let i = 1; i <= dizi.jingjie; i++) {
  1996. const diziJingjie = Gamecfg.huobanTupo.getItem(cfgdz.pinzhi, i.toString());
  1997. if (diziJingjie == null) {
  1998. continue;
  1999. }
  2000. jingjieEps = this.ep_merge(jingjieEps, diziJingjie.attr);
  2001. }
  2002. diziEps = this.ep_merge(diziEps, jingjieEps);
  2003. return diziEps;
  2004. }
  2005. //获取模块的属性加成
  2006. ep_act(sevBack: Xys.SevBack, key: string): { [key: string]: number } {
  2007. let eps = this.ep_init();
  2008. if (sevBack.actEps != null && sevBack.actEps.a != null && sevBack.actEps.a[key] != null) {
  2009. eps = gameMethod.ep_merge(eps, sevBack.actEps.a[key]);
  2010. }
  2011. return eps;
  2012. }
  2013. /**
  2014. * 解析洞天 矿车数据
  2015. * @param carInfo
  2016. * @param now
  2017. * @returns edtime //离结束 还有多长时间 (0 已完成 )(未开始 -1)
  2018. * @returns win //胜利方是谁 0守方 1攻方 (未开始默认0)
  2019. * @returns nowpos nowpos, //当前位置
  2020. */
  2021. getDongTianCar(carInfo: Xys.ActDongTian_CarInfo | any, now: number): Xys.ActDongTian_Carshow {
  2022. if (carInfo.stime <= 0) {
  2023. //未启动
  2024. return {
  2025. edtime: -1, //离结束 还有多长时间
  2026. win: 0, //胜利方是谁 0守方 1攻方 (未开始默认0)
  2027. nowpos: carInfo.dpos, //当前位置
  2028. };
  2029. }
  2030. //获取矿车配置
  2031. let carCfg = Gamecfg.dongtianCar.getItem(carInfo.id);
  2032. if (carCfg == null) {
  2033. console.error(`dongtianCar_err:${carInfo.id}`);
  2034. return {
  2035. edtime: -1, //离结束 还有多长时间
  2036. win: 0, //胜利方是谁 0守方 1攻方 (未开始默认0)
  2037. nowpos: carInfo.dpos, //当前位置
  2038. };
  2039. }
  2040. let dnum = 0; //胜利方多出来的人数
  2041. let pow = 1; //胜利方状态值
  2042. let leng = carInfo.dpos; //距离(本方距离)
  2043. let win: 0 | 1 = 0;
  2044. let fevCard: boolean = false; //胜利方是否有终生卡
  2045. //人数对比
  2046. if (carInfo.he.knum.length > carInfo.my.knum.length) {
  2047. //进攻方胜利
  2048. dnum = carInfo.he.knum.length - carInfo.my.knum.length;
  2049. pow = carInfo.he.pow;
  2050. leng = carCfg.lengs[2] - carInfo.dpos; //反向距离
  2051. win = 1; //进攻方胜利
  2052. fevCard = carInfo.he.fevCard; //终生卡
  2053. } else {
  2054. //防守方胜利
  2055. dnum = carInfo.my.knum.length - carInfo.he.knum.length;
  2056. pow = carInfo.my.pow;
  2057. fevCard = carInfo.my.fevCard; //终生卡
  2058. }
  2059. //如果人数 <= 0 (防守方胜利 系数0.7) 就当防守方有0.7个人
  2060. dnum = Math.max(dnum, 0.7);
  2061. //哥布林速度系数
  2062. let wkVel = 1;
  2063. let cfgMath = Gamecfg.mathInfo.getItem("dongtian_wkVel");
  2064. if (cfgMath == null || cfgMath.pram.count == null) {
  2065. console.error(`dongtian_wkVel`);
  2066. } else {
  2067. wkVel = cfgMath.pram.count;
  2068. }
  2069. let tilixs = 200; //根据体力获得系数
  2070. //总速度
  2071. let vel = (dnum * wkVel * tilixs) / 100;
  2072. //终生卡 速度加成 +5%
  2073. let sdadd = 10000;
  2074. if (fevCard) {
  2075. sdadd += 1500;
  2076. }
  2077. vel = (vel * sdadd) / 10000;
  2078. //总的需要时间 计算公式
  2079. let allTime = Math.ceil(leng / vel);
  2080. //经过时间
  2081. let dtime = now - carInfo.stime;
  2082. if (dtime >= allTime) {
  2083. //已完成
  2084. return {
  2085. edtime: 0, //离结束 还有多长时间 (未开始 -1)
  2086. win: win, //胜利方是谁 0守方 1攻方 (未开始默认0)
  2087. nowpos: win ? carCfg.lengs[2] : 0, //当前位置 防守方胜利 就是0 进攻方胜利 就是最大值
  2088. };
  2089. } else {
  2090. //未完成 计算 当前位置偏移量
  2091. let dpos = dtime * vel;
  2092. //当前位置
  2093. let nowpos = carInfo.dpos;
  2094. if (win > 0) {
  2095. nowpos += dpos;
  2096. nowpos = Math.floor(nowpos); //进攻方胜利 取余偏向防守方(小值)
  2097. } else {
  2098. nowpos -= dpos;
  2099. nowpos = Math.ceil(nowpos); //防守方胜利 取余偏向进攻方(大值)
  2100. }
  2101. return {
  2102. edtime: allTime - dtime, //离结束 还有多长时间 (未开始 -1)
  2103. win: win, //胜利方是谁 0守方 1攻方 (未开始默认0)
  2104. nowpos: nowpos, //当前位置
  2105. };
  2106. }
  2107. }
  2108. /**
  2109. * 章节挂机计算
  2110. * @param actZhangjie 章节信息
  2111. * @param newTime 现在时间
  2112. * @param zflevel 阵法等级
  2113. * @returns
  2114. */
  2115. guajiItems(
  2116. _actZhangjie: Xys.ActZhangjie,
  2117. newTime: number,
  2118. zflevel: number
  2119. ): { items: Xys.KindItem[]; zy_items: Xys.KindItem[]; dj_items: Xys.KindItem[]; actZhangjie: Xys.ActZhangjie } {
  2120. let actZhangjie: Xys.ActZhangjie = this.objCopy(_actZhangjie);
  2121. let items: Xys.KindItem[] = []; //挂机奖励(总)
  2122. let zy_items: Xys.KindItem[] = []; //挂机奖励(金币/玩家经验/阵法经验)
  2123. let dj_items: Xys.KindItem[] = []; //挂机奖励(道具)
  2124. let cfgzj = Gamecfg.zhangjieInfo.getItem(actZhangjie.zjid);
  2125. if (cfgzj == null) {
  2126. return {
  2127. actZhangjie: actZhangjie,
  2128. items: items,
  2129. zy_items: zy_items,
  2130. dj_items: dj_items,
  2131. };
  2132. }
  2133. for (const item of cfgzj.gjRwd_zy) {
  2134. let cAt: number = newTime - actZhangjie.gjtime;
  2135. cAt = Math.min(cAt, actZhangjie.gjMax * 3600); //8小时上限
  2136. let count = Math.floor(cAt / (item[3] / item[2]));
  2137. if (count > 0) {
  2138. items.push([item[0], item[1], count]);
  2139. zy_items.push([item[0], item[1], count]);
  2140. }
  2141. }
  2142. for (const item of cfgzj.gjRwd_dj) {
  2143. if (item[4] != null && item[4] > zflevel) {
  2144. continue; //未达到阵法等级
  2145. }
  2146. if (actZhangjie.gjRwd_dj[item[0].toString()] == null) {
  2147. actZhangjie.gjRwd_dj[item[0].toString()] = {};
  2148. }
  2149. if (actZhangjie.gjRwd_dj[item[0].toString()][item[1].toString()] == null) {
  2150. actZhangjie.gjRwd_dj[item[0].toString()][item[1].toString()] = 0;
  2151. }
  2152. let cAt: number = newTime - actZhangjie.gjtime;
  2153. cAt = Math.min(cAt, actZhangjie.gjMax * 3600) + actZhangjie.gjRwd_dj[item[0].toString()][item[1].toString()];
  2154. //获得一个道具 需要多长时间
  2155. let oneTime = item[3] / item[2];
  2156. let count = Math.floor(cAt / oneTime);
  2157. if (count > 0) {
  2158. items.push([item[0], item[1], count]);
  2159. dj_items.push([item[0], item[1], count]);
  2160. actZhangjie.gjRwd_dj[item[0].toString()][item[1].toString()] = 0;
  2161. }
  2162. actZhangjie.gjRwd_dj[item[0].toString()][item[1].toString()] = Math.floor(cAt % oneTime);
  2163. }
  2164. actZhangjie.gjtime = newTime;
  2165. return {
  2166. actZhangjie: actZhangjie,
  2167. // items: gameMethod.mergeArr(items),
  2168. items: items,
  2169. zy_items: gameMethod.mergeArr(zy_items),
  2170. dj_items: gameMethod.mergeArr(dj_items),
  2171. };
  2172. }
  2173. //异或加解密
  2174. xorEncrypt(str: string, x:boolean = true, key: string = "zgyx2024888") {
  2175. if(!x){
  2176. return str
  2177. }
  2178. const result = [];
  2179. for (let i = 0; i < str.length; i++) {
  2180. const charCode = str.charCodeAt(i) ^ key.charCodeAt(i % key.length);
  2181. result.push(String.fromCharCode(charCode));
  2182. }
  2183. return result.join("");
  2184. }
  2185. // 用随机种子获取太初古矿地图
  2186. getGuKuangMap(randNum: number, cs: number): { id: string; hp: number; item: number[][]; icon: string }[][] {
  2187. let geziCp: number[] = Object.values(gezi);
  2188. let map: {
  2189. id: string;
  2190. hp: number;
  2191. item: number[][];
  2192. icon: string;
  2193. }[][] = []; // 地图数据
  2194. let sendRand = new SeedRand(randNum);
  2195. sendRand.random();
  2196. geziCp = sendRand.arrayShuffle(geziCp);
  2197. let index = 1;
  2198. let tcInfo;
  2199. let tsInfo;
  2200. let tcInfoLast;
  2201. let tsInfoLast;
  2202. while (index > 0) {
  2203. let tcInfo2;
  2204. let tsInfo2;
  2205. if (tcInfo == null) {
  2206. tcInfo2 = Gamecfg.taichuInfo.getItem(index.toString());
  2207. }
  2208. if (tsInfo == null) {
  2209. tsInfo2 = Gamecfg.taichuTs.getItem(index.toString());
  2210. }
  2211. if (tcInfo2 && tcInfo2.cs[0] <= cs && tcInfo2.cs[1] >= cs) {
  2212. tcInfo = tcInfo2;
  2213. } else if (tcInfo2) {
  2214. tcInfoLast = tcInfo2;
  2215. }
  2216. if (tsInfo2 && tsInfo2.cs[0] <= cs && tsInfo2.cs[1] >= cs) {
  2217. tsInfo = tsInfo2;
  2218. } else if (tsInfo2) {
  2219. tsInfoLast = tsInfo2;
  2220. }
  2221. if (tcInfo && tsInfo) {
  2222. index = -1;
  2223. } else if (tcInfo2 == null && tsInfo2 == null && tcInfoLast && tsInfoLast) {
  2224. tcInfo = gameMethod.objCopy(tcInfoLast);
  2225. tsInfo = gameMethod.objCopy(tsInfoLast);
  2226. let ts_cs_min = tsInfo.cs[0];
  2227. let ts_cs_max = tsInfo.cs[1];
  2228. let cha = 0;
  2229. while (ts_cs_max + cha < cs) {
  2230. cha = ts_cs_max - ts_cs_min;
  2231. ts_cs_min = ts_cs_max + 1;
  2232. ts_cs_max = ts_cs_min + cha;
  2233. cha = 0;
  2234. }
  2235. tsInfo.cs = [ts_cs_min, ts_cs_max];
  2236. index = -1;
  2237. } else {
  2238. index++;
  2239. }
  2240. }
  2241. if (tcInfo == null || tsInfo == null) {
  2242. return map;
  2243. }
  2244. let jlCs: number[] = [];
  2245. for (let i = tsInfo.cs[0]; i <= tsInfo.cs[1]; i++) {
  2246. jlCs.push(i);
  2247. }
  2248. let jlC = sendRand.getRandArr2(jlCs, 1).result[0]; // 当前层数区间 奖励层所在层数
  2249. let itemCount: { [itemid: string]: number[] } = {}; // 地块id:[格子数组]
  2250. let sd = tcInfo.sd;
  2251. for (let i = 0; i < sd.length; i++) {
  2252. let result = sendRand.getRandArr2(geziCp, sd[i][1]);
  2253. geziCp = result.arr;
  2254. itemCount[sd[i][0].toString()] = result.result;
  2255. }
  2256. let jlcNum: number | null = null; // 奖励层所在行数 0-5
  2257. if (jlC == cs) {
  2258. jlcNum = sendRand.getRandArr2([0, 1, 2, 3, 4, 5], 1).result[0];
  2259. }
  2260. let itemCountKeys = Object.keys(itemCount);
  2261. let mapLine: {
  2262. id: string;
  2263. hp: number;
  2264. item: number[][];
  2265. icon: string;
  2266. }[] = [];
  2267. let isHas = false;
  2268. let tilesInfo101 = Gamecfg.taichuTiles.getItem("1");
  2269. let tilesInfo301 = Gamecfg.taichuTiles.getItem("301");
  2270. let line = 0; // 第几行
  2271. for (let i = 0; i < gezi.length; i++) {
  2272. line = Math.floor(i / 6) + 1;
  2273. // 开始绘制地图
  2274. if (i % 6 == 0 && mapLine.length > 0) {
  2275. map.push(mapLine);
  2276. mapLine = [];
  2277. }
  2278. isHas = false;
  2279. let zuojiaInfo = Gamecfg.taichuZuojia.getItem(cs.toString(), line.toString());
  2280. if (zuojiaInfo != null) {
  2281. isHas = true;
  2282. for (let id of zuojiaInfo.item) {
  2283. let tilesInfo = Gamecfg.taichuTiles.getItem(id.toString());
  2284. if (tilesInfo != null) {
  2285. mapLine.push({
  2286. id: tilesInfo.id,
  2287. hp: tilesInfo.hp,
  2288. item: tilesInfo.itme,
  2289. icon: tilesInfo.icon,
  2290. });
  2291. } else {
  2292. mapLine.push({
  2293. id: "",
  2294. hp: 0,
  2295. item: [],
  2296. icon: "",
  2297. });
  2298. }
  2299. }
  2300. i += 5;
  2301. } else {
  2302. for (let k = 0; k < itemCountKeys.length; k++) {
  2303. if (itemCount[itemCountKeys[k]].indexOf(i) != -1) {
  2304. let tilesInfo = Gamecfg.taichuTiles.getItem(itemCountKeys[k]);
  2305. if (tilesInfo != null) {
  2306. mapLine.push({
  2307. id: itemCountKeys[k],
  2308. hp: tilesInfo.hp,
  2309. item: tilesInfo.itme,
  2310. icon: tilesInfo.icon,
  2311. });
  2312. isHas = true;
  2313. break;
  2314. }
  2315. }
  2316. }
  2317. }
  2318. if (!isHas) {
  2319. if (cs == 1 && i < 6) {
  2320. if (tilesInfo101 != null) {
  2321. mapLine.push({
  2322. id: "1",
  2323. hp: 1,
  2324. item: [],
  2325. icon: tilesInfo101.icon,
  2326. });
  2327. }
  2328. } else {
  2329. if (tilesInfo101 && map.length > 0 && map[map.length - 1][mapLine.length].hp == 0) {
  2330. // 如果上一层是空格 加一个木块
  2331. mapLine.push({
  2332. id: tilesInfo101.id,
  2333. hp: tilesInfo101.hp,
  2334. item: tilesInfo101.itme,
  2335. icon: tilesInfo101.icon,
  2336. });
  2337. } else {
  2338. mapLine.push({
  2339. id: "",
  2340. hp: 0,
  2341. item: [],
  2342. icon: "",
  2343. });
  2344. }
  2345. }
  2346. }
  2347. }
  2348. if (mapLine.length > 0) {
  2349. map.push(mapLine);
  2350. }
  2351. if (jlcNum != null) {
  2352. let len = tsInfo.sd.length;
  2353. if (len != 12) {
  2354. return map;
  2355. }
  2356. for (let i = 0; i < tsInfo.sd.length; i++) {
  2357. if (i % 6 == 0 && i != 0) {
  2358. jlcNum += 1;
  2359. }
  2360. if (tilesInfo301 != null) {
  2361. map[jlcNum][i % 6] =
  2362. tsInfo.sd[i].length == 1
  2363. ? {
  2364. id: "301",
  2365. hp: 0,
  2366. item: [],
  2367. icon: i == 0 ? tilesInfo301.icon : "",
  2368. }
  2369. : {
  2370. id: "301",
  2371. hp: 1,
  2372. item: [tsInfo.sd[i]],
  2373. icon: i == 0 ? tilesInfo301.icon : "",
  2374. };
  2375. }
  2376. }
  2377. // 奖励层下一层 整行不能为空
  2378. for (let i = 0; i < 6; i++) {
  2379. if (i % 6 == 0) {
  2380. jlcNum += 1;
  2381. }
  2382. if (map[jlcNum][i % 6].hp <= 0 && tilesInfo101 != null) {
  2383. // 转成石头
  2384. map[jlcNum][i % 6] = {
  2385. id: tilesInfo101.id,
  2386. hp: tilesInfo101.hp,
  2387. item: tilesInfo101.itme,
  2388. icon: tilesInfo101.icon,
  2389. };
  2390. }
  2391. }
  2392. }
  2393. return map;
  2394. }
  2395. /**
  2396. * 根据玩家选的流派推荐阵容
  2397. * @param type 玩家预选流派
  2398. * @returns
  2399. */
  2400. tuijian(sevBack: Xys.SevBack, type: string) {
  2401. //用于记录哪些位置被使用了
  2402. let gezi: string[] = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
  2403. let tuijian: { [gzid: string]: string } = {};
  2404. //先筛选出符合要求的弟子id列表
  2405. let dzList1: any[] = []; //前排
  2406. let dzList2: any[] = []; //中排
  2407. let dzList3: any[] = []; //后排
  2408. let wanbian1: any[] = []; //万变流前排
  2409. let wanbian2: any[] = []; //万变流中排
  2410. let wanbian3: any[] = []; //万变流后排
  2411. let other1: any[] = []; //其他前排
  2412. let other2: any[] = []; //其他中排
  2413. let other3: any[] = []; //其他后排
  2414. let actDiZiList: any = {};
  2415. if (sevBack.actDiZiList != null && sevBack.actDiZiList.a != null) {
  2416. actDiZiList = sevBack.actDiZiList.a;
  2417. }
  2418. for (let dzid in actDiZiList) {
  2419. let cfg = Gamecfg.huobanBase.getItem(actDiZiList[dzid].id);
  2420. if (cfg == null || cfg.show == 0) {
  2421. continue;
  2422. }
  2423. //不是预选流派和万变流不符合条件
  2424. if (cfg.liupai != type && cfg.liupai != "5") {
  2425. if (cfg.dingwei == "1") {
  2426. other1.push(dzid);
  2427. } else if (cfg.dingwei == "2") {
  2428. other2.push(dzid);
  2429. } else if (cfg.dingwei == "3") {
  2430. other3.push(dzid);
  2431. }
  2432. }
  2433. if (cfg.dingwei == "1" && cfg.liupai == type) {
  2434. dzList1.push(dzid);
  2435. } else if (cfg.dingwei == "2" && cfg.liupai == type) {
  2436. dzList2.push(dzid);
  2437. } else if (cfg.dingwei == "3" && cfg.liupai == type) {
  2438. dzList3.push(dzid);
  2439. } else if (cfg.dingwei == "1" && cfg.liupai == "5") {
  2440. wanbian1.push(dzid);
  2441. } else if (cfg.dingwei == "2" && cfg.liupai == "5") {
  2442. wanbian2.push(dzid);
  2443. } else if (cfg.dingwei == "3" && cfg.liupai == "5") {
  2444. wanbian3.push(dzid);
  2445. }
  2446. }
  2447. let push1 = 0; //记录前排放了几个弟子
  2448. let push2 = 0; //记录中排放了几个弟子
  2449. let push3 = 0; //记录后排放了几个弟子
  2450. //选出1个前排3个中排2个后排 优先选本流派,然后选万变流,否则选所有弟子里面战力最高的
  2451. if (dzList1.length > 0) {
  2452. //如果是只有一个就直接进去
  2453. if (dzList1.length == 1) {
  2454. tuijian["1"] = dzList1[0];
  2455. let index = gezi.indexOf("1");
  2456. if (index > -1) {
  2457. gezi.splice(index, 1);
  2458. }
  2459. push1 += 1;
  2460. } else {
  2461. let maxPower = 0;
  2462. for (let dzid of dzList1) {
  2463. let power = this.ep_power_dizi(sevBack, dzid);
  2464. if (power > maxPower) {
  2465. maxPower = power;
  2466. tuijian["1"] = dzid;
  2467. let index = gezi.indexOf("1");
  2468. if (index > -1) {
  2469. gezi.splice(index, 1);
  2470. }
  2471. push1 += 1;
  2472. }
  2473. }
  2474. }
  2475. } else if (wanbian1.length > 0 && push1 < 1) {
  2476. //没有就遍历万变流
  2477. //如果是只有一个就直接进去
  2478. if (wanbian1.length == 1) {
  2479. tuijian["1"] = wanbian1[0];
  2480. let index = gezi.indexOf("1");
  2481. if (index > -1) {
  2482. gezi.splice(index, 1);
  2483. }
  2484. push1 += 1;
  2485. } else {
  2486. let maxPower = 0;
  2487. for (let dzid of wanbian1) {
  2488. let power = this.ep_power_dizi(sevBack, dzid);
  2489. if (power > maxPower) {
  2490. maxPower = power;
  2491. tuijian["1"] = dzid;
  2492. let index = gezi.indexOf("1");
  2493. if (index > -1) {
  2494. gezi.splice(index, 1);
  2495. }
  2496. push1 += 1;
  2497. }
  2498. }
  2499. }
  2500. }
  2501. //放中排的
  2502. if (dzList2.length > 0) {
  2503. //如果是小于等于3个就直接放进去
  2504. if (dzList2.length <= 3) {
  2505. let xb = 4;
  2506. for (let i = 0; i < dzList2.length; i++) {
  2507. tuijian[(xb + i).toString()] = dzList2[i];
  2508. let index = gezi.indexOf((xb + i).toString());
  2509. if (index > -1) {
  2510. gezi.splice(index, 1);
  2511. }
  2512. push2 += 1;
  2513. }
  2514. } else {
  2515. let needDzid = dzList2
  2516. .map((dzid) => {
  2517. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2518. })
  2519. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2520. .slice(0, 3) // 选出战力最高的三个弟子
  2521. .map((item) => item.dzid); // 只取 dzid
  2522. let xb = 4;
  2523. for (let i = 0; i < 3; i++) {
  2524. tuijian[(xb + i).toString()] = needDzid[i];
  2525. let index = gezi.indexOf((xb + i).toString());
  2526. if (index > -1) {
  2527. gezi.splice(index, 1);
  2528. }
  2529. push2 += 1;
  2530. }
  2531. }
  2532. } else if (wanbian2.length > 0 && push2 < 3) {
  2533. //弟子不满足3个就遍历万变流
  2534. let needDzid = wanbian2
  2535. .map((dzid) => {
  2536. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2537. })
  2538. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2539. .slice(0, 3 - push2) // 选出战力最高的需要的弟子数量
  2540. .map((item) => item.dzid); // 只取 dzid
  2541. let xb = 4 + push2;
  2542. let cs = 2 - push3;
  2543. cs = Math.min(cs, wanbian2.length);
  2544. for (let i = 0; i < cs; i++) {
  2545. tuijian[(xb + i).toString()] = needDzid[i];
  2546. let index = gezi.indexOf((xb + i).toString());
  2547. if (index > -1) {
  2548. gezi.splice(index, 1);
  2549. }
  2550. push2 += 1;
  2551. }
  2552. }
  2553. //放后排的
  2554. if (dzList3.length > 0) {
  2555. //如果是小于等于2个就直接放进去
  2556. if (dzList3.length <= 2) {
  2557. let xb = 7;
  2558. for (let i = 0; i < dzList3.length; i++) {
  2559. tuijian[(xb + i).toString()] = dzList3[i];
  2560. let index = gezi.indexOf((xb + i).toString());
  2561. if (index > -1) {
  2562. gezi.splice(index, 1);
  2563. }
  2564. push3 += 1;
  2565. }
  2566. } else {
  2567. let needDzid = dzList3
  2568. .map((dzid) => {
  2569. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2570. })
  2571. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2572. .slice(0, 2) // 选出战力最高的2个弟子
  2573. .map((item) => item.dzid); // 只取 dzid
  2574. let xb = 7;
  2575. for (let i = 0; i < 2; i++) {
  2576. tuijian[(xb + i).toString()] = needDzid[i];
  2577. let index = gezi.indexOf((xb + i).toString());
  2578. if (index > -1) {
  2579. gezi.splice(index, 1);
  2580. }
  2581. push3 += 1;
  2582. }
  2583. }
  2584. } else if (wanbian3.length > 0 && push3 < 2) {
  2585. //弟子不满足2个就遍历万变流
  2586. let needDzid = wanbian3
  2587. .map((dzid) => {
  2588. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2589. })
  2590. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2591. .slice(0, 2 - push3) // 选出战力最高的需要的弟子数量
  2592. .map((item) => item.dzid); // 只取 dzid
  2593. let xb = 7 + push3;
  2594. let cs = 2 - push3;
  2595. cs = Math.min(cs, wanbian3.length);
  2596. for (let i = 0; i < cs; i++) {
  2597. tuijian[(xb + i).toString()] = needDzid[i];
  2598. let index = gezi.indexOf((xb + i).toString());
  2599. if (index > -1) {
  2600. gezi.splice(index, 1);
  2601. }
  2602. push3 += 1;
  2603. }
  2604. }
  2605. //如果遍历同派和万变流都没有符合的就优先从同站位最高战力里面拿
  2606. if (push1 < 1) {
  2607. //选择的流派和万变流都没有前排弟子就从其他前排弟子里面拿战力最高的
  2608. let needDzid = other1
  2609. .map((dzid) => {
  2610. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2611. })
  2612. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2613. .slice(0, 1) // 选出战力最高的需要的弟子数量
  2614. .map((item) => item.dzid); // 只取 dzid
  2615. let xb = 1;
  2616. let cs = Math.min(1, other1.length);
  2617. for (let i = 0; i < cs; i++) {
  2618. tuijian[(xb + i).toString()] = needDzid[i];
  2619. let index = gezi.indexOf((xb + i).toString());
  2620. if (index > -1) {
  2621. gezi.splice(index, 1);
  2622. }
  2623. //把用掉的弟子剔除
  2624. let index1 = other1.indexOf(needDzid[i]);
  2625. if (index1 > -1) {
  2626. other1.splice(index, 1);
  2627. }
  2628. }
  2629. }
  2630. if (push2 < 3) {
  2631. //选择的流派和万变流都没有前排弟子就从其他前排弟子里面拿战力最高的
  2632. let needDzid = other2
  2633. .map((dzid) => {
  2634. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2635. })
  2636. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2637. .slice(0, 3 - push2) // 选出战力最高的需要的弟子数量
  2638. .map((item) => item.dzid); // 只取 dzid
  2639. let xb = 4 + push2;
  2640. let cs = Math.min(3 - push2, other2.length);
  2641. for (let i = 0; i < cs; i++) {
  2642. tuijian[(xb + i).toString()] = needDzid[i];
  2643. let index = gezi.indexOf((xb + i).toString());
  2644. if (index > -1) {
  2645. gezi.splice(index, 1);
  2646. }
  2647. //把用掉的弟子剔除
  2648. let index1 = other2.indexOf(needDzid[i]);
  2649. if (index1 > -1) {
  2650. other2.splice(index, 1);
  2651. }
  2652. }
  2653. }
  2654. if (push3 < 2) {
  2655. //选择的流派和万变流都没有前排弟子就从其他前排弟子里面拿战力最高的
  2656. let needDzid = other3
  2657. .map((dzid) => {
  2658. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2659. })
  2660. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2661. .slice(0, 2 - push3) // 选出战力最高的需要的弟子数量
  2662. .map((item) => item.dzid); // 只取 dzid
  2663. let xb = 7 + push3;
  2664. let cs = Math.min(2 - push3, other3.length);
  2665. for (let i = 0; i < cs; i++) {
  2666. tuijian[(xb + i).toString()] = needDzid[i];
  2667. let index = gezi.indexOf((xb + i).toString());
  2668. if (index > -1) {
  2669. gezi.splice(index, 1);
  2670. }
  2671. //把用掉的弟子剔除
  2672. let index1 = other3.indexOf(needDzid[i]);
  2673. if (index1 > -1) {
  2674. other3.splice(index, 1);
  2675. }
  2676. }
  2677. }
  2678. //如果还是不足6个弟子就直接拿战力最高的前几个从空位开始放
  2679. if (Object.keys(tuijian).length < 6) {
  2680. //把其余的弟子合并
  2681. let other: any[] = this.addArr(other1, other2);
  2682. other = this.addArr(other, other3);
  2683. let needDzid = other
  2684. .map((dzid) => {
  2685. return { dzid, power: this.ep_power_dizi(sevBack, dzid) };
  2686. })
  2687. .sort((a, b) => b.power - a.power) // 按战力从大到小排序
  2688. .slice(0, 6 - Object.keys(tuijian).length) // 选出战力最高的需要的弟子数量
  2689. .map((item) => item.dzid); // 只取 dzid
  2690. for (let i = 0; i < needDzid.length; i++) {
  2691. //这个时候用掉的格子都已经删掉了,所以直接取就可以了
  2692. tuijian[gezi[i]] = needDzid[i];
  2693. }
  2694. }
  2695. return tuijian;
  2696. }
  2697. getSeedRand(seed: number) {
  2698. return new SeedRand(seed);
  2699. }
  2700. }
  2701. //输出
  2702. export let gameMethod: GameMethod = new GameMethod();
  2703. //种子随机
  2704. export class SeedRand {
  2705. seed: number;
  2706. constructor(seed: number) {
  2707. this.seed = seed;
  2708. }
  2709. /**
  2710. * 核心方法 输出一个小数
  2711. */
  2712. random(): number {
  2713. this.seed = (this.seed * 9301 + 49297) % 233280;
  2714. return this.seed / 233280.0;
  2715. }
  2716. random2(seed: number): number {
  2717. seed = (seed * 9301 + 49297) % 233280;
  2718. return seed / 233280.0;
  2719. }
  2720. /**
  2721. * 按照范围获取一个随机数
  2722. */
  2723. rand(min: number, max: number): number {
  2724. let _rd = Math.round((max - min + 1) * this.random() - 0.5) + min;
  2725. return _rd;
  2726. }
  2727. /**
  2728. * 随机排列一个数组
  2729. */
  2730. arrayShuffle(arr: any[]) {
  2731. let len = arr.length;
  2732. for (let i = 0; i < len - 1; i++) {
  2733. let index = this.rand(0, len - i - 1);
  2734. let temp = arr[index];
  2735. arr[index] = arr[len - i - 1];
  2736. arr[len - i - 1] = temp;
  2737. }
  2738. return arr;
  2739. }
  2740. /**
  2741. * 随机获取数组元素
  2742. */
  2743. getRandArr<T>(_arr: T[], num: number): T[] {
  2744. let arr = gameMethod.objCopy(_arr);
  2745. let result = [];
  2746. num = Math.min(num, arr.length);
  2747. for (let i = 0; i < num; i++) {
  2748. let ran = Math.floor(this.random() * (arr.length - i));
  2749. result.push(arr[ran]);
  2750. arr[ran] = arr[arr.length - i - 1];
  2751. }
  2752. return result;
  2753. }
  2754. /**
  2755. * 随机获取数组元素 seed、_arr、num不变 随机出的数据完全一致
  2756. */
  2757. getRandArr2<T>(_arr: T[], num: number) {
  2758. let arr: T[] = gameMethod.objCopy(_arr);
  2759. let result: T[] = [];
  2760. num = Math.min(num, arr.length);
  2761. let seed = this.random2(this.seed);
  2762. for (let i = 0; i < num; i++) {
  2763. seed = this.random2(seed);
  2764. let ran = Math.floor(seed * arr.length);
  2765. result.push(arr[ran]);
  2766. arr.splice(ran, 1);
  2767. }
  2768. return { result: result, arr: arr };
  2769. }
  2770. }