koishi-plugin-smmcat-gensokyo 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -191,6 +191,7 @@ var GensokyoMap = {
191
191
  floor: 1,
192
192
  areaName: "绿野平原三",
193
193
  type: "冒险区" /* 冒险区 */,
194
+ monster: [{ name: "dora", lv: 5 }],
194
195
  needLv: 1,
195
196
  left: "绿野平原一",
196
197
  down: "绿野平原六"
@@ -442,6 +443,58 @@ var userBenchmark = {
442
443
  }
443
444
  };
444
445
 
446
+ // src/data/initProps.ts
447
+ var propsData = {
448
+ "红药": {
449
+ name: "红药",
450
+ type: "消耗类" /* 消耗类 */,
451
+ info: "回复自身20HP",
452
+ price: 10,
453
+ fn: /* @__PURE__ */ __name(function(session) {
454
+ User.giveHPMP(session.userId, { hp: 20 }, async (val) => {
455
+ if (val.err) {
456
+ await session.send(val.err);
457
+ return;
458
+ }
459
+ const msg = `回复成功,玩家当前血量:${val.currentHP}`;
460
+ await session.send(msg);
461
+ });
462
+ }, "fn")
463
+ },
464
+ "蓝药": {
465
+ name: "蓝药",
466
+ type: "消耗类" /* 消耗类 */,
467
+ info: "回复自身20MP",
468
+ price: 10,
469
+ fn: /* @__PURE__ */ __name(function(session) {
470
+ User.giveHPMP(session.userId, { mp: 20 }, async (val) => {
471
+ if (val.err) {
472
+ await session.send(val.err);
473
+ return;
474
+ }
475
+ const msg = `回复成功,玩家当前蓝量:${val.currentMP}`;
476
+ await session.send(msg);
477
+ });
478
+ }, "fn")
479
+ },
480
+ "初级万能药": {
481
+ name: "初级万能药",
482
+ type: "消耗类" /* 消耗类 */,
483
+ info: "回复自身20MP和20HP",
484
+ price: 20,
485
+ fn: /* @__PURE__ */ __name(function(session) {
486
+ User.giveHPMP(session.userId, { hp: 20, mp: 20 }, async (val) => {
487
+ if (val.err) {
488
+ await session.send(val.err);
489
+ return;
490
+ }
491
+ const msg = `回复成功,玩家当前血量:${val.currentHP}、蓝量:${val.currentMP}`;
492
+ await session.send(msg);
493
+ });
494
+ }, "fn")
495
+ }
496
+ };
497
+
445
498
  // src/props.ts
446
499
  var Props = {
447
500
  config: {},
@@ -475,1196 +528,1378 @@ var Props = {
475
528
  await Props.ctx.database.create("smm_gensokyo_user_props", temp);
476
529
  }
477
530
  },
531
+ /** 获取持有道具信息 */
532
+ async getPropsDataByUserId(userId) {
533
+ await Props.initUserPropsData(userId);
534
+ const userProps = Props.userPorpsTemp[userId];
535
+ const msgList = Object.keys(userProps).map((item) => {
536
+ return `${userProps[item].name}:${userProps[item].value}个`;
537
+ });
538
+ return msgList.length ? `当前您持有如下道具:
539
+
540
+ ` + msgList.join("\n") : "您没有任何道具...";
541
+ },
478
542
  /** 更新本地数据库对应数据 */
479
543
  async setDatabasePropsData(userId) {
480
- const propsData = Props.userPorpsTemp[userId];
481
- if (propsData) {
544
+ const propsData2 = Props.userPorpsTemp[userId];
545
+ if (propsData2) {
482
546
  const temp = {
483
- props: propsData
547
+ props: propsData2
484
548
  };
485
549
  await Props.ctx.database.set("smm_gensokyo_user_props", { userId }, temp);
486
550
  }
551
+ },
552
+ async userProps(session, propsName) {
553
+ const userPropsData = Props.userPorpsTemp[session.userId];
554
+ if (!userPropsData) return;
555
+ if (!userPropsData[propsName]) {
556
+ await session.send(`您似乎没有${propsName}这个道具...`);
557
+ return;
558
+ }
559
+ User.loseProps(session.userId, { name: propsName, val: 1 }, async (val) => {
560
+ if (val.err) {
561
+ await session.send(val.err);
562
+ return;
563
+ }
564
+ propsData[propsName].fn(session);
565
+ });
487
566
  }
488
567
  };
489
568
 
490
- // src/users.ts
491
- var UserOccDict = {
492
- ["剑士" /* 剑士 */]: {
493
- info: "擅长近战攻击,拥有强大的属性能力",
494
- initStatus: {
495
- userId: "",
496
- playName: "",
497
- type: "剑士" /* 剑士 */,
498
- exp: 0,
499
- maxExp: 100,
500
- lv: 1,
501
- hp: 120,
502
- maxHp: 120,
503
- mp: 80,
504
- maxMp: 80,
505
- pp: 100,
506
- maxPp: 100,
507
- atk: 12,
508
- def: 5,
509
- chr: 50,
510
- csr: 0,
511
- ghd: 1.2,
512
- speed: 5,
513
- evasion: 100,
514
- hit: 100
515
- }
569
+ // src/monster.ts
570
+ var import_koishi = require("koishi");
571
+
572
+ // src/data/initMonster.ts
573
+ var monsterData = {
574
+ "小蜜蜂": {
575
+ name: "小蜜蜂",
576
+ type: "野怪" /* 野怪 */,
577
+ info: "幻想乡一层常见的生物",
578
+ pic: "http://smmcat.cn/run/gensokyo/小蜜蜂.png",
579
+ hp: 50,
580
+ maxHp: 50,
581
+ mp: 30,
582
+ maxMp: 30,
583
+ atk: 7,
584
+ def: 2,
585
+ chr: 50,
586
+ csr: 0,
587
+ evasion: 100,
588
+ hit: 1e3,
589
+ ghd: 1.2,
590
+ speed: 4,
591
+ giveExp: 10,
592
+ giveMonetary: 2,
593
+ giveProps: [
594
+ { name: "红药", val: 3, radomVal: 30 }
595
+ ]
516
596
  },
517
- ["法师" /* 法师 */]: {
518
- info: "精通元素魔法,能够打出爆发伤害",
519
- initStatus: {
520
- userId: "",
521
- playName: "",
522
- type: "法师" /* 法师 */,
523
- exp: 0,
524
- maxExp: 100,
525
- lv: 1,
526
- hp: 100,
527
- maxHp: 100,
528
- mp: 100,
529
- maxMp: 100,
530
- pp: 100,
531
- maxPp: 100,
532
- atk: 10,
533
- def: 2,
534
- chr: 50,
535
- csr: 0,
536
- ghd: 1.2,
537
- speed: 5,
538
- evasion: 100,
539
- hit: 100
540
- }
597
+ "小蜘蛛": {
598
+ name: "小蜘蛛",
599
+ type: "野怪" /* 野怪 */,
600
+ info: "幻想乡一层常见的生物",
601
+ pic: "http://smmcat.cn/run/gensokyo/小蜘蛛.png",
602
+ hp: 55,
603
+ maxHp: 55,
604
+ mp: 30,
605
+ maxMp: 30,
606
+ atk: 10,
607
+ def: 3,
608
+ chr: 50,
609
+ csr: 0,
610
+ evasion: 150,
611
+ hit: 1e3,
612
+ ghd: 1.2,
613
+ speed: 4,
614
+ giveExp: 12,
615
+ giveMonetary: 2,
616
+ giveProps: [
617
+ { name: "蓝药", val: 3, radomVal: 30 }
618
+ ]
541
619
  },
542
- ["刺客" /* 刺客 */]: {
543
- info: "迅捷攻击,高闪避值的高敏玩家",
544
- initStatus: {
545
- userId: "",
546
- playName: "",
547
- type: "刺客" /* 刺客 */,
548
- exp: 0,
549
- maxExp: 100,
550
- lv: 1,
551
- hp: 90,
552
- maxHp: 90,
553
- mp: 70,
554
- maxMp: 70,
555
- pp: 100,
556
- maxPp: 100,
557
- atk: 8,
558
- def: 2,
559
- chr: 80,
560
- csr: 0,
561
- ghd: 1.3,
562
- speed: 6,
563
- evasion: 120,
564
- hit: 100
565
- }
620
+ "dora": {
621
+ name: "dora",
622
+ type: "野怪" /* 野怪 */,
623
+ info: "偶尔出没在一层世界的奇怪生物",
624
+ pic: "http://smmcat.cn/run/gensokyo/dora.png",
625
+ hp: 88,
626
+ maxHp: 88,
627
+ mp: 10,
628
+ maxMp: 10,
629
+ atk: 20,
630
+ def: 5,
631
+ chr: 200,
632
+ csr: 0,
633
+ evasion: 200,
634
+ hit: 1e3,
635
+ ghd: 1.2,
636
+ speed: 4,
637
+ giveExp: 15,
638
+ giveMonetary: 3,
639
+ giveProps: [
640
+ { name: "蓝药", val: 3, radomVal: 30 },
641
+ { name: "初级万能药", val: 2, radomVal: 90, const: true, lv: 5 }
642
+ ]
566
643
  }
567
644
  };
568
- var User = {
645
+
646
+ // src/monster.ts
647
+ var Monster = {
569
648
  config: {},
570
649
  ctx: {},
571
- userTempData: {},
650
+ monsterTempData: {},
572
651
  async init(config, ctx) {
573
- User.config = config;
574
- User.ctx = ctx;
652
+ Monster.config = config;
653
+ Monster.ctx = ctx;
575
654
  ctx.model.extend(
576
- "smm_gensokyo_user_attribute",
655
+ "smm_gensokyo_monster_attribute",
577
656
  {
578
- userId: "string",
579
- playName: "string",
657
+ id: "integer",
658
+ name: "string",
659
+ info: "string",
580
660
  type: "string",
581
- exp: "integer",
582
- lv: "integer",
583
661
  hp: "integer",
662
+ maxHp: "integer",
584
663
  mp: "integer",
585
- pp: "integer",
586
- isDie: "boolean"
664
+ maxMp: "integer",
665
+ atk: "integer",
666
+ def: "integer",
667
+ chr: "integer",
668
+ evasion: "integer",
669
+ hit: "integer",
670
+ ghd: "integer",
671
+ speed: "integer"
587
672
  },
588
673
  {
589
- primary: "userId",
674
+ primary: "id",
590
675
  autoInc: false
591
676
  }
592
677
  );
593
- const userData = await ctx.database.get("smm_gensokyo_user_attribute", {});
594
- const temp = {};
595
- userData.forEach((item) => {
596
- temp[item.userId] = item;
597
- });
598
- User.userTempData = temp;
599
- },
600
- /** 获取角色基础属性 */
601
- async getUserAttribute(session) {
602
- if (!User.userTempData[session.userId]) {
603
- await session.send("未创建账户,请发送 /开始注册 完成账号的注册!");
604
- return null;
678
+ const monsterData2 = await ctx.database.get("smm_gensokyo_monster_attribute", {});
679
+ if (monsterData2.length == 0) {
680
+ Monster.monsterTempData = Monster._createInitMonsterData();
681
+ } else {
682
+ const temp = {};
683
+ monsterData2.forEach((item) => {
684
+ temp[item.id] = item;
685
+ });
686
+ Monster.monsterTempData = temp;
605
687
  }
606
- return User.getUserAddLvAttribute(session.userId);
607
688
  },
608
- /** 获取角色实际等级属性数据 */
609
- getUserAddLvAttribute(userId) {
610
- const UserDict = User.userTempData[userId];
611
- if (!UserDict) return null;
612
- const UserData = {
613
- ...UserOccDict[UserDict.type].initStatus,
614
- lv: UserDict.lv,
615
- hp: UserDict.hp,
616
- mp: UserDict.mp,
617
- exp: UserDict.exp,
618
- pp: UserDict.pp,
619
- playName: UserDict.playName,
620
- userId: UserDict.userId
621
- };
622
- const lv = UserData.lv;
623
- const temp = {};
624
- const lvScope = Object.keys(userBenchmark).reverse().find((item) => Number(item) < lv) || 10;
625
- const useBenchmark = userBenchmark[lvScope];
626
- Object.keys(UserData).forEach((i) => {
627
- temp[i] = UserData[i];
689
+ /** 赋予原始的怪物数据 */
690
+ _createInitMonsterData() {
691
+ return monsterData;
692
+ },
693
+ getMonsterAttributeData(monsterName, lv) {
694
+ const monster = Monster.monsterTempData[monsterName];
695
+ if (!monster) return null;
696
+ const temp = { lv };
697
+ const lvScope = Object.keys(monsterBenchmark).reverse().find((item) => Number(item) < lv) || 10;
698
+ const useBenchmark = monsterBenchmark[lvScope];
699
+ console.log(useBenchmark);
700
+ Object.keys(monster).forEach((i) => {
701
+ temp[i] = monster[i];
628
702
  if (useBenchmark[i]) {
629
- if (i == "maxExp") {
630
- temp[i] = Math.floor(100 * useBenchmark[i] * (lv - 1)) || 100;
631
- } else {
632
- temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
633
- }
703
+ temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
634
704
  }
635
705
  });
636
706
  return temp;
637
707
  },
638
- /** 通过 userId 获取角色属性 */
639
- getUserAttributeByUserId(userId) {
640
- return User.getUserAddLvAttribute(userId) || null;
641
- },
642
- /** 创建游戏账号 */
643
- async createPlayUser(session) {
644
- const [data] = await User.ctx.database.get("smm_gensokyo_user_attribute", { userId: session.userId });
645
- if (data) {
646
- await session.send("已存在账号,请勿重复创建!");
647
- return;
708
+ /** 格式化怪物属性数据 */
709
+ monsterAttributeTextFormat(monster) {
710
+ const { name: name2, type, lv, hp, maxHp, mp, maxMp, atk, def, chr, evasion, hit, ghd, speed, info, pic, giveProps } = monster;
711
+ const propsList = giveProps.filter((item) => item.lv ? lv >= item.lv : true).map((item) => item.name);
712
+ const attributeText = (pic ? import_koishi.h.image(pic) + "\n" : "") + `Lv.${lv}【${name2}】
713
+
714
+ 【怪物类型】${type}
715
+ 【生命值】${hp}/${maxHp}
716
+ 【魔法值】${mp}/${maxMp}
717
+ 【攻击力】${atk}
718
+ 【防御力】${def}
719
+ 【闪避值】${evasion}
720
+ 【命中值】${hit}
721
+ 【速度值】${speed}
722
+ 【暴击率】${(chr / 10).toFixed(1)}%
723
+ 【爆伤倍率】${(ghd * 100).toFixed(0)}%` + (propsList?.length ? `
724
+ 【概率掉落道具】` + propsList.join("、") : "") + (info ? "\n\n" + info : "");
725
+ return attributeText;
726
+ }
727
+ };
728
+
729
+ // src/utlis.ts
730
+ var random = /* @__PURE__ */ __name((min, max) => {
731
+ return Math.floor(Math.random() * (max - min + 1)) + min;
732
+ }, "random");
733
+ var generateHealthDisplay = /* @__PURE__ */ __name((current, total) => {
734
+ const ratio = current / total;
735
+ const displayLength = 10;
736
+ const filledLength = Math.floor(ratio * displayLength);
737
+ const unfilledLength = displayLength - filledLength;
738
+ const filled = "■".repeat(filledLength);
739
+ const unfilled = "□".repeat(unfilledLength);
740
+ return filled + unfilled;
741
+ }, "generateHealthDisplay");
742
+
743
+ // src/damage.ts
744
+ var Damage = class {
745
+ static {
746
+ __name(this, "Damage");
747
+ }
748
+ config;
749
+ constructor(agent, realHarm = false) {
750
+ this.config = {
751
+ agent: { self: { ...agent.self }, goal: { ...agent.goal } },
752
+ harm: 0,
753
+ default_harm: 0,
754
+ isRealHarm: realHarm,
755
+ isEvasion: false,
756
+ isCsp: false,
757
+ isBadDef: false
758
+ };
759
+ }
760
+ /** 伤害判定前 */
761
+ before(fn) {
762
+ this.config.default_harm = this.config.agent.self.atk + this.config.agent.self.gain.atk;
763
+ fn && fn(this.config);
764
+ return this;
765
+ }
766
+ /** 真实伤害判定 */
767
+ beforRealHarm(fn) {
768
+ fn && fn(this.config);
769
+ if (this.config.isRealHarm) {
770
+ this.config.harm = this.config.default_harm;
648
771
  }
649
- await session.send("请输入自己的游戏昵称:(60s)");
650
- const playname = await session.prompt(6e4);
651
- if (playname == void 0) return;
652
- const [repeat] = await User.ctx.database.get("smm_gensokyo_user_attribute", { playName: playname.trim() });
653
- if (repeat) {
654
- await session.send("名字重复,请更换一个名字。");
655
- return;
772
+ return this;
773
+ }
774
+ /** 是否闪避判定 */
775
+ evasion(fn) {
776
+ const { self, goal } = this.config.agent;
777
+ if (this.config.isRealHarm) return this;
778
+ const lvSup = /* @__PURE__ */ __name(() => Math.floor((goal.lv - self.lv) / 5) * 20, "lvSup");
779
+ const evaVal = Math.min(95, (goal.evasion + goal.gain.evasion - self.hit + lvSup()) / 10);
780
+ if (random(0, 100) <= evaVal) {
781
+ this.config.isEvasion = true;
782
+ fn && fn(this.config);
783
+ return this;
656
784
  }
657
- if (playname.trim().length > 6 || playname.trim().length < 1) {
658
- await session.send("名字长度有问题,要求小于 6个字,大于 1个字");
659
- return;
785
+ fn && fn(this.config);
786
+ return this;
787
+ }
788
+ /** 是否暴击判定 */
789
+ csp(fn) {
790
+ const { self, goal } = this.config.agent;
791
+ if (this.config.isRealHarm) return this;
792
+ if (this.config.isEvasion) return this;
793
+ const cspVal = (self.chr + self.gain.chr - goal.csr) / 10;
794
+ if (random(0, 100) <= cspVal) {
795
+ this.config.isCsp = true;
796
+ this.config.harm = Math.floor(this.config.default_harm * (self.ghd + self.gain.ghd));
797
+ fn && fn(this.config);
798
+ return this;
660
799
  }
661
- await session.send(`请输入要专职的职业:(60s)
662
- ${Object.keys(UserOccDict).map((i) => `【${i}】:${UserOccDict[i].info}`).join("\n")}`);
663
- let jobType = await session.prompt(6e4);
664
- if (jobType == void 0) return;
665
- while (!Object.keys(UserOccDict).includes(jobType)) {
666
- await session.send("未找到该职业,请重新选择!");
667
- jobType = await session.prompt(6e4);
800
+ this.config.harm = this.config.default_harm;
801
+ fn && fn(this.config);
802
+ return this;
803
+ }
804
+ /** 防御结算 */
805
+ beforDef(fn) {
806
+ const { goal } = this.config.agent;
807
+ if (this.config.isRealHarm) return this;
808
+ if (this.config.isEvasion) return this;
809
+ const dpVal = goal.def + goal.gain.def;
810
+ fn && fn(this.config);
811
+ if (this.config.harm - dpVal > 0) {
812
+ this.config.harm -= dpVal;
813
+ } else {
814
+ this.config.isBadDef = true;
815
+ this.config.harm = 1;
668
816
  }
669
- const temp = {
670
- userId: session.userId,
671
- playName: playname.trim(),
672
- type: jobType,
673
- hp: UserOccDict[jobType].initStatus.hp,
674
- pp: UserOccDict[jobType].initStatus.pp,
675
- mp: UserOccDict[jobType].initStatus.mp,
676
- lv: 1,
677
- exp: 0,
678
- isDie: false
679
- };
680
- User.ctx.database.create("smm_gensokyo_user_attribute", temp);
681
- User.userTempData[session.userId] = temp;
682
- await Props.initUserPropsData(session.userId);
683
- await session.send("创建成功!\n" + User.userAttributeTextFormat(session.userId));
817
+ return this;
818
+ }
819
+ result(fn) {
820
+ this.before((val) => {
821
+ fn?.before && fn.before(val);
822
+ }).beforRealHarm((val) => {
823
+ fn?.beforRealHarm && fn.beforRealHarm(val);
824
+ }).evasion((val) => {
825
+ fn?.evasion && fn.evasion(val);
826
+ }).csp((val) => {
827
+ fn?.csp && fn.csp(val);
828
+ }).beforDef((val) => {
829
+ fn?.beforDef && fn.beforDef(val);
830
+ });
831
+ return this.config;
832
+ }
833
+ };
834
+ function giveDamage(self, goal, damage) {
835
+ if (goal.hp - damage.harm > 0) {
836
+ goal.hp -= damage.harm;
837
+ return damage.harm;
838
+ } else {
839
+ const lostHp = goal.hp;
840
+ goal.hp = 0;
841
+ return lostHp;
842
+ }
843
+ }
844
+ __name(giveDamage, "giveDamage");
845
+ function giveCure(goal, val) {
846
+ const upVal = goal.hp + val;
847
+ if (upVal < goal.maxHp + goal.gain.maxHp) {
848
+ goal.hp = upVal;
849
+ return val;
850
+ } else {
851
+ const abHp = goal.maxHp + goal.gain.maxHp - goal.hp;
852
+ goal.hp += abHp;
853
+ return abHp;
854
+ }
855
+ }
856
+ __name(giveCure, "giveCure");
857
+ function moreDamageInfo(damage) {
858
+ return (damage.isCsp ? `(暴击!)` : "") + (damage.isEvasion ? `(闪避成功!)` : "") + (damage.isBadDef ? `(未破防!)` : "");
859
+ }
860
+ __name(moreDamageInfo, "moreDamageInfo");
861
+
862
+ // src/skillFn.ts
863
+ var skillFn = {
864
+ "重砍": {
865
+ name: "重砍",
866
+ type: "伤害技" /* 伤害技 */,
867
+ info: "[伤害技]消耗10MP,对敌方一个单位造成基于攻击力1.2倍伤害。该次伤害无视敌方30%防御!(最低无视1防御)",
868
+ lv: 3,
869
+ mp: 10,
870
+ feature: ["剑士" /* 剑士 */],
871
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
872
+ const damageData = new Damage(agent).result({
873
+ before: /* @__PURE__ */ __name((val) => {
874
+ val.default_harm += Math.floor(val.default_harm * 0.2);
875
+ val.agent.goal.def -= Math.floor(val.agent.goal.def * 0.3) || 1;
876
+ }, "before")
877
+ });
878
+ fn({
879
+ damage: damageData,
880
+ type: this.type,
881
+ target: [agent.goal],
882
+ isNext: false
883
+ });
884
+ return `${getLineupName(agent.self)} 释放重砍,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
885
+ }, "fn")
684
886
  },
685
- /** 信息格式化 */
686
- userAttributeTextFormat(userId) {
687
- if (!User.userTempData[userId]) {
688
- return "没有找到您的角色信息";
689
- }
690
- const temp = User.getUserAttributeByUserId(userId);
691
- return `昵称:${temp.playName}
692
- 职位:${temp.type}
693
- 等级:${temp.lv} (${temp.exp}/${temp.maxExp})
694
- -----------------
695
- 【生命值】${temp.hp}/${temp.maxHp}
696
- 【魔法值】${temp.mp}/${temp.maxMp}
697
- 【活力值】${temp.pp}/${temp.maxPp}
698
- -----------------
699
- 【攻击力】${temp.atk} (+0)
700
- 【防御力】${temp.def} (+0)
701
- 【速度值】${temp.speed} (+0)
702
- 【闪避值】${temp.evasion} (+0)
703
- 【命中率】${(temp.hit / 10 + 100).toFixed(1)}% (+0%)
704
- 【暴击率】${(temp.chr / 10).toFixed(1)}% (+0%)
705
- 【暴击伤害】${(temp.ghd * 100).toFixed(1)}% (+0%)` + (temp.csr > 0 ? `
706
- 【暴击抵抗】${temp.csr}` : "");
887
+ "突刺": {
888
+ name: "突刺",
889
+ type: "伤害技" /* 伤害技 */,
890
+ info: "[伤害技]消耗10MP,对敌方一个单位造成基于攻击力1.2倍伤害,该伤害无视敌方闪避10%",
891
+ lv: 3,
892
+ mp: 10,
893
+ feature: ["刺客" /* 刺客 */],
894
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
895
+ const damageData = new Damage(agent).result({
896
+ before: /* @__PURE__ */ __name((val) => {
897
+ val.default_harm += Math.floor(val.default_harm * 0.2);
898
+ val.agent.goal.evasion -= Math.floor((val.agent.goal.evasion + val.agent.goal.gain.evasion) * 0.1);
899
+ }, "before")
900
+ });
901
+ fn({
902
+ damage: damageData,
903
+ type: this.type,
904
+ target: [agent.goal],
905
+ isNext: false
906
+ });
907
+ return `${getLineupName(agent.self)} 释放突刺,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
908
+ }, "fn")
707
909
  },
708
- /** 写入用户数据到数据库 */
709
- async setDatabaseUserAttribute(userId) {
710
- const userInfo = User.userTempData[userId];
711
- if (!userInfo) return;
712
- const temp = {
713
- playName: userInfo.playName.trim(),
714
- hp: userInfo.hp,
715
- pp: userInfo.pp,
716
- mp: userInfo.mp,
717
- lv: userInfo.lv,
718
- exp: userInfo.exp
719
- };
720
- User.ctx.database.set("smm_gensokyo_user_attribute", { userId }, temp);
910
+ "水炮": {
911
+ name: "水炮",
912
+ type: "伤害技" /* 伤害技 */,
913
+ info: "[伤害技]消耗10MP,通过凝集魔力对敌方造成基于攻击力1.2倍伤害,该伤害基于当前剩余魔法值10%额外叠加伤害。",
914
+ lv: 3,
915
+ mp: 10,
916
+ feature: ["法师" /* 法师 */],
917
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
918
+ const damageData = new Damage(agent).result({
919
+ before: /* @__PURE__ */ __name((val) => {
920
+ val.default_harm += Math.floor(val.default_harm * 0.2) + Math.floor(val.agent.self.mp * 0.1);
921
+ }, "before")
922
+ });
923
+ fn({
924
+ damage: damageData,
925
+ type: this.type,
926
+ target: [agent.goal],
927
+ isNext: false
928
+ });
929
+ return `${getLineupName(agent.self)} 释放水炮,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
930
+ }, "fn")
721
931
  },
722
- /** 给予玩家经验 */
723
- async giveExp(userId, value, fn) {
724
- const userInfo = User.userTempData[userId];
725
- if (!userInfo) return;
726
- const beforData = { ...User.getUserAttributeByUserId(userId) };
727
- let isUp = false;
728
- userInfo.exp += value;
729
- while (true) {
730
- const { maxExp } = User.getUserAttributeByUserId(userId);
731
- if (userInfo.exp < maxExp) break;
732
- userInfo.lv += 1;
733
- userInfo.exp -= maxExp;
734
- isUp = true;
735
- }
736
- if (isUp) {
737
- const afterData = User.getUserAttributeByUserId(userId);
738
- const upTemp = {
739
- name: afterData.playName,
740
- lv: afterData.lv,
741
- maxHp: afterData.maxHp - beforData.maxHp,
742
- maxMp: afterData.maxMp = beforData.maxMp,
743
- atk: afterData.atk - beforData.atk,
744
- def: afterData.def - beforData.def
745
- };
746
- fn && await fn(upTemp);
747
- }
748
- await User.setDatabaseUserAttribute(userId);
932
+ "濒死一击": {
933
+ name: "濒死一击",
934
+ type: "伤害技" /* 伤害技 */,
935
+ info: "[伤害技]血量低于40%可释放,消耗20MP,对敌方一个单位造成基于攻击力2倍伤害。该次伤害暴击率提高20%",
936
+ lv: 3,
937
+ mp: 20,
938
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
939
+ if (agent.self.hp / (agent.self.maxHp + agent.self.gain.maxHp) < 0.4) {
940
+ const damageData = new Damage(agent).result({
941
+ before: /* @__PURE__ */ __name((val) => {
942
+ val.default_harm += val.default_harm;
943
+ val.agent.self.chr += 200;
944
+ }, "before")
945
+ });
946
+ fn({
947
+ damage: damageData,
948
+ type: this.type,
949
+ target: [agent.goal],
950
+ isNext: false
951
+ });
952
+ return `${getLineupName(agent.self)} 释放濒死一击,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
953
+ } else {
954
+ fn({
955
+ type: "释放失败" /* 释放失败 */,
956
+ isNext: true,
957
+ err: "释放失败,未达成条件。"
958
+ });
959
+ return ``;
960
+ }
961
+ }, "fn")
749
962
  },
750
- /** 给予玩家死亡 */
751
- async giveDie(userId) {
752
- const userInfo = User.userTempData[userId];
753
- userInfo.hp = 0;
754
- userInfo.isDie = true;
755
- await User.setDatabaseUserAttribute(userId);
963
+ "初级治愈": {
964
+ name: "初级治愈",
965
+ type: "治疗技" /* 治疗技 */,
966
+ info: "[治疗技]直接恢复自身或者目标 40HP",
967
+ lv: 1,
968
+ mp: 30,
969
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
970
+ const selectGoal = agent.goal;
971
+ if (agent.goal.hp <= 0) {
972
+ return `${getLineupName(agent.self)}已阵亡,无法恢复...`;
973
+ }
974
+ fn({
975
+ value: 40,
976
+ target: [selectGoal],
977
+ type: "治疗技" /* 治疗技 */,
978
+ isNext: false
979
+ });
980
+ return `${getLineupName(agent.self)}释放初级治愈,${getLineupName(agent.goal)}恢复40HP`;
981
+ }, "fn")
982
+ }
983
+ };
984
+
985
+ // src/battle.ts
986
+ var BattleData = {
987
+ config: {},
988
+ ctx: {},
989
+ historyTemp: {},
990
+ lastPlay: {},
991
+ teamTemp: {},
992
+ init(config, ctx) {
993
+ this.config = config;
994
+ this.ctx = ctx;
756
995
  },
757
- /** 给予玩家恢复 */
758
- async giveLife(userId, val) {
759
- const userInfo = User.userTempData[userId];
760
- if (!val) {
761
- const { maxHp } = User.getUserAttributeByUserId(userId);
762
- userInfo.hp = maxHp;
763
- } else {
764
- userInfo.hp = val;
765
- }
766
- await User.setDatabaseUserAttribute(userId);
996
+ /** 玩家是否正在战斗 */
997
+ isBattle(session) {
998
+ return !!BattleData.lastPlay[session.userId];
767
999
  },
768
- /** 给予玩家血量或者蓝量 */
769
- async giveHPMP(userId, value, fn) {
770
- const userInfo = User.userTempData[userId];
771
- if (!userInfo) return;
772
- if (userInfo.isDie) {
773
- fn && await fn({
774
- currentHP: 0,
775
- currentMP: 0,
776
- err: "角色已死亡,无法使用恢复道具。"
777
- });
778
- return;
779
- }
780
- const { maxHp, maxMp } = User.getUserAttributeByUserId(userId);
781
- if (userInfo.hp + (value.hp || 0) < maxHp) {
782
- userInfo.hp += value.hp || 0;
783
- } else {
784
- userInfo.hp = maxHp;
785
- }
786
- if (userInfo.mp + (value.mp || 0) < maxHp) {
787
- userInfo.mp += value.mp || 0;
788
- } else {
789
- userInfo.mp = maxMp;
1000
+ /** 玩家是否正在战斗 */
1001
+ isBattleByUserId(userId) {
1002
+ return !!BattleData.lastPlay[userId];
1003
+ },
1004
+ /** 玩家是否在队伍中 */
1005
+ isTeam(session) {
1006
+ return !!BattleData.teamTemp[session.userId];
1007
+ },
1008
+ isTeamByUserId(userId) {
1009
+ return !!BattleData.teamTemp[userId];
1010
+ },
1011
+ // 返回队伍信息
1012
+ teamListByUser(userId) {
1013
+ const teamList = [];
1014
+ if (!BattleData.teamTemp[userId]) {
1015
+ return [];
790
1016
  }
791
- fn && await fn({
792
- currentHP: userInfo.hp,
793
- currentMP: userInfo.mp
1017
+ const _userId = BattleData.teamTemp[userId].for;
1018
+ Object.keys(BattleData.teamTemp).forEach((item) => {
1019
+ if (BattleData.teamTemp[item].for == _userId) {
1020
+ teamList.push(User.getUserAttributeByUserId(item));
1021
+ }
794
1022
  });
795
- await User.setDatabaseUserAttribute(userId);
1023
+ return teamList;
796
1024
  },
797
- /** 给予玩家PP值 */
798
- async givePP(userId, value, fn) {
799
- const userInfo = User.userTempData[userId];
800
- if (!userInfo) return;
801
- const { maxPp } = User.getUserAttributeByUserId(userId);
802
- if (userInfo.pp + value < maxPp) {
803
- userInfo.pp += value;
1025
+ /** 创建战斗-与怪物 */
1026
+ async createBattleByMonster(session, goal) {
1027
+ if (BattleData.isBattle(session)) {
1028
+ await session.send("当前正在战斗,还不能逃脱!");
1029
+ return;
1030
+ }
1031
+ const battle_user = [];
1032
+ const battle_monsterList = [];
1033
+ const playUser = [];
1034
+ if (BattleData.isTeam(session) && BattleData.teamTemp[session.userId].identity == "队员") {
1035
+ await session.send("你不是队伍的队长,无法主动操作战斗!");
1036
+ return;
1037
+ } else if (BattleData.isTeam(session)) {
1038
+ Object.keys(BattleData.teamTemp).forEach((item) => {
1039
+ if (BattleData.teamTemp[item].for == session.userId) {
1040
+ playUser.push(item);
1041
+ battle_user.push(initBattleAttribute(User.getUserAttributeByUserId(item)));
1042
+ }
1043
+ });
804
1044
  } else {
805
- userInfo.pp = maxPp;
1045
+ playUser.push(session.userId);
1046
+ battle_user.push(initBattleAttribute(User.getUserAttributeByUserId(session.userId)));
806
1047
  }
807
- fn && await fn({
808
- currentPP: userInfo.pp
1048
+ goal.forEach((item) => {
1049
+ battle_monsterList.push(initBattleAttribute(Monster.getMonsterAttributeData(item.name, item.lv)));
809
1050
  });
810
- await User.setDatabaseUserAttribute(userId);
1051
+ const temp = {
1052
+ self: battle_user.map((i) => ({ ...i, for: "self" })),
1053
+ goal: battle_monsterList.map((i) => ({ ...i, for: "goal" }))
1054
+ };
1055
+ playUser.forEach((userId) => {
1056
+ BattleData.lastPlay[userId] = temp;
1057
+ });
1058
+ await session.send(`开始与 ${goal.map((i) => i.name).join("、")} 进行战斗`);
811
1059
  },
812
- /** 给予玩家货币 */
813
- async giveMonetary(userId, val, fn) {
814
- const [bindData] = await User.ctx.database.get("binding", { pid: userId });
815
- if (bindData && val) {
816
- const [currentM] = await User.ctx.database.get("monetary", { uid: bindData.aid });
817
- await User.ctx.monetary.gain(bindData.aid, val);
818
- fn && fn({ val, currentVal: currentM.value += val });
1060
+ /** 创建战斗-与玩家 */
1061
+ async createBattleByUser(session, goal) {
1062
+ if (BattleData.isBattle(session)) {
1063
+ await session.send("当前正在战斗,还不能逃脱!");
1064
+ return;
819
1065
  }
820
- },
821
- /** 收取玩家货币 */
822
- async lostMonetary(userId, val, fn) {
823
- const [bindData] = await User.ctx.database.get("binding", { pid: userId });
824
- if (bindData && val) {
825
- const [currentM] = await User.ctx.database.get("monetary", { uid: bindData.aid });
826
- if (currentM.value - val < 0) {
827
- fn && fn({
828
- val: Math.abs(val),
829
- currentVal: currentM.value,
830
- err: "余额不足!"
831
- });
832
- return;
1066
+ const battle_self = [];
1067
+ const battle_goal = [];
1068
+ const playUser = [];
1069
+ const lostMsg = [];
1070
+ goal = goal.filter((item) => {
1071
+ const isBattle = BattleData.isBattleByUserId(item.userId);
1072
+ const pyUser = User.userTempData[item.userId];
1073
+ if (isBattle) {
1074
+ lostMsg.push(`${pyUser.playName}正在参与着一场战斗,无法被PK选中。`);
1075
+ return false;
833
1076
  }
834
- await User.ctx.monetary.cost(bindData.aid, val);
835
- fn && fn({
836
- val: Math.abs(val),
837
- currentVal: currentM.value - val
1077
+ return true;
1078
+ });
1079
+ if (lostMsg.length) {
1080
+ await session.send(lostMsg.join("\n"));
1081
+ }
1082
+ if (!goal.length) {
1083
+ lostMsg.push(`PK失败,无任何目标进行PK`);
1084
+ return;
1085
+ }
1086
+ if (BattleData.isTeam(session) && BattleData.teamTemp[session.userId].identity == "队员") {
1087
+ await session.send("你不是队伍的队长,无法主动操作战斗!");
1088
+ return;
1089
+ } else if (BattleData.isTeam(session)) {
1090
+ Object.keys(BattleData.teamTemp).forEach((item) => {
1091
+ if (BattleData.teamTemp[item].for == session.userId) {
1092
+ playUser.push(item);
1093
+ battle_self.push(initBattleAttribute(User.getUserAttributeByUserId(item)));
1094
+ }
838
1095
  });
1096
+ } else {
1097
+ playUser.push(session.userId);
1098
+ battle_self.push(initBattleAttribute(User.getUserAttributeByUserId(session.userId)));
839
1099
  }
1100
+ goal.forEach((item) => {
1101
+ playUser.push(item.userId);
1102
+ battle_goal.push(initBattleAttribute(User.getUserAttributeByUserId(item.userId)));
1103
+ });
1104
+ const pkTemp = {
1105
+ self: battle_self.map((i) => ({ ...i, for: "self" })),
1106
+ goal: battle_goal.map((i) => ({ ...i, for: "goal" })),
1107
+ isPK: true
1108
+ };
1109
+ playUser.forEach((userId) => {
1110
+ BattleData.lastPlay[userId] = pkTemp;
1111
+ });
1112
+ await session.send(`开始与玩家 ${battle_goal.map((i) => i.name).join("、")} 进行PK战斗`);
840
1113
  },
841
- /** 目标是否死亡 */
842
- isDie(userId) {
843
- return User.userTempData[userId]?.isDie;
844
- }
845
- };
846
-
847
- // src/monster.ts
848
- var import_koishi = require("koishi");
849
-
850
- // src/data/initMonster.ts
851
- var monsterData = {
852
- "小蜜蜂": {
853
- name: "小蜜蜂",
854
- type: "野怪" /* 野怪 */,
855
- info: "幻想乡一层常见的生物",
856
- pic: "http://smmcat.cn/run/gensokyo/小蜜蜂.png",
857
- hp: 50,
858
- maxHp: 50,
859
- mp: 30,
860
- maxMp: 30,
861
- atk: 7,
862
- def: 2,
863
- chr: 50,
864
- csr: 0,
865
- evasion: 100,
866
- hit: 1e3,
867
- ghd: 1.2,
868
- speed: 4,
869
- giveExp: 10,
870
- giveMonetary: 2
871
- },
872
- "小蜘蛛": {
873
- name: "小蜘蛛",
874
- type: "野怪" /* 野怪 */,
875
- info: "幻想乡一层常见的生物",
876
- pic: "http://smmcat.cn/run/gensokyo/小蜘蛛.png",
877
- hp: 55,
878
- maxHp: 55,
879
- mp: 30,
880
- maxMp: 30,
881
- atk: 10,
882
- def: 3,
883
- chr: 50,
884
- csr: 0,
885
- evasion: 150,
886
- hit: 1e3,
887
- ghd: 1.2,
888
- speed: 4,
889
- giveExp: 12,
890
- giveMonetary: 2
891
- },
892
- "dora": {
893
- name: "dora",
894
- type: "野怪" /* 野怪 */,
895
- info: "偶尔出没在一层世界的奇怪生物",
896
- pic: "http://smmcat.cn/run/gensokyo/dora.png",
897
- hp: 88,
898
- maxHp: 88,
899
- mp: 10,
900
- maxMp: 10,
901
- atk: 20,
902
- def: 5,
903
- chr: 200,
904
- csr: 0,
905
- evasion: 200,
906
- hit: 1e3,
907
- ghd: 1.2,
908
- speed: 4,
909
- giveExp: 15,
910
- giveMonetary: 3
911
- }
912
- };
913
-
914
- // src/monster.ts
915
- var Monster = {
916
- config: {},
917
- ctx: {},
918
- monsterTempData: {},
919
- async init(config, ctx) {
920
- Monster.config = config;
921
- Monster.ctx = ctx;
922
- ctx.model.extend(
923
- "smm_gensokyo_monster_attribute",
924
- {
925
- id: "integer",
926
- name: "string",
927
- info: "string",
928
- type: "string",
929
- hp: "integer",
930
- maxHp: "integer",
931
- mp: "integer",
932
- maxMp: "integer",
933
- atk: "integer",
934
- def: "integer",
935
- chr: "integer",
936
- evasion: "integer",
937
- hit: "integer",
938
- ghd: "integer",
939
- speed: "integer"
940
- },
941
- {
942
- primary: "id",
943
- autoInc: false
1114
+ /** 文本化当前战况 */
1115
+ battleSituationTextFormat(team) {
1116
+ const selfTemp = [];
1117
+ const goalTemp = [];
1118
+ team.self.forEach((item) => {
1119
+ if (item.hp > 0) {
1120
+ selfTemp.push(`lv.${item.lv}[${item.name}]:
1121
+ ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
1122
+ MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
1123
+ } else {
1124
+ selfTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
944
1125
  }
945
- );
946
- const monsterData2 = await ctx.database.get("smm_gensokyo_monster_attribute", {});
947
- if (monsterData2.length == 0) {
948
- Monster.monsterTempData = Monster._createInitMonsterData();
949
- } else {
950
- const temp = {};
951
- monsterData2.forEach((item) => {
952
- temp[item.id] = item;
953
- });
954
- Monster.monsterTempData = temp;
1126
+ });
1127
+ team.goal.forEach((item) => {
1128
+ if (item.hp > 0) {
1129
+ goalTemp.push(`lv.${item.lv}[${item.name}]:
1130
+ ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
1131
+ MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
1132
+ } else {
1133
+ goalTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
1134
+ }
1135
+ });
1136
+ if (team.isPK) {
1137
+ return `[当前战况]
1138
+ 攻击方:
1139
+ ` + selfTemp.join("\n") + "\n\n防御方:\n" + goalTemp.join("\n");
955
1140
  }
1141
+ return `[当前战况]
1142
+ 我方阵容:
1143
+ ` + selfTemp.join("\n") + "\n\n敌方阵容:\n" + goalTemp.join("\n");
956
1144
  },
957
- /** 赋予原始的怪物数据 */
958
- _createInitMonsterData() {
959
- return monsterData;
1145
+ /** 判断输赢 */
1146
+ playOver(team) {
1147
+ const self = team.self.every((item) => item.hp <= 0);
1148
+ const goal = team.goal.every((item) => item.hp <= 0);
1149
+ if (self && goal) {
1150
+ return { over: true, type: "平局", win: "" };
1151
+ } else if (self) {
1152
+ return { over: true, type: team.isPK ? "防御方赢" : "敌方赢", win: "goal" };
1153
+ } else if (goal) {
1154
+ return { over: true, type: team.isPK ? "攻击方赢" : "我方赢", win: "self" };
1155
+ }
1156
+ return { over: false, type: "未结束", win: "" };
960
1157
  },
961
- getMonsterAttributeData(monsterName, lv) {
962
- const monster = Monster.monsterTempData[monsterName];
963
- if (!monster) return null;
964
- const temp = { lv };
965
- const lvScope = Object.keys(monsterBenchmark).reverse().find((item) => Number(item) < lv) || 10;
966
- const useBenchmark = monsterBenchmark[lvScope];
967
- console.log(useBenchmark);
968
- Object.keys(monster).forEach((i) => {
969
- temp[i] = monster[i];
970
- if (useBenchmark[i]) {
971
- temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
1158
+ /** 清理战场 */
1159
+ clearBattleData(session) {
1160
+ const currentBattle = BattleData.lastPlay[session.userId];
1161
+ const allAgentList = [...currentBattle.goal, ...currentBattle.self];
1162
+ allAgentList.forEach((item) => {
1163
+ if (item.type == "玩家") {
1164
+ delete BattleData.lastPlay[item.userId];
972
1165
  }
973
1166
  });
974
- return temp;
975
1167
  },
976
- /** 格式化怪物属性数据 */
977
- monsterAttributeTextFormat(monster) {
978
- const { name: name2, type, lv, hp, maxHp, mp, maxMp, atk, def, chr, evasion, hit, ghd, speed, info, pic } = monster;
979
- const attributeText = (pic ? import_koishi.h.image(pic) + "\n" : "") + `Lv.${lv}【${name2}】
980
-
981
- 【怪物类型】${type}
982
- 【生命值】${hp}/${maxHp}
983
- 【魔法值】${mp}/${maxMp}
984
- 【攻击力】${atk}
985
- 【防御力】${def}
986
- 【闪避值】${evasion}
987
- 【命中值】${hit}
988
- 【速度值】${speed}
989
- 【暴击率】${(chr / 10).toFixed(1)}%
990
- 【爆伤倍率】${(ghd * 100).toFixed(0)}%` + (info ? "\n\n" + info : "");
991
- return attributeText;
992
- }
993
- };
994
-
995
- // src/utlis.ts
996
- var random = /* @__PURE__ */ __name((min, max) => {
997
- return Math.floor(Math.random() * (max - min + 1)) + min;
998
- }, "random");
999
- var generateHealthDisplay = /* @__PURE__ */ __name((current, total) => {
1000
- const ratio = current / total;
1001
- const displayLength = 10;
1002
- const filledLength = Math.floor(ratio * displayLength);
1003
- const unfilledLength = displayLength - filledLength;
1004
- const filled = "■".repeat(filledLength);
1005
- const unfilled = "□".repeat(unfilledLength);
1006
- return filled + unfilled;
1007
- }, "generateHealthDisplay");
1008
-
1009
- // src/damage.ts
1010
- var Damage = class {
1011
- static {
1012
- __name(this, "Damage");
1013
- }
1014
- config;
1015
- constructor(agent, realHarm = false) {
1016
- this.config = {
1017
- agent: { self: { ...agent.self }, goal: { ...agent.goal } },
1018
- harm: 0,
1019
- default_harm: 0,
1020
- isRealHarm: realHarm,
1021
- isEvasion: false,
1022
- isCsp: false,
1023
- isBadDef: false
1024
- };
1025
- }
1026
- /** 伤害判定前 */
1027
- before(fn) {
1028
- this.config.default_harm = this.config.agent.self.atk + this.config.agent.self.gain.atk;
1029
- fn && fn(this.config);
1030
- return this;
1031
- }
1032
- /** 真实伤害判定 */
1033
- beforRealHarm(fn) {
1034
- fn && fn(this.config);
1035
- if (this.config.isRealHarm) {
1036
- this.config.harm = this.config.default_harm;
1168
+ async play(session, atkType, select) {
1169
+ if (!BattleData.isBattle(session)) {
1170
+ await session.send("您并没有任何参与战斗。");
1171
+ return;
1037
1172
  }
1038
- return this;
1039
- }
1040
- /** 是否闪避判定 */
1041
- evasion(fn) {
1042
- const { self, goal } = this.config.agent;
1043
- if (this.config.isRealHarm) return this;
1044
- const lvSup = /* @__PURE__ */ __name(() => Math.floor((goal.lv - self.lv) / 5) * 20, "lvSup");
1045
- const evaVal = Math.min(95, (goal.evasion + goal.gain.evasion - self.hit + lvSup()) / 10);
1046
- if (random(0, 100) <= evaVal) {
1047
- this.config.isEvasion = true;
1048
- fn && fn(this.config);
1049
- return this;
1173
+ const currentBattle = BattleData.lastPlay[session.userId];
1174
+ const allAgentList = [...currentBattle.goal, ...currentBattle.self].sort((a, b) => b.speed - a.speed);
1175
+ const msgList = [];
1176
+ for (const agent of allAgentList) {
1177
+ if (agent.hp <= 0) {
1178
+ if (agent.type == "玩家" && !User.userTempData[agent.userId]?.isDie) {
1179
+ User.userTempData[agent.userId].hp = 0;
1180
+ User.userTempData[agent.userId].isDie = true;
1181
+ }
1182
+ continue;
1183
+ }
1184
+ let lifeGoalList = [];
1185
+ let lifeSelfList = [];
1186
+ if (agent.for == "self") {
1187
+ lifeGoalList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
1188
+ lifeSelfList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
1189
+ } else {
1190
+ lifeGoalList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
1191
+ lifeSelfList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
1192
+ }
1193
+ if (!lifeGoalList.length) continue;
1194
+ let selectGoal = {};
1195
+ let isMy = false;
1196
+ let funType = "普攻";
1197
+ if (agent.type == "玩家" && agent.userId == session.userId) {
1198
+ isMy = true;
1199
+ funType = atkType;
1200
+ selectGoal = lifeGoalList.find((item) => item.name == select) || lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1201
+ } else if (agent.type == "玩家") {
1202
+ selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1203
+ } else {
1204
+ selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1205
+ }
1206
+ const noralAtk = /* @__PURE__ */ __name(() => {
1207
+ const damageInfo = new Damage({ self: agent, goal: selectGoal }).result();
1208
+ giveDamage(agent, selectGoal, damageInfo);
1209
+ msgList.push(
1210
+ `${getLineupName(agent)} 使用普攻攻击了 ${getLineupName(selectGoal)},造成了${damageInfo.harm}伤害。` + moreDamageInfo(damageInfo)
1211
+ );
1212
+ }, "noralAtk");
1213
+ if (funType == "普攻") {
1214
+ noralAtk();
1215
+ } else {
1216
+ if (skillFn[atkType]) {
1217
+ if (["治疗技" /* 治疗技 */, "增益技" /* 增益技 */].includes(skillFn[atkType].type)) {
1218
+ selectGoal = lifeSelfList.find((item) => item.name == select) || agent;
1219
+ }
1220
+ const selectFn = skillFn[atkType];
1221
+ if (selectFn.mp == 0 || agent.mp - selectFn.mp >= 0) {
1222
+ agent.mp -= selectFn.mp;
1223
+ let isNext = false;
1224
+ const fnMsg = selectFn.fn(
1225
+ { self: agent, goal: selectGoal },
1226
+ { selfList: lifeSelfList, goalList: lifeGoalList },
1227
+ (val) => {
1228
+ switch (val.type) {
1229
+ case "伤害技" /* 伤害技 */:
1230
+ val.target.map((goal) => {
1231
+ giveDamage(agent, goal, val.damage);
1232
+ });
1233
+ break;
1234
+ case "治疗技" /* 治疗技 */:
1235
+ val.target.map((goal) => {
1236
+ giveCure(goal, val.value);
1237
+ });
1238
+ break;
1239
+ case "释放失败" /* 释放失败 */:
1240
+ val.err && session.send(val.err);
1241
+ default:
1242
+ break;
1243
+ }
1244
+ isNext = val.isNext;
1245
+ }
1246
+ );
1247
+ fnMsg && msgList.push(fnMsg);
1248
+ isNext && noralAtk();
1249
+ } else {
1250
+ await session.send(`MP不足,释放失败!`);
1251
+ noralAtk();
1252
+ }
1253
+ } else {
1254
+ await session.send(`未持有该技能或者该技能不存在,释放失败!`);
1255
+ noralAtk();
1256
+ }
1257
+ }
1050
1258
  }
1051
- fn && fn(this.config);
1052
- return this;
1053
- }
1054
- /** 是否暴击判定 */
1055
- csp(fn) {
1056
- const { self, goal } = this.config.agent;
1057
- if (this.config.isRealHarm) return this;
1058
- if (this.config.isEvasion) return this;
1059
- const cspVal = (self.chr + self.gain.chr - goal.csr) / 10;
1060
- if (random(0, 100) <= cspVal) {
1061
- this.config.isCsp = true;
1062
- this.config.harm = Math.floor(this.config.default_harm * (self.ghd + self.gain.ghd));
1063
- fn && fn(this.config);
1064
- return this;
1259
+ await session.send(msgList.length ? `战斗记录:
1260
+ ` + msgList.join("\n") : "");
1261
+ await session.send(BattleData.battleSituationTextFormat(currentBattle));
1262
+ const result = BattleData.playOver(currentBattle);
1263
+ if (result.over) {
1264
+ await session.send(result.type);
1265
+ await BattleData.settlement(currentBattle, result, session);
1266
+ BattleData.clearBattleData(session);
1065
1267
  }
1066
- this.config.harm = this.config.default_harm;
1067
- fn && fn(this.config);
1068
- return this;
1069
- }
1070
- /** 防御结算 */
1071
- beforDef(fn) {
1072
- const { goal } = this.config.agent;
1073
- if (this.config.isRealHarm) return this;
1074
- if (this.config.isEvasion) return this;
1075
- const dpVal = goal.def + goal.gain.def;
1076
- fn && fn(this.config);
1077
- if (this.config.harm - dpVal > 0) {
1078
- this.config.harm -= dpVal;
1268
+ },
1269
+ /** 结算奖励 */
1270
+ async settlement(tempData, overInfo, session) {
1271
+ const allList = [...tempData.self, ...tempData.goal].filter((item) => item.type == "玩家");
1272
+ const selfList = tempData.self.filter((item) => item.type == "玩家");
1273
+ const goalList = tempData.goal.filter((item) => item.type == "玩家");
1274
+ const msg = /* @__PURE__ */ __name(async (val) => {
1275
+ const msgTemp = `${val.name}[升级]${val.lv}级!
1276
+ ` + (val.atk ? `攻击力↑ ${val.atk}
1277
+ ` : "") + (val.def ? `防御力↑ ${val.def}
1278
+ ` : "") + (val.maxHp ? `最大血量↑ ${val.maxHp}
1279
+ ` : "") + (val.maxMp ? `最大蓝量↑ ${val.maxMp}` : "");
1280
+ await session.send(msgTemp);
1281
+ }, "msg");
1282
+ const aynchronize = /* @__PURE__ */ __name((agent) => {
1283
+ User.userTempData[agent.userId].hp = agent.hp;
1284
+ User.userTempData[agent.userId].mp = agent.mp;
1285
+ }, "aynchronize");
1286
+ if (tempData.isPK) {
1287
+ if (overInfo.win == "self") {
1288
+ await session.send("攻击方获得20EXP、5货币");
1289
+ for (const agent of allList) {
1290
+ aynchronize(agent);
1291
+ if (agent.for == "self") {
1292
+ if (agent.hp <= 0) {
1293
+ User.userTempData[agent.userId].hp = 0;
1294
+ User.userTempData[agent.userId].isDie = true;
1295
+ }
1296
+ await User.giveExp(agent.userId, 20, async (val) => await msg(val));
1297
+ await User.giveMonetary(agent.userId, 5);
1298
+ }
1299
+ }
1300
+ } else if (overInfo.win == "goal") {
1301
+ await session.send("防御方获得20EXP、5货币");
1302
+ for (const agent of allList) {
1303
+ aynchronize(agent);
1304
+ if (agent.for == "goal") {
1305
+ if (agent.hp <= 0) {
1306
+ User.userTempData[agent.userId].hp = 0;
1307
+ User.userTempData[agent.userId].isDie = true;
1308
+ }
1309
+ await User.giveExp(agent.userId, 20, async (val) => await msg(val));
1310
+ await User.giveMonetary(agent.userId, 5);
1311
+ }
1312
+ }
1313
+ }
1079
1314
  } else {
1080
- this.config.isBadDef = true;
1081
- this.config.harm = 1;
1315
+ let val = 0;
1316
+ let monetary = 0;
1317
+ let props = [];
1318
+ const monsterName = tempData.goal.filter((item) => item.type == "怪物").map((i) => ({ name: i.name, lv: i.lv }));
1319
+ monsterName.forEach((item) => {
1320
+ const monster = Monster.monsterTempData[item.name];
1321
+ if (monster) {
1322
+ val += Math.floor(monster.giveExp + monster.giveExp * (item.lv - 1) * 0.2);
1323
+ monetary += Math.floor(monster.giveMonetary + monster.giveExp * (item.lv - 1) * 0.1);
1324
+ monster.giveProps?.forEach((propsItem) => {
1325
+ if (item.lv >= (propsItem.lv || 1) && random(0, 100) < propsItem.radomVal) {
1326
+ props.push({
1327
+ name: propsItem.name,
1328
+ val: propsItem.const ? propsItem.val : random(1, propsItem.val)
1329
+ });
1330
+ }
1331
+ });
1332
+ }
1333
+ });
1334
+ await session.send(`小队获得${val}EXP、${monetary}货币!`);
1335
+ for (const agent of selfList) {
1336
+ aynchronize(agent);
1337
+ if (overInfo.win == "self") {
1338
+ await User.giveExp(agent.userId, val, async (val2) => await msg(val2));
1339
+ await User.giveMonetary(agent.userId, monetary);
1340
+ props.length && await User.giveProps(agent.userId, props, async (val2) => {
1341
+ const propsDict = {};
1342
+ val2.currentProps.forEach((item) => {
1343
+ if (!propsDict[item.name]) propsDict[item.name] = 1;
1344
+ propsDict[item.name]++;
1345
+ });
1346
+ const msg2 = Object.keys(propsDict).map((item) => {
1347
+ return `${item} ${propsDict[item]}个`;
1348
+ }).join("\n");
1349
+ await session.send(`${agent.name}在战斗中获得:` + msg2);
1350
+ });
1351
+ }
1352
+ }
1082
1353
  }
1083
- return this;
1084
- }
1085
- result(fn) {
1086
- this.before((val) => {
1087
- fn?.before && fn.before(val);
1088
- }).beforRealHarm((val) => {
1089
- fn?.beforRealHarm && fn.beforRealHarm(val);
1090
- }).evasion((val) => {
1091
- fn?.evasion && fn.evasion(val);
1092
- }).csp((val) => {
1093
- fn?.csp && fn.csp(val);
1094
- }).beforDef((val) => {
1095
- fn?.beforDef && fn.beforDef(val);
1096
- });
1097
- return this.config;
1098
1354
  }
1099
1355
  };
1100
- function giveDamage(self, goal, damage) {
1101
- if (goal.hp - damage.harm > 0) {
1102
- goal.hp -= damage.harm;
1103
- return damage.harm;
1104
- } else {
1105
- const lostHp = goal.hp;
1106
- goal.hp = 0;
1107
- return lostHp;
1108
- }
1356
+ function getLineupName(agent) {
1357
+ return `[${agent.type}]${agent.name}`;
1109
1358
  }
1110
- __name(giveDamage, "giveDamage");
1111
- function giveCure(goal, val) {
1112
- const upVal = goal.hp + val;
1113
- if (upVal < goal.maxHp + goal.gain.maxHp) {
1114
- goal.hp = upVal;
1115
- return val;
1359
+ __name(getLineupName, "getLineupName");
1360
+ function initBattleAttribute(data) {
1361
+ if ("playName" in data) {
1362
+ const userData = data;
1363
+ const temp = {
1364
+ userId: userData.userId,
1365
+ name: userData.playName,
1366
+ lv: userData.lv,
1367
+ type: "玩家",
1368
+ hp: userData.hp,
1369
+ maxHp: userData.maxHp,
1370
+ mp: userData.mp,
1371
+ maxMp: userData.maxMp,
1372
+ atk: userData.atk,
1373
+ def: userData.def,
1374
+ chr: userData.chr,
1375
+ ghd: userData.ghd,
1376
+ csr: userData.csr,
1377
+ evasion: userData.evasion,
1378
+ hit: userData.hit,
1379
+ speed: userData.speed,
1380
+ gain: {
1381
+ maxHp: 0,
1382
+ maxMp: 0,
1383
+ atk: 0,
1384
+ def: 0,
1385
+ chr: 0,
1386
+ ghd: 0,
1387
+ evasion: 0,
1388
+ hit: 0,
1389
+ speed: 0
1390
+ },
1391
+ buff: [],
1392
+ fn: []
1393
+ };
1394
+ return temp;
1116
1395
  } else {
1117
- const abHp = goal.maxHp + goal.gain.maxHp - goal.hp;
1118
- goal.hp += abHp;
1119
- return abHp;
1396
+ const monsterData2 = data;
1397
+ const temp = {
1398
+ name: monsterData2.name,
1399
+ type: "怪物",
1400
+ lv: monsterData2.lv,
1401
+ hp: monsterData2.hp,
1402
+ maxHp: monsterData2.maxHp,
1403
+ mp: monsterData2.mp,
1404
+ maxMp: monsterData2.maxMp,
1405
+ atk: monsterData2.atk,
1406
+ def: monsterData2.def,
1407
+ chr: monsterData2.chr,
1408
+ ghd: monsterData2.ghd,
1409
+ csr: monsterData2.csr,
1410
+ evasion: monsterData2.evasion,
1411
+ hit: monsterData2.hit,
1412
+ speed: monsterData2.speed,
1413
+ gain: {
1414
+ maxHp: 0,
1415
+ maxMp: 0,
1416
+ atk: 0,
1417
+ def: 0,
1418
+ chr: 0,
1419
+ ghd: 0,
1420
+ evasion: 0,
1421
+ hit: 0,
1422
+ speed: 0
1423
+ },
1424
+ buff: [],
1425
+ fn: []
1426
+ };
1427
+ return temp;
1120
1428
  }
1121
1429
  }
1122
- __name(giveCure, "giveCure");
1123
- function moreDamageInfo(damage) {
1124
- return (damage.isCsp ? `(暴击!)` : "") + (damage.isEvasion ? `(闪避成功!)` : "") + (damage.isBadDef ? `(未破防!)` : "");
1125
- }
1126
- __name(moreDamageInfo, "moreDamageInfo");
1430
+ __name(initBattleAttribute, "initBattleAttribute");
1127
1431
 
1128
- // src/skillFn.ts
1129
- var skillFn = {
1130
- "重砍": {
1131
- name: "重砍",
1132
- type: "伤害技" /* 伤害技 */,
1133
- info: "[伤害技]消耗10MP,对敌方一个单位造成基于攻击力1.2倍伤害。该次伤害无视敌方30%防御!(最低无视1防御)",
1134
- lv: 3,
1135
- mp: 10,
1136
- feature: ["剑士" /* 剑士 */],
1137
- fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1138
- const damageData = new Damage(agent).result({
1139
- before: /* @__PURE__ */ __name((val) => {
1140
- val.default_harm += Math.floor(val.default_harm * 0.2);
1141
- val.agent.goal.def -= Math.floor(val.agent.goal.def * 0.3) || 1;
1142
- }, "before")
1143
- });
1144
- fn({
1145
- damage: damageData,
1146
- type: this.type,
1147
- target: [agent.goal],
1148
- isNext: false
1149
- });
1150
- return `${getLineupName(agent.self)} 释放重砍,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
1151
- }, "fn")
1152
- },
1153
- "突刺": {
1154
- name: "突刺",
1155
- type: "伤害技" /* 伤害技 */,
1156
- info: "[伤害技]消耗10MP,对敌方一个单位造成基于攻击力1.2倍伤害,该伤害无视敌方闪避10%",
1157
- lv: 3,
1158
- mp: 10,
1159
- feature: ["刺客" /* 刺客 */],
1160
- fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1161
- const damageData = new Damage(agent).result({
1162
- before: /* @__PURE__ */ __name((val) => {
1163
- val.default_harm += Math.floor(val.default_harm * 0.2);
1164
- val.agent.goal.evasion -= Math.floor((val.agent.goal.evasion + val.agent.goal.gain.evasion) * 0.1);
1165
- }, "before")
1166
- });
1167
- fn({
1168
- damage: damageData,
1169
- type: this.type,
1170
- target: [agent.goal],
1171
- isNext: false
1172
- });
1173
- return `${getLineupName(agent.self)} 释放突刺,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
1174
- }, "fn")
1175
- },
1176
- "水炮": {
1177
- name: "水炮",
1178
- type: "伤害技" /* 伤害技 */,
1179
- info: "[伤害技]消耗10MP,通过凝集魔力对敌方造成基于攻击力1.2倍伤害,该伤害基于当前剩余魔法值10%额外叠加伤害。",
1180
- lv: 3,
1181
- mp: 10,
1182
- feature: ["法师" /* 法师 */],
1183
- fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1184
- const damageData = new Damage(agent).result({
1185
- before: /* @__PURE__ */ __name((val) => {
1186
- val.default_harm += Math.floor(val.default_harm * 0.2) + Math.floor(val.agent.self.mp * 0.1);
1187
- }, "before")
1188
- });
1189
- fn({
1190
- damage: damageData,
1191
- type: this.type,
1192
- target: [agent.goal],
1193
- isNext: false
1194
- });
1195
- return `${getLineupName(agent.self)} 释放水炮,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
1196
- }, "fn")
1197
- },
1198
- "濒死一击": {
1199
- name: "濒死一击",
1200
- type: "伤害技" /* 伤害技 */,
1201
- info: "[伤害技]血量低于40%可释放,消耗20MP,对敌方一个单位造成基于攻击力2倍伤害。该次伤害暴击率提高20%",
1202
- lv: 3,
1203
- mp: 20,
1204
- fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1205
- if (agent.self.hp / (agent.self.maxHp + agent.self.gain.maxHp) < 0.4) {
1206
- const damageData = new Damage(agent).result({
1207
- before: /* @__PURE__ */ __name((val) => {
1208
- val.default_harm += val.default_harm;
1209
- val.agent.self.chr += 200;
1210
- }, "before")
1211
- });
1212
- fn({
1213
- damage: damageData,
1214
- type: this.type,
1215
- target: [agent.goal],
1216
- isNext: false
1217
- });
1218
- return `${getLineupName(agent.self)} 释放濒死一击,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
1219
- } else {
1220
- fn({
1221
- type: "释放失败" /* 释放失败 */,
1222
- isNext: true,
1223
- err: "释放失败,未达成条件。"
1224
- });
1225
- return ``;
1226
- }
1227
- }, "fn")
1432
+ // src/users.ts
1433
+ var UserOccDict = {
1434
+ ["剑士" /* 剑士 */]: {
1435
+ info: "擅长近战攻击,拥有强大的属性能力",
1436
+ initStatus: {
1437
+ userId: "",
1438
+ playName: "",
1439
+ type: "剑士" /* 剑士 */,
1440
+ exp: 0,
1441
+ maxExp: 100,
1442
+ lv: 1,
1443
+ hp: 120,
1444
+ maxHp: 120,
1445
+ mp: 80,
1446
+ maxMp: 80,
1447
+ pp: 100,
1448
+ maxPp: 100,
1449
+ atk: 12,
1450
+ def: 5,
1451
+ chr: 50,
1452
+ csr: 0,
1453
+ ghd: 1.2,
1454
+ speed: 5,
1455
+ evasion: 100,
1456
+ hit: 100
1457
+ }
1228
1458
  },
1229
- "初级治愈": {
1230
- name: "初级治愈",
1231
- type: "治疗技" /* 治疗技 */,
1232
- info: "[治疗技]直接恢复自身或者目标 40HP",
1233
- lv: 1,
1234
- mp: 30,
1235
- fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1236
- const selectGoal = agent.goal;
1237
- fn({
1238
- value: 40,
1239
- target: [selectGoal],
1240
- type: "治疗技" /* 治疗技 */,
1241
- isNext: false
1242
- });
1243
- return `${getLineupName(agent.self)}释放初级治愈,${getLineupName(agent.goal)}恢复40HP`;
1244
- }, "fn")
1459
+ ["法师" /* 法师 */]: {
1460
+ info: "精通元素魔法,能够打出爆发伤害",
1461
+ initStatus: {
1462
+ userId: "",
1463
+ playName: "",
1464
+ type: "法师" /* 法师 */,
1465
+ exp: 0,
1466
+ maxExp: 100,
1467
+ lv: 1,
1468
+ hp: 100,
1469
+ maxHp: 100,
1470
+ mp: 100,
1471
+ maxMp: 100,
1472
+ pp: 100,
1473
+ maxPp: 100,
1474
+ atk: 10,
1475
+ def: 2,
1476
+ chr: 50,
1477
+ csr: 0,
1478
+ ghd: 1.2,
1479
+ speed: 5,
1480
+ evasion: 100,
1481
+ hit: 100
1482
+ }
1483
+ },
1484
+ ["刺客" /* 刺客 */]: {
1485
+ info: "迅捷攻击,高闪避值的高敏玩家",
1486
+ initStatus: {
1487
+ userId: "",
1488
+ playName: "",
1489
+ type: "刺客" /* 刺客 */,
1490
+ exp: 0,
1491
+ maxExp: 100,
1492
+ lv: 1,
1493
+ hp: 90,
1494
+ maxHp: 90,
1495
+ mp: 70,
1496
+ maxMp: 70,
1497
+ pp: 100,
1498
+ maxPp: 100,
1499
+ atk: 8,
1500
+ def: 2,
1501
+ chr: 80,
1502
+ csr: 0,
1503
+ ghd: 1.3,
1504
+ speed: 6,
1505
+ evasion: 120,
1506
+ hit: 100
1507
+ }
1245
1508
  }
1246
1509
  };
1247
-
1248
- // src/battle.ts
1249
- var BattleData = {
1510
+ var User = {
1250
1511
  config: {},
1251
1512
  ctx: {},
1252
- historyTemp: {},
1253
- lastPlay: {},
1254
- teamTemp: {},
1255
- init(config, ctx) {
1256
- this.config = config;
1257
- this.ctx = ctx;
1258
- },
1259
- /** 玩家是否正在战斗 */
1260
- isBattle(session) {
1261
- return !!BattleData.lastPlay[session.userId];
1262
- },
1263
- /** 玩家是否正在战斗 */
1264
- isBattleByUserId(userId) {
1265
- return !!BattleData.lastPlay[userId];
1266
- },
1267
- /** 玩家是否在队伍中 */
1268
- isTeam(session) {
1269
- return !!BattleData.teamTemp[session.userId];
1270
- },
1271
- isTeamByUserId(userId) {
1272
- return !!BattleData.teamTemp[userId];
1513
+ userTempData: {},
1514
+ async init(config, ctx) {
1515
+ User.config = config;
1516
+ User.ctx = ctx;
1517
+ ctx.model.extend(
1518
+ "smm_gensokyo_user_attribute",
1519
+ {
1520
+ userId: "string",
1521
+ playName: "string",
1522
+ type: "string",
1523
+ exp: "integer",
1524
+ lv: "integer",
1525
+ hp: "integer",
1526
+ mp: "integer",
1527
+ pp: "integer",
1528
+ isDie: "boolean"
1529
+ },
1530
+ {
1531
+ primary: "userId",
1532
+ autoInc: false
1533
+ }
1534
+ );
1535
+ const userData = await ctx.database.get("smm_gensokyo_user_attribute", {});
1536
+ const temp = {};
1537
+ userData.forEach((item) => {
1538
+ temp[item.userId] = item;
1539
+ });
1540
+ User.userTempData = temp;
1273
1541
  },
1274
- // 返回队伍信息
1275
- teamListByUser(userId) {
1276
- const teamList = [];
1277
- if (!BattleData.teamTemp[userId]) {
1278
- return [];
1542
+ /** 获取角色基础属性 */
1543
+ async getUserAttribute(session) {
1544
+ if (!User.userTempData[session.userId]) {
1545
+ await session.send("未创建账户,请发送 /开始注册 完成账号的注册!");
1546
+ return null;
1279
1547
  }
1280
- const _userId = BattleData.teamTemp[userId].for;
1281
- Object.keys(BattleData.teamTemp).forEach((item) => {
1282
- if (BattleData.teamTemp[item].for == _userId) {
1283
- teamList.push(User.getUserAttributeByUserId(item));
1548
+ return User.getUserAddLvAttribute(session.userId);
1549
+ },
1550
+ /** 获取角色实际等级属性数据 */
1551
+ getUserAddLvAttribute(userId) {
1552
+ const UserDict = User.userTempData[userId];
1553
+ if (!UserDict) return null;
1554
+ const UserData = {
1555
+ ...UserOccDict[UserDict.type].initStatus,
1556
+ lv: UserDict.lv,
1557
+ hp: UserDict.hp,
1558
+ mp: UserDict.mp,
1559
+ exp: UserDict.exp,
1560
+ pp: UserDict.pp,
1561
+ playName: UserDict.playName,
1562
+ userId: UserDict.userId
1563
+ };
1564
+ const lv = UserData.lv;
1565
+ const temp = {};
1566
+ const lvScope = Object.keys(userBenchmark).reverse().find((item) => Number(item) < lv) || 10;
1567
+ const useBenchmark = userBenchmark[lvScope];
1568
+ Object.keys(UserData).forEach((i) => {
1569
+ temp[i] = UserData[i];
1570
+ if (useBenchmark[i]) {
1571
+ if (i == "maxExp") {
1572
+ temp[i] = Math.floor(100 * useBenchmark[i] * (lv - 1)) || 100;
1573
+ } else {
1574
+ temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
1575
+ }
1284
1576
  }
1285
1577
  });
1286
- return teamList;
1578
+ return temp;
1287
1579
  },
1288
- /** 创建战斗-与怪物 */
1289
- async createBattleByMonster(session, goal) {
1290
- if (BattleData.isBattle(session)) {
1291
- await session.send("当前正在战斗,还不能逃脱!");
1580
+ /** 通过 userId 获取角色属性 */
1581
+ getUserAttributeByUserId(userId) {
1582
+ return User.getUserAddLvAttribute(userId) || null;
1583
+ },
1584
+ /** 创建游戏账号 */
1585
+ async createPlayUser(session) {
1586
+ const [data] = await User.ctx.database.get("smm_gensokyo_user_attribute", { userId: session.userId });
1587
+ if (data) {
1588
+ await session.send("已存在账号,请勿重复创建!");
1292
1589
  return;
1293
1590
  }
1294
- const battle_user = [];
1295
- const battle_monsterList = [];
1296
- const playUser = [];
1297
- if (BattleData.isTeam(session) && BattleData.teamTemp[session.userId].identity == "队员") {
1298
- await session.send("你不是队伍的队长,无法主动操作战斗!");
1591
+ await session.send("请输入自己的游戏昵称:(60s)");
1592
+ const playname = await session.prompt(6e4);
1593
+ if (playname == void 0) return;
1594
+ const [repeat] = await User.ctx.database.get("smm_gensokyo_user_attribute", { playName: playname.trim() });
1595
+ if (repeat) {
1596
+ await session.send("名字重复,请更换一个名字。");
1299
1597
  return;
1300
- } else if (BattleData.isTeam(session)) {
1301
- Object.keys(BattleData.teamTemp).forEach((item) => {
1302
- if (BattleData.teamTemp[item].for == session.userId) {
1303
- playUser.push(item);
1304
- battle_user.push(initBattleAttribute(User.getUserAttributeByUserId(item)));
1305
- }
1306
- });
1307
- } else {
1308
- playUser.push(session.userId);
1309
- battle_user.push(initBattleAttribute(User.getUserAttributeByUserId(session.userId)));
1310
1598
  }
1311
- goal.forEach((item) => {
1312
- battle_monsterList.push(initBattleAttribute(Monster.getMonsterAttributeData(item.name, item.lv)));
1313
- });
1599
+ if (playname.trim().length > 6 || playname.trim().length < 1) {
1600
+ await session.send("名字长度有问题,要求小于 6个字,大于 1个字");
1601
+ return;
1602
+ }
1603
+ await session.send(`请输入要专职的职业:(60s)
1604
+ ${Object.keys(UserOccDict).map((i) => `【${i}】:${UserOccDict[i].info}`).join("\n")}`);
1605
+ let jobType = await session.prompt(6e4);
1606
+ if (jobType == void 0) return;
1607
+ while (!Object.keys(UserOccDict).includes(jobType)) {
1608
+ await session.send("未找到该职业,请重新选择!");
1609
+ jobType = await session.prompt(6e4);
1610
+ }
1611
+ const temp = {
1612
+ userId: session.userId,
1613
+ playName: playname.trim(),
1614
+ type: jobType,
1615
+ hp: UserOccDict[jobType].initStatus.hp,
1616
+ pp: UserOccDict[jobType].initStatus.pp,
1617
+ mp: UserOccDict[jobType].initStatus.mp,
1618
+ lv: 1,
1619
+ exp: 0,
1620
+ isDie: false
1621
+ };
1622
+ User.ctx.database.create("smm_gensokyo_user_attribute", temp);
1623
+ User.userTempData[session.userId] = temp;
1624
+ await Props.initUserPropsData(session.userId);
1625
+ await session.send("创建成功!\n" + User.userAttributeTextFormat(session.userId));
1626
+ },
1627
+ /** 信息格式化 */
1628
+ userAttributeTextFormat(userId) {
1629
+ if (!User.userTempData[userId]) {
1630
+ return "没有找到您的角色信息";
1631
+ }
1632
+ const temp = User.getUserAttributeByUserId(userId);
1633
+ return `昵称:${temp.playName}
1634
+ 职位:${temp.type}
1635
+ 等级:${temp.lv} (${temp.exp}/${temp.maxExp})
1636
+ -----------------
1637
+ 【生命值】${temp.hp}/${temp.maxHp}
1638
+ 【魔法值】${temp.mp}/${temp.maxMp}
1639
+ 【活力值】${temp.pp}/${temp.maxPp}
1640
+ -----------------
1641
+ 【攻击力】${temp.atk} (+0)
1642
+ 【防御力】${temp.def} (+0)
1643
+ 【速度值】${temp.speed} (+0)
1644
+ 【闪避值】${temp.evasion} (+0)
1645
+ 【命中率】${(temp.hit / 10 + 100).toFixed(1)}% (+0%)
1646
+ 【暴击率】${(temp.chr / 10).toFixed(1)}% (+0%)
1647
+ 【暴击伤害】${(temp.ghd * 100).toFixed(1)}% (+0%)` + (temp.csr > 0 ? `
1648
+ 【暴击抵抗】${temp.csr}` : "");
1649
+ },
1650
+ /** 写入用户数据到数据库 */
1651
+ async setDatabaseUserAttribute(userId) {
1652
+ const userInfo = User.userTempData[userId];
1653
+ if (!userInfo) return;
1314
1654
  const temp = {
1315
- self: battle_user.map((i) => ({ ...i, for: "self" })),
1316
- goal: battle_monsterList.map((i) => ({ ...i, for: "goal" }))
1655
+ playName: userInfo.playName.trim(),
1656
+ hp: userInfo.hp,
1657
+ pp: userInfo.pp,
1658
+ mp: userInfo.mp,
1659
+ lv: userInfo.lv,
1660
+ exp: userInfo.exp
1317
1661
  };
1318
- playUser.forEach((userId) => {
1319
- BattleData.lastPlay[userId] = temp;
1320
- });
1321
- await session.send(`开始与 ${goal.map((i) => i.name).join("、")} 进行战斗`);
1662
+ User.ctx.database.set("smm_gensokyo_user_attribute", { userId }, temp);
1322
1663
  },
1323
- /** 创建战斗-与玩家 */
1324
- async createBattleByUser(session, goal) {
1325
- if (BattleData.isBattle(session)) {
1326
- await session.send("当前正在战斗,还不能逃脱!");
1327
- return;
1328
- }
1329
- const battle_self = [];
1330
- const battle_goal = [];
1331
- const playUser = [];
1332
- const lostMsg = [];
1333
- goal = goal.filter((item) => {
1334
- const isBattle = BattleData.isBattleByUserId(item.userId);
1335
- const pyUser = User.userTempData[item.userId];
1336
- if (isBattle) {
1337
- lostMsg.push(`${pyUser.playName}正在参与着一场战斗,无法被PK选中。`);
1338
- return false;
1339
- }
1340
- return true;
1341
- });
1342
- if (lostMsg.length) {
1343
- await session.send(lostMsg.join("\n"));
1344
- }
1345
- if (!goal.length) {
1346
- lostMsg.push(`PK失败,无任何目标进行PK`);
1347
- return;
1664
+ /** 给予玩家经验 */
1665
+ async giveExp(userId, value, fn) {
1666
+ const userInfo = User.userTempData[userId];
1667
+ if (!userInfo) return;
1668
+ const beforData = { ...User.getUserAttributeByUserId(userId) };
1669
+ let isUp = false;
1670
+ userInfo.exp += value;
1671
+ while (true) {
1672
+ const { maxExp } = User.getUserAttributeByUserId(userId);
1673
+ if (userInfo.exp < maxExp) break;
1674
+ userInfo.lv += 1;
1675
+ userInfo.exp -= maxExp;
1676
+ isUp = true;
1348
1677
  }
1349
- if (BattleData.isTeam(session) && BattleData.teamTemp[session.userId].identity == "队员") {
1350
- await session.send("你不是队伍的队长,无法主动操作战斗!");
1351
- return;
1352
- } else if (BattleData.isTeam(session)) {
1353
- Object.keys(BattleData.teamTemp).forEach((item) => {
1354
- if (BattleData.teamTemp[item].for == session.userId) {
1355
- playUser.push(item);
1356
- battle_self.push(initBattleAttribute(User.getUserAttributeByUserId(item)));
1357
- }
1358
- });
1359
- } else {
1360
- playUser.push(session.userId);
1361
- battle_self.push(initBattleAttribute(User.getUserAttributeByUserId(session.userId)));
1678
+ if (isUp) {
1679
+ const afterData = User.getUserAttributeByUserId(userId);
1680
+ const upTemp = {
1681
+ name: afterData.playName,
1682
+ lv: afterData.lv,
1683
+ maxHp: afterData.maxHp - beforData.maxHp,
1684
+ maxMp: afterData.maxMp = beforData.maxMp,
1685
+ atk: afterData.atk - beforData.atk,
1686
+ def: afterData.def - beforData.def
1687
+ };
1688
+ fn && await fn(upTemp);
1362
1689
  }
1363
- goal.forEach((item) => {
1364
- playUser.push(item.userId);
1365
- battle_goal.push(initBattleAttribute(User.getUserAttributeByUserId(item.userId)));
1366
- });
1367
- const pkTemp = {
1368
- self: battle_self.map((i) => ({ ...i, for: "self" })),
1369
- goal: battle_goal.map((i) => ({ ...i, for: "goal" })),
1370
- isPK: true
1371
- };
1372
- playUser.forEach((userId) => {
1373
- BattleData.lastPlay[userId] = pkTemp;
1374
- });
1375
- await session.send(`开始与玩家 ${battle_goal.map((i) => i.name).join("、")} 进行PK战斗`);
1690
+ await User.setDatabaseUserAttribute(userId);
1376
1691
  },
1377
- /** 文本化当前战况 */
1378
- battleSituationTextFormat(team) {
1379
- const selfTemp = [];
1380
- const goalTemp = [];
1381
- team.self.forEach((item) => {
1382
- if (item.hp > 0) {
1383
- selfTemp.push(`lv.${item.lv}[${item.name}]:
1384
- ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
1385
- MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
1386
- } else {
1387
- selfTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
1388
- }
1389
- });
1390
- team.goal.forEach((item) => {
1391
- if (item.hp > 0) {
1392
- goalTemp.push(`lv.${item.lv}[${item.name}]:
1393
- ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
1394
- MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
1395
- } else {
1396
- goalTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
1397
- }
1398
- });
1399
- if (team.isPK) {
1400
- return `[当前战况]
1401
- 攻击方:
1402
- ` + selfTemp.join("\n") + "\n\n防御方:\n" + goalTemp.join("\n");
1403
- }
1404
- return `[当前战况]
1405
- 我方阵容:
1406
- ` + selfTemp.join("\n") + "\n\n敌方阵容:\n" + goalTemp.join("\n");
1692
+ /** 给予玩家死亡 */
1693
+ async giveDie(userId) {
1694
+ const userInfo = User.userTempData[userId];
1695
+ userInfo.hp = 0;
1696
+ userInfo.isDie = true;
1697
+ await User.setDatabaseUserAttribute(userId);
1407
1698
  },
1408
- /** 判断输赢 */
1409
- playOver(team) {
1410
- const self = team.self.every((item) => item.hp <= 0);
1411
- const goal = team.goal.every((item) => item.hp <= 0);
1412
- if (self && goal) {
1413
- return { over: true, type: "平局", win: "" };
1414
- } else if (self) {
1415
- return { over: true, type: team.isPK ? "防御方赢" : "敌方赢", win: "goal" };
1416
- } else if (goal) {
1417
- return { over: true, type: team.isPK ? "攻击方赢" : "我方赢", win: "self" };
1699
+ /** 给予玩家复活 */
1700
+ async giveLife(userId, val) {
1701
+ const userInfo = User.userTempData[userId];
1702
+ if (!val) {
1703
+ const { maxHp } = User.getUserAttributeByUserId(userId);
1704
+ userInfo.hp = maxHp;
1705
+ } else {
1706
+ userInfo.hp = val;
1418
1707
  }
1419
- return { over: false, type: "未结束", win: "" };
1420
- },
1421
- /** 清理战场 */
1422
- clearBattleData(session) {
1423
- const currentBattle = BattleData.lastPlay[session.userId];
1424
- const allAgentList = [...currentBattle.goal, ...currentBattle.self];
1425
- allAgentList.forEach((item) => {
1426
- if (item.type == "玩家") {
1427
- delete BattleData.lastPlay[item.userId];
1428
- }
1429
- });
1708
+ await User.setDatabaseUserAttribute(userId);
1430
1709
  },
1431
- async play(session, atkType, select) {
1432
- if (!BattleData.isBattle(session)) {
1433
- await session.send("您并没有任何参与战斗。");
1710
+ /** 给予玩家血量或者蓝量 */
1711
+ async giveHPMP(userId, value, fn) {
1712
+ const userInfo = User.userTempData[userId];
1713
+ if (!userInfo) return;
1714
+ if (userInfo.isDie) {
1715
+ fn && await fn({
1716
+ currentHP: 0,
1717
+ currentMP: 0,
1718
+ err: "角色已死亡,无法使用恢复道具。"
1719
+ });
1434
1720
  return;
1435
1721
  }
1436
- const currentBattle = BattleData.lastPlay[session.userId];
1437
- const allAgentList = [...currentBattle.goal, ...currentBattle.self].sort((a, b) => b.speed - a.speed);
1438
- const msgList = [];
1439
- for (const agent of allAgentList) {
1440
- if (agent.hp <= 0) continue;
1441
- let lifeGoalList = [];
1442
- let lifeSelfList = [];
1443
- if (agent.for == "self") {
1444
- lifeGoalList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
1445
- lifeSelfList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
1446
- } else {
1447
- lifeGoalList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
1448
- lifeSelfList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
1449
- }
1450
- if (!lifeGoalList.length) continue;
1451
- let selectGoal = {};
1452
- let isMy = false;
1453
- let funType = "普攻";
1454
- if (agent.type == "玩家" && agent.userId == session.userId) {
1455
- isMy = true;
1456
- funType = atkType;
1457
- selectGoal = lifeGoalList.find((item) => item.name == select) || lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1458
- } else if (agent.type == "玩家") {
1459
- selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1722
+ if (BattleData.isBattleByUserId(userId)) {
1723
+ const { goal, self } = BattleData.lastPlay[userId];
1724
+ const agentAll = [...goal, ...self];
1725
+ const agent = agentAll.find((item) => item?.userId == userId);
1726
+ if (!agent) return;
1727
+ if (agent.hp + (value.hp || 0) < agent.maxHp) {
1728
+ agent.hp += value.hp || 0;
1460
1729
  } else {
1461
- selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1730
+ agent.hp = agent.maxHp;
1462
1731
  }
1463
- const noralAtk = /* @__PURE__ */ __name(() => {
1464
- const damageInfo = new Damage({ self: agent, goal: selectGoal }).result();
1465
- giveDamage(agent, selectGoal, damageInfo);
1466
- msgList.push(
1467
- `${getLineupName(agent)} 使用普攻攻击了 ${getLineupName(selectGoal)},造成了${damageInfo.harm}伤害。` + moreDamageInfo(damageInfo)
1468
- );
1469
- }, "noralAtk");
1470
- if (funType == "普攻") {
1471
- noralAtk();
1732
+ if (agent.mp + (value.mp || 0) < agent.maxMp) {
1733
+ agent.mp += value.mp || 0;
1472
1734
  } else {
1473
- if (skillFn[atkType]) {
1474
- if (["治疗技" /* 治疗技 */, "增益技" /* 增益技 */].includes(skillFn[atkType].type)) {
1475
- selectGoal = lifeSelfList.find((item) => item.name == select) || agent;
1476
- }
1477
- const selectFn = skillFn[atkType];
1478
- if (selectFn.mp == 0 || agent.mp - selectFn.mp >= 0) {
1479
- agent.mp -= selectFn.mp;
1480
- let isNext = false;
1481
- const fnMsg = selectFn.fn(
1482
- { self: agent, goal: selectGoal },
1483
- { selfList: lifeSelfList, goalList: lifeGoalList },
1484
- (val) => {
1485
- switch (val.type) {
1486
- case "伤害技" /* 伤害技 */:
1487
- val.target.map((goal) => {
1488
- giveDamage(agent, goal, val.damage);
1489
- });
1490
- break;
1491
- case "治疗技" /* 治疗技 */:
1492
- val.target.map((goal) => {
1493
- giveCure(goal, val.value);
1494
- });
1495
- break;
1496
- case "释放失败" /* 释放失败 */:
1497
- val.err && session.send(val.err);
1498
- default:
1499
- break;
1500
- }
1501
- isNext = val.isNext;
1502
- }
1503
- );
1504
- fnMsg && msgList.push(fnMsg);
1505
- isNext && noralAtk();
1506
- } else {
1507
- await session.send(`MP不足,释放失败!`);
1508
- noralAtk();
1509
- }
1510
- } else {
1511
- await session.send(`未持有该技能或者该技能不存在,释放失败!`);
1512
- noralAtk();
1513
- }
1735
+ agent.mp = agent.maxMp;
1514
1736
  }
1737
+ fn && await fn({
1738
+ currentHP: agent.hp,
1739
+ currentMP: agent.mp
1740
+ });
1741
+ return;
1515
1742
  }
1516
- await session.send(msgList.length ? `战斗记录:
1517
- ` + msgList.join("\n") : "");
1518
- await session.send(BattleData.battleSituationTextFormat(currentBattle));
1519
- const result = BattleData.playOver(currentBattle);
1520
- if (result.over) {
1521
- await session.send(result.type);
1522
- await BattleData.settlement(currentBattle, result, session);
1523
- BattleData.clearBattleData(session);
1743
+ const { maxHp, maxMp } = User.getUserAttributeByUserId(userId);
1744
+ if (value.hp && !value.mp && userInfo.hp == maxHp) {
1745
+ fn && await fn({
1746
+ currentHP: userInfo.hp,
1747
+ currentMP: userInfo.mp,
1748
+ err: "当前血量已满,无需回复。"
1749
+ });
1750
+ return;
1751
+ }
1752
+ if (value.mp && !value.hp && userInfo.mp == maxMp) {
1753
+ fn && await fn({
1754
+ currentHP: userInfo.hp,
1755
+ currentMP: userInfo.mp,
1756
+ err: "当前蓝量已满,无需回复。"
1757
+ });
1758
+ return;
1524
1759
  }
1760
+ if (value.mp && value.hp && userInfo.mp == maxMp && userInfo.hp == maxHp) {
1761
+ fn && await fn({
1762
+ currentHP: userInfo.hp,
1763
+ currentMP: userInfo.mp,
1764
+ err: "当前状态全满,无需回复。"
1765
+ });
1766
+ return;
1767
+ }
1768
+ if (userInfo.hp + (value.hp || 0) < maxHp) {
1769
+ userInfo.hp += value.hp || 0;
1770
+ } else {
1771
+ userInfo.hp = maxHp;
1772
+ }
1773
+ if (userInfo.mp + (value.mp || 0) < maxHp) {
1774
+ userInfo.mp += value.mp || 0;
1775
+ } else {
1776
+ userInfo.mp = maxMp;
1777
+ }
1778
+ fn && await fn({
1779
+ currentHP: userInfo.hp,
1780
+ currentMP: userInfo.mp
1781
+ });
1782
+ await User.setDatabaseUserAttribute(userId);
1525
1783
  },
1526
- /** 结算奖励 */
1527
- async settlement(tempData, overInfo, session) {
1528
- const allList = [...tempData.self, ...tempData.goal].filter((item) => item.type == "玩家");
1529
- const selfList = tempData.self.filter((item) => item.type == "玩家");
1530
- const goalList = tempData.goal.filter((item) => item.type == "玩家");
1531
- const msg = /* @__PURE__ */ __name(async (val) => {
1532
- const msgTemp = `${val.name}[升级]${val.lv}级!
1533
- ` + (val.atk ? `攻击力↑ ${val.atk}
1534
- ` : "") + (val.def ? `防御力↑ ${val.def}
1535
- ` : "") + (val.maxHp ? `最大血量↑ ${val.maxHp}
1536
- ` : "") + (val.maxMp ? `最大蓝量↑ ${val.maxMp}` : "");
1537
- await session.send(msgTemp);
1538
- }, "msg");
1539
- const aynchronize = /* @__PURE__ */ __name((agent) => {
1540
- User.userTempData[agent.userId].hp = agent.hp;
1541
- User.userTempData[agent.userId].mp = agent.mp;
1542
- }, "aynchronize");
1543
- if (tempData.isPK) {
1544
- if (overInfo.win == "self") {
1545
- await session.send("攻击方获得20EXP、5货币");
1546
- for (const agent of allList) {
1547
- aynchronize(agent);
1548
- if (agent.for == "self") {
1549
- if (agent.hp <= 0) {
1550
- User.userTempData[agent.userId].hp = 0;
1551
- User.userTempData[agent.userId].isDie = true;
1552
- }
1553
- await User.giveExp(agent.userId, 20, async (val) => await msg(val));
1554
- await User.giveMonetary(agent.userId, 5);
1555
- }
1556
- }
1557
- } else if (overInfo.win == "goal") {
1558
- await session.send("防御方获得20EXP、5货币");
1559
- for (const agent of allList) {
1560
- aynchronize(agent);
1561
- if (agent.for == "goal") {
1562
- if (agent.hp <= 0) {
1563
- User.userTempData[agent.userId].hp = 0;
1564
- User.userTempData[agent.userId].isDie = true;
1565
- }
1566
- await User.giveExp(agent.userId, 20, async (val) => await msg(val));
1567
- await User.giveMonetary(agent.userId, 5);
1568
- }
1569
- }
1570
- }
1784
+ /** 给予玩家PP值 */
1785
+ async givePP(userId, value, fn) {
1786
+ const userInfo = User.userTempData[userId];
1787
+ if (!userInfo) return;
1788
+ const { maxPp } = User.getUserAttributeByUserId(userId);
1789
+ if (userInfo.pp + value < maxPp) {
1790
+ userInfo.pp += value;
1571
1791
  } else {
1572
- let val = 0;
1573
- let monetary = 0;
1574
- const monsterName = tempData.goal.filter((item) => item.type == "怪物").map((i) => ({ name: i.name, lv: i.lv }));
1575
- monsterName.forEach((item) => {
1576
- const monster = Monster.monsterTempData[item.name];
1577
- if (monster) {
1578
- val += Math.floor(monster.giveExp + monster.giveExp * (item.lv - 1) * 0.2);
1579
- monetary += Math.floor(monster.giveMonetary + monster.giveExp * (item.lv - 1) * 0.1);
1580
- }
1792
+ userInfo.pp = maxPp;
1793
+ }
1794
+ fn && await fn({
1795
+ currentPP: userInfo.pp
1796
+ });
1797
+ await User.setDatabaseUserAttribute(userId);
1798
+ },
1799
+ async lostPP(userId, value, fn) {
1800
+ const userInfo = User.userTempData[userId];
1801
+ if (!userInfo) return;
1802
+ if (userInfo.pp - value < 0) {
1803
+ fn && await fn({
1804
+ currentPP: userInfo.pp,
1805
+ err: "PP值不够,消耗失败!"
1581
1806
  });
1582
- await session.send(`小队获得${val}EXP、${monetary}货币!`);
1583
- for (const agent of selfList) {
1584
- aynchronize(agent);
1585
- if (overInfo.win == "self") {
1586
- await User.giveExp(agent.userId, val, async (val2) => await msg(val2));
1587
- await User.giveMonetary(agent.userId, monetary);
1588
- }
1807
+ return;
1808
+ }
1809
+ userInfo.pp -= value;
1810
+ fn && await fn({
1811
+ currentPP: userInfo.pp
1812
+ });
1813
+ await User.setDatabaseUserAttribute(userId);
1814
+ },
1815
+ /** 给予玩家货币 */
1816
+ async giveMonetary(userId, val, fn) {
1817
+ const [bindData] = await User.ctx.database.get("binding", { pid: userId });
1818
+ if (bindData && val) {
1819
+ const [currentM] = await User.ctx.database.get("monetary", { uid: bindData.aid });
1820
+ await User.ctx.monetary.gain(bindData.aid, val);
1821
+ fn && await fn({ val, currentVal: currentM.value += val });
1822
+ }
1823
+ },
1824
+ /** 收取玩家货币 */
1825
+ async lostMonetary(userId, val, fn) {
1826
+ const [bindData] = await User.ctx.database.get("binding", { pid: userId });
1827
+ if (bindData && val) {
1828
+ const [currentM] = await User.ctx.database.get("monetary", { uid: bindData.aid });
1829
+ if (currentM.value - val < 0) {
1830
+ fn && await fn({
1831
+ val: Math.abs(val),
1832
+ currentVal: currentM.value,
1833
+ err: "余额不足!"
1834
+ });
1835
+ return;
1589
1836
  }
1837
+ await User.ctx.monetary.cost(bindData.aid, val);
1838
+ fn && await fn({
1839
+ val: Math.abs(val),
1840
+ currentVal: currentM.value - val
1841
+ });
1842
+ }
1843
+ },
1844
+ /** 给予玩家指定道具 */
1845
+ async giveProps(userId, props, fn) {
1846
+ const userProps = Props.userPorpsTemp[userId];
1847
+ if (!userProps) return;
1848
+ const upProps = [];
1849
+ for (const item of props) {
1850
+ const propsItem = propsData[item.name];
1851
+ if (!propsItem) continue;
1852
+ userProps[item.name] = {
1853
+ name: propsItem.name,
1854
+ type: propsItem.type,
1855
+ value: 0
1856
+ };
1857
+ userProps[item.name].value += item.val || 1;
1858
+ upProps.push({ name: item.name, val: userProps[item.name].value });
1859
+ }
1860
+ fn && await fn({
1861
+ currentProps: upProps
1862
+ });
1863
+ await Props.setDatabasePropsData(userId);
1864
+ },
1865
+ /** 去除玩家指定道具 */
1866
+ async loseProps(userId, props, fn) {
1867
+ const userProps = Props.userPorpsTemp[userId];
1868
+ const propsItem = propsData[props.name];
1869
+ if (!userProps) return;
1870
+ if (!propsItem) {
1871
+ fn && await fn({
1872
+ currentProps: { name: props.name, val: 0 },
1873
+ err: "该道具信息不存在!"
1874
+ });
1875
+ return;
1876
+ }
1877
+ if (!userProps[props.name]) {
1878
+ userProps[props.name] = {
1879
+ name: propsItem.name,
1880
+ type: propsItem.type,
1881
+ value: 0
1882
+ };
1883
+ }
1884
+ if (userProps[props.name].value - (props.val || 1) < 0) {
1885
+ fn && await fn({
1886
+ currentProps: { name: props.name, val: userProps[props.name].value },
1887
+ err: `道具数量不足!剩余${userProps[props.name].value}个。`
1888
+ });
1889
+ return;
1590
1890
  }
1891
+ userProps[props.name].value -= props.val || 1;
1892
+ if (userProps[props.name].value == 0) delete userProps[props.name];
1893
+ fn && await fn({
1894
+ currentProps: { name: props.name, val: userProps[props.name]?.value || 0 }
1895
+ });
1896
+ await Props.setDatabasePropsData(userId);
1897
+ },
1898
+ /** 目标是否死亡 */
1899
+ isDie(userId) {
1900
+ return User.userTempData[userId]?.isDie;
1591
1901
  }
1592
1902
  };
1593
- function getLineupName(agent) {
1594
- return `[${agent.type}]${agent.name}`;
1595
- }
1596
- __name(getLineupName, "getLineupName");
1597
- function initBattleAttribute(data) {
1598
- if ("playName" in data) {
1599
- const userData = data;
1600
- const temp = {
1601
- userId: userData.userId,
1602
- name: userData.playName,
1603
- lv: userData.lv,
1604
- type: "玩家",
1605
- hp: userData.hp,
1606
- maxHp: userData.maxHp,
1607
- mp: userData.mp,
1608
- maxMp: userData.maxMp,
1609
- atk: userData.atk,
1610
- def: userData.def,
1611
- chr: userData.chr,
1612
- ghd: userData.ghd,
1613
- csr: userData.csr,
1614
- evasion: userData.evasion,
1615
- hit: userData.hit,
1616
- speed: userData.speed,
1617
- gain: {
1618
- maxHp: 0,
1619
- maxMp: 0,
1620
- atk: 0,
1621
- def: 0,
1622
- chr: 0,
1623
- ghd: 0,
1624
- evasion: 0,
1625
- hit: 0,
1626
- speed: 0
1627
- },
1628
- buff: [],
1629
- fn: []
1630
- };
1631
- return temp;
1632
- } else {
1633
- const monsterData2 = data;
1634
- const temp = {
1635
- name: monsterData2.name,
1636
- type: "怪物",
1637
- lv: monsterData2.lv,
1638
- hp: monsterData2.hp,
1639
- maxHp: monsterData2.maxHp,
1640
- mp: monsterData2.mp,
1641
- maxMp: monsterData2.maxMp,
1642
- atk: monsterData2.atk,
1643
- def: monsterData2.def,
1644
- chr: monsterData2.chr,
1645
- ghd: monsterData2.ghd,
1646
- csr: monsterData2.csr,
1647
- evasion: monsterData2.evasion,
1648
- hit: monsterData2.hit,
1649
- speed: monsterData2.speed,
1650
- gain: {
1651
- maxHp: 0,
1652
- maxMp: 0,
1653
- atk: 0,
1654
- def: 0,
1655
- chr: 0,
1656
- ghd: 0,
1657
- evasion: 0,
1658
- hit: 0,
1659
- speed: 0
1660
- },
1661
- buff: [],
1662
- fn: []
1663
- };
1664
- return temp;
1665
- }
1666
- }
1667
- __name(initBattleAttribute, "initBattleAttribute");
1668
1903
 
1669
1904
  // src/index.ts
1670
1905
  var name = "smmcat-gensokyo";
@@ -1786,10 +2021,22 @@ function apply(ctx, config) {
1786
2021
  await session.send(GensokyoMap.userAreaTextFormat(userData.playName, query));
1787
2022
  });
1788
2023
  ctx.command("幻想乡/个人属性").action(async ({ session }) => {
2024
+ const userData = await User.getUserAttribute(session);
2025
+ if (!userData) return;
2026
+ GensokyoMap.initUserPoistion(session, userData);
1789
2027
  return `您的属性如下:
1790
2028
  ` + User.userAttributeTextFormat(session.userId);
1791
2029
  });
2030
+ ctx.command("幻想乡/个人道具").action(async ({ session }) => {
2031
+ const userData = await User.getUserAttribute(session);
2032
+ if (!userData) return;
2033
+ GensokyoMap.initUserPoistion(session, userData);
2034
+ return await Props.getPropsDataByUserId(session.userId);
2035
+ });
1792
2036
  ctx.command("幻想乡/个人信息").userFields(["id"]).action(async ({ session }) => {
2037
+ const userData = await User.getUserAttribute(session);
2038
+ if (!userData) return;
2039
+ GensokyoMap.initUserPoistion(session, userData);
1793
2040
  const [data] = await ctx.database.get("monetary", { uid: session.user.id });
1794
2041
  return `[${User.userTempData[session.userId].playName}]:您当前货币为:${data?.value || 0}个`;
1795
2042
  });
@@ -1861,6 +2108,15 @@ function apply(ctx, config) {
1861
2108
  await BattleData.createBattleByUser(session, [{ userId: exist.userId }]);
1862
2109
  }
1863
2110
  });
2111
+ ctx.command("幻想乡/道具使用 <props>").action(async ({ session }, props) => {
2112
+ const userData = await User.getUserAttribute(session);
2113
+ if (!userData) return;
2114
+ GensokyoMap.initUserPoistion(session, userData);
2115
+ if (!props) {
2116
+ return `未选择道具使用,请选择道具,例如:/道具使用 红药`;
2117
+ }
2118
+ await Props.userProps(session, props);
2119
+ });
1864
2120
  ctx.command("幻想乡/技能查询 <goal>").action(async ({ session }, goal) => {
1865
2121
  if (!goal) return `请输入技能名,例如 /技能查询 重砍`;
1866
2122
  if (!skillFn[goal]) return `没有存在 ${goal} 技能!`;