koishi-plugin-smmcat-gensokyo 0.0.14 → 0.0.16

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,1373 @@ 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 > 0 ? agent.hp : 0;
1284
+ User.userTempData[agent.userId].mp = agent.mp;
1285
+ if (User.userTempData[agent.userId].hp <= 0) {
1286
+ User.userTempData[agent.userId].isDie = true;
1287
+ }
1288
+ }, "aynchronize");
1289
+ if (tempData.isPK) {
1290
+ if (overInfo.win == "self") {
1291
+ await session.send("攻击方获得20EXP、5货币");
1292
+ for (const agent of allList) {
1293
+ aynchronize(agent);
1294
+ if (agent.for == "self") {
1295
+ await User.giveExp(agent.userId, 20, async (val) => await msg(val));
1296
+ await User.giveMonetary(agent.userId, 5);
1297
+ }
1298
+ }
1299
+ } else if (overInfo.win == "goal") {
1300
+ await session.send("防御方获得20EXP、5货币");
1301
+ for (const agent of allList) {
1302
+ aynchronize(agent);
1303
+ if (agent.for == "goal") {
1304
+ await User.giveExp(agent.userId, 20, async (val) => await msg(val));
1305
+ await User.giveMonetary(agent.userId, 5);
1306
+ }
1307
+ }
1308
+ }
1079
1309
  } else {
1080
- this.config.isBadDef = true;
1081
- this.config.harm = 1;
1310
+ let val = 0;
1311
+ let monetary = 0;
1312
+ let props = [];
1313
+ const monsterName = tempData.goal.filter((item) => item.type == "怪物").map((i) => ({ name: i.name, lv: i.lv }));
1314
+ monsterName.forEach((item) => {
1315
+ const monster = Monster.monsterTempData[item.name];
1316
+ if (monster) {
1317
+ val += Math.floor(monster.giveExp + monster.giveExp * (item.lv - 1) * 0.2);
1318
+ monetary += Math.floor(monster.giveMonetary + monster.giveExp * (item.lv - 1) * 0.1);
1319
+ monster.giveProps?.forEach((propsItem) => {
1320
+ if (item.lv >= (propsItem.lv || 1) && random(0, 100) < propsItem.radomVal) {
1321
+ props.push({
1322
+ name: propsItem.name,
1323
+ val: propsItem.const ? propsItem.val : random(1, propsItem.val)
1324
+ });
1325
+ }
1326
+ });
1327
+ }
1328
+ });
1329
+ for (const agent of selfList) {
1330
+ aynchronize(agent);
1331
+ if (overInfo.win == "self") {
1332
+ await session.send(`小队获得${val}EXP、${monetary}货币!`);
1333
+ await User.giveExp(agent.userId, val, async (val2) => await msg(val2));
1334
+ await User.giveMonetary(agent.userId, monetary);
1335
+ props.length && await User.giveProps(agent.userId, props, async (val2) => {
1336
+ const propsDict = {};
1337
+ val2.currentProps.forEach((item) => {
1338
+ if (!propsDict[item.name]) propsDict[item.name] = 1;
1339
+ propsDict[item.name]++;
1340
+ });
1341
+ const msg2 = Object.keys(propsDict).map((item) => {
1342
+ return `${item} ${propsDict[item]}个`;
1343
+ }).join("\n");
1344
+ await session.send(`${agent.name}在战斗中获得:` + msg2);
1345
+ });
1346
+ }
1347
+ }
1082
1348
  }
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
1349
  }
1099
1350
  };
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
- }
1351
+ function getLineupName(agent) {
1352
+ return `[${agent.type}]${agent.name}`;
1109
1353
  }
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;
1354
+ __name(getLineupName, "getLineupName");
1355
+ function initBattleAttribute(data) {
1356
+ if ("playName" in data) {
1357
+ const userData = data;
1358
+ const temp = {
1359
+ userId: userData.userId,
1360
+ name: userData.playName,
1361
+ lv: userData.lv,
1362
+ type: "玩家",
1363
+ hp: userData.hp,
1364
+ maxHp: userData.maxHp,
1365
+ mp: userData.mp,
1366
+ maxMp: userData.maxMp,
1367
+ atk: userData.atk,
1368
+ def: userData.def,
1369
+ chr: userData.chr,
1370
+ ghd: userData.ghd,
1371
+ csr: userData.csr,
1372
+ evasion: userData.evasion,
1373
+ hit: userData.hit,
1374
+ speed: userData.speed,
1375
+ gain: {
1376
+ maxHp: 0,
1377
+ maxMp: 0,
1378
+ atk: 0,
1379
+ def: 0,
1380
+ chr: 0,
1381
+ ghd: 0,
1382
+ evasion: 0,
1383
+ hit: 0,
1384
+ speed: 0
1385
+ },
1386
+ buff: [],
1387
+ fn: []
1388
+ };
1389
+ return temp;
1116
1390
  } else {
1117
- const abHp = goal.maxHp + goal.gain.maxHp - goal.hp;
1118
- goal.hp += abHp;
1119
- return abHp;
1391
+ const monsterData2 = data;
1392
+ const temp = {
1393
+ name: monsterData2.name,
1394
+ type: "怪物",
1395
+ lv: monsterData2.lv,
1396
+ hp: monsterData2.hp,
1397
+ maxHp: monsterData2.maxHp,
1398
+ mp: monsterData2.mp,
1399
+ maxMp: monsterData2.maxMp,
1400
+ atk: monsterData2.atk,
1401
+ def: monsterData2.def,
1402
+ chr: monsterData2.chr,
1403
+ ghd: monsterData2.ghd,
1404
+ csr: monsterData2.csr,
1405
+ evasion: monsterData2.evasion,
1406
+ hit: monsterData2.hit,
1407
+ speed: monsterData2.speed,
1408
+ gain: {
1409
+ maxHp: 0,
1410
+ maxMp: 0,
1411
+ atk: 0,
1412
+ def: 0,
1413
+ chr: 0,
1414
+ ghd: 0,
1415
+ evasion: 0,
1416
+ hit: 0,
1417
+ speed: 0
1418
+ },
1419
+ buff: [],
1420
+ fn: []
1421
+ };
1422
+ return temp;
1120
1423
  }
1121
1424
  }
1122
- __name(giveCure, "giveCure");
1123
- function moreDamageInfo(damage) {
1124
- return (damage.isCsp ? `(暴击!)` : "") + (damage.isEvasion ? `(闪避成功!)` : "") + (damage.isBadDef ? `(未破防!)` : "");
1125
- }
1126
- __name(moreDamageInfo, "moreDamageInfo");
1425
+ __name(initBattleAttribute, "initBattleAttribute");
1127
1426
 
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")
1427
+ // src/users.ts
1428
+ var UserOccDict = {
1429
+ ["剑士" /* 剑士 */]: {
1430
+ info: "擅长近战攻击,拥有强大的属性能力",
1431
+ initStatus: {
1432
+ userId: "",
1433
+ playName: "",
1434
+ type: "剑士" /* 剑士 */,
1435
+ exp: 0,
1436
+ maxExp: 100,
1437
+ lv: 1,
1438
+ hp: 120,
1439
+ maxHp: 120,
1440
+ mp: 80,
1441
+ maxMp: 80,
1442
+ pp: 100,
1443
+ maxPp: 100,
1444
+ atk: 12,
1445
+ def: 5,
1446
+ chr: 50,
1447
+ csr: 0,
1448
+ ghd: 1.2,
1449
+ speed: 5,
1450
+ evasion: 100,
1451
+ hit: 100
1452
+ }
1228
1453
  },
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")
1454
+ ["法师" /* 法师 */]: {
1455
+ info: "精通元素魔法,能够打出爆发伤害",
1456
+ initStatus: {
1457
+ userId: "",
1458
+ playName: "",
1459
+ type: "法师" /* 法师 */,
1460
+ exp: 0,
1461
+ maxExp: 100,
1462
+ lv: 1,
1463
+ hp: 100,
1464
+ maxHp: 100,
1465
+ mp: 100,
1466
+ maxMp: 100,
1467
+ pp: 100,
1468
+ maxPp: 100,
1469
+ atk: 10,
1470
+ def: 2,
1471
+ chr: 50,
1472
+ csr: 0,
1473
+ ghd: 1.2,
1474
+ speed: 5,
1475
+ evasion: 100,
1476
+ hit: 100
1477
+ }
1478
+ },
1479
+ ["刺客" /* 刺客 */]: {
1480
+ info: "迅捷攻击,高闪避值的高敏玩家",
1481
+ initStatus: {
1482
+ userId: "",
1483
+ playName: "",
1484
+ type: "刺客" /* 刺客 */,
1485
+ exp: 0,
1486
+ maxExp: 100,
1487
+ lv: 1,
1488
+ hp: 90,
1489
+ maxHp: 90,
1490
+ mp: 70,
1491
+ maxMp: 70,
1492
+ pp: 100,
1493
+ maxPp: 100,
1494
+ atk: 8,
1495
+ def: 2,
1496
+ chr: 80,
1497
+ csr: 0,
1498
+ ghd: 1.3,
1499
+ speed: 6,
1500
+ evasion: 120,
1501
+ hit: 100
1502
+ }
1245
1503
  }
1246
1504
  };
1247
-
1248
- // src/battle.ts
1249
- var BattleData = {
1505
+ var User = {
1250
1506
  config: {},
1251
1507
  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];
1273
- },
1274
- // 返回队伍信息
1275
- teamListByUser(userId) {
1276
- const teamList = [];
1277
- if (!BattleData.teamTemp[userId]) {
1278
- return [];
1279
- }
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));
1508
+ userTempData: {},
1509
+ async init(config, ctx) {
1510
+ User.config = config;
1511
+ User.ctx = ctx;
1512
+ ctx.model.extend(
1513
+ "smm_gensokyo_user_attribute",
1514
+ {
1515
+ userId: "string",
1516
+ playName: "string",
1517
+ type: "string",
1518
+ exp: "integer",
1519
+ lv: "integer",
1520
+ hp: "integer",
1521
+ mp: "integer",
1522
+ pp: "integer",
1523
+ isDie: "boolean"
1524
+ },
1525
+ {
1526
+ primary: "userId",
1527
+ autoInc: false
1284
1528
  }
1529
+ );
1530
+ const userData = await ctx.database.get("smm_gensokyo_user_attribute", {});
1531
+ const temp = {};
1532
+ userData.forEach((item) => {
1533
+ temp[item.userId] = item;
1285
1534
  });
1286
- return teamList;
1535
+ User.userTempData = temp;
1287
1536
  },
1288
- /** 创建战斗-与怪物 */
1289
- async createBattleByMonster(session, goal) {
1290
- if (BattleData.isBattle(session)) {
1291
- await session.send("当前正在战斗,还不能逃脱!");
1292
- return;
1293
- }
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("你不是队伍的队长,无法主动操作战斗!");
1299
- 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)));
1537
+ /** 获取角色基础属性 */
1538
+ async getUserAttribute(session) {
1539
+ if (!User.userTempData[session.userId]) {
1540
+ await session.send("未创建账户,请发送 /开始注册 完成账号的注册!");
1541
+ return null;
1310
1542
  }
1311
- goal.forEach((item) => {
1312
- battle_monsterList.push(initBattleAttribute(Monster.getMonsterAttributeData(item.name, item.lv)));
1313
- });
1314
- const temp = {
1315
- self: battle_user.map((i) => ({ ...i, for: "self" })),
1316
- goal: battle_monsterList.map((i) => ({ ...i, for: "goal" }))
1317
- };
1318
- playUser.forEach((userId) => {
1319
- BattleData.lastPlay[userId] = temp;
1320
- });
1321
- await session.send(`开始与 ${goal.map((i) => i.name).join("、")} 进行战斗`);
1543
+ return User.getUserAddLvAttribute(session.userId);
1322
1544
  },
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;
1545
+ /** 获取角色实际等级属性数据 */
1546
+ getUserAddLvAttribute(userId) {
1547
+ const UserDict = User.userTempData[userId];
1548
+ if (!UserDict) return null;
1549
+ const UserData = {
1550
+ ...UserOccDict[UserDict.type].initStatus,
1551
+ lv: UserDict.lv,
1552
+ hp: UserDict.hp,
1553
+ mp: UserDict.mp,
1554
+ exp: UserDict.exp,
1555
+ pp: UserDict.pp,
1556
+ playName: UserDict.playName,
1557
+ userId: UserDict.userId
1558
+ };
1559
+ const lv = UserData.lv;
1560
+ const temp = {};
1561
+ const lvScope = Object.keys(userBenchmark).reverse().find((item) => Number(item) < lv) || 10;
1562
+ const useBenchmark = userBenchmark[lvScope];
1563
+ Object.keys(UserData).forEach((i) => {
1564
+ temp[i] = UserData[i];
1565
+ if (useBenchmark[i]) {
1566
+ if (i == "maxExp") {
1567
+ temp[i] = Math.floor(100 * useBenchmark[i] * (lv - 1)) || 100;
1568
+ } else {
1569
+ temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
1570
+ }
1339
1571
  }
1340
- return true;
1341
1572
  });
1342
- if (lostMsg.length) {
1343
- await session.send(lostMsg.join("\n"));
1344
- }
1345
- if (!goal.length) {
1346
- lostMsg.push(`PK失败,无任何目标进行PK`);
1573
+ return temp;
1574
+ },
1575
+ /** 通过 userId 获取角色属性 */
1576
+ getUserAttributeByUserId(userId) {
1577
+ return User.getUserAddLvAttribute(userId) || null;
1578
+ },
1579
+ /** 创建游戏账号 */
1580
+ async createPlayUser(session) {
1581
+ const [data] = await User.ctx.database.get("smm_gensokyo_user_attribute", { userId: session.userId });
1582
+ if (data) {
1583
+ await session.send("已存在账号,请勿重复创建!");
1347
1584
  return;
1348
1585
  }
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)));
1586
+ await session.send("请输入自己的游戏昵称:(60s)");
1587
+ const playname = await session.prompt(6e4);
1588
+ if (playname == void 0) return;
1589
+ const [repeat] = await User.ctx.database.get("smm_gensokyo_user_attribute", { playName: playname.trim() });
1590
+ if (repeat) {
1591
+ await session.send("名字重复,请更换一个名字。");
1592
+ return;
1362
1593
  }
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
1594
+ if (playname.trim().length > 6 || playname.trim().length < 1) {
1595
+ await session.send("名字长度有问题,要求小于 6个字,大于 1个字");
1596
+ return;
1597
+ }
1598
+ await session.send(`请输入要专职的职业:(60s)
1599
+ ${Object.keys(UserOccDict).map((i) => `【${i}】:${UserOccDict[i].info}`).join("\n")}`);
1600
+ let jobType = await session.prompt(6e4);
1601
+ if (jobType == void 0) return;
1602
+ while (!Object.keys(UserOccDict).includes(jobType)) {
1603
+ await session.send("未找到该职业,请重新选择!");
1604
+ jobType = await session.prompt(6e4);
1605
+ }
1606
+ const temp = {
1607
+ userId: session.userId,
1608
+ playName: playname.trim(),
1609
+ type: jobType,
1610
+ hp: UserOccDict[jobType].initStatus.hp,
1611
+ pp: UserOccDict[jobType].initStatus.pp,
1612
+ mp: UserOccDict[jobType].initStatus.mp,
1613
+ lv: 1,
1614
+ exp: 0,
1615
+ isDie: false
1371
1616
  };
1372
- playUser.forEach((userId) => {
1373
- BattleData.lastPlay[userId] = pkTemp;
1374
- });
1375
- await session.send(`开始与玩家 ${battle_goal.map((i) => i.name).join("、")} 进行PK战斗`);
1617
+ User.ctx.database.create("smm_gensokyo_user_attribute", temp);
1618
+ User.userTempData[session.userId] = temp;
1619
+ await Props.initUserPropsData(session.userId);
1620
+ await session.send("创建成功!\n" + User.userAttributeTextFormat(session.userId));
1376
1621
  },
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");
1622
+ /** 信息格式化 */
1623
+ userAttributeTextFormat(userId) {
1624
+ if (!User.userTempData[userId]) {
1625
+ return "没有找到您的角色信息";
1403
1626
  }
1404
- return `[当前战况]
1405
- 我方阵容:
1406
- ` + selfTemp.join("\n") + "\n\n敌方阵容:\n" + goalTemp.join("\n");
1627
+ const temp = User.getUserAttributeByUserId(userId);
1628
+ return `昵称:${temp.playName}
1629
+ 职位:${temp.type}
1630
+ 等级:${temp.lv} (${temp.exp}/${temp.maxExp})
1631
+ -----------------
1632
+ 【生命值】${temp.hp}/${temp.maxHp}
1633
+ 【魔法值】${temp.mp}/${temp.maxMp}
1634
+ 【活力值】${temp.pp}/${temp.maxPp}
1635
+ -----------------
1636
+ 【攻击力】${temp.atk} (+0)
1637
+ 【防御力】${temp.def} (+0)
1638
+ 【速度值】${temp.speed} (+0)
1639
+ 【闪避值】${temp.evasion} (+0)
1640
+ 【命中率】${(temp.hit / 10 + 100).toFixed(1)}% (+0%)
1641
+ 【暴击率】${(temp.chr / 10).toFixed(1)}% (+0%)
1642
+ 【暴击伤害】${(temp.ghd * 100).toFixed(1)}% (+0%)` + (temp.csr > 0 ? `
1643
+ 【暴击抵抗】${temp.csr}` : "");
1407
1644
  },
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" };
1645
+ /** 写入用户数据到数据库 */
1646
+ async setDatabaseUserAttribute(userId) {
1647
+ const userInfo = User.userTempData[userId];
1648
+ if (!userInfo) return;
1649
+ const temp = {
1650
+ playName: userInfo.playName.trim(),
1651
+ hp: userInfo.hp,
1652
+ pp: userInfo.pp,
1653
+ mp: userInfo.mp,
1654
+ lv: userInfo.lv,
1655
+ exp: userInfo.exp
1656
+ };
1657
+ User.ctx.database.set("smm_gensokyo_user_attribute", { userId }, temp);
1658
+ },
1659
+ /** 给予玩家经验 */
1660
+ async giveExp(userId, value, fn) {
1661
+ const userInfo = User.userTempData[userId];
1662
+ if (!userInfo) return;
1663
+ const beforData = { ...User.getUserAttributeByUserId(userId) };
1664
+ let isUp = false;
1665
+ userInfo.exp += value;
1666
+ while (true) {
1667
+ const { maxExp } = User.getUserAttributeByUserId(userId);
1668
+ if (userInfo.exp < maxExp) break;
1669
+ userInfo.lv += 1;
1670
+ userInfo.exp -= maxExp;
1671
+ isUp = true;
1418
1672
  }
1419
- return { over: false, type: "未结束", win: "" };
1673
+ if (isUp) {
1674
+ const afterData = User.getUserAttributeByUserId(userId);
1675
+ const upTemp = {
1676
+ name: afterData.playName,
1677
+ lv: afterData.lv,
1678
+ maxHp: afterData.maxHp - beforData.maxHp,
1679
+ maxMp: afterData.maxMp = beforData.maxMp,
1680
+ atk: afterData.atk - beforData.atk,
1681
+ def: afterData.def - beforData.def
1682
+ };
1683
+ fn && await fn(upTemp);
1684
+ }
1685
+ await User.setDatabaseUserAttribute(userId);
1420
1686
  },
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
- });
1687
+ /** 给予玩家死亡 */
1688
+ async giveDie(userId) {
1689
+ const userInfo = User.userTempData[userId];
1690
+ userInfo.hp = 0;
1691
+ userInfo.isDie = true;
1692
+ await User.setDatabaseUserAttribute(userId);
1430
1693
  },
1431
- async play(session, atkType, select) {
1432
- if (!BattleData.isBattle(session)) {
1433
- await session.send("您并没有任何参与战斗。");
1434
- return;
1694
+ /** 给予玩家复活 */
1695
+ async giveLife(userId, val) {
1696
+ const userInfo = User.userTempData[userId];
1697
+ if (!val) {
1698
+ const { maxHp } = User.getUserAttributeByUserId(userId);
1699
+ userInfo.hp = maxHp;
1700
+ } else {
1701
+ userInfo.hp = val;
1435
1702
  }
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)];
1460
- } else {
1461
- selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
1462
- }
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();
1472
- } 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
- }
1703
+ await User.setDatabaseUserAttribute(userId);
1704
+ },
1705
+ /** 给予玩家血量或者蓝量 */
1706
+ async giveHPMP(userId, value, fn) {
1707
+ const userInfo = User.userTempData[userId];
1708
+ if (!userInfo) return;
1709
+ if (userInfo.isDie) {
1710
+ fn && await fn({
1711
+ currentHP: 0,
1712
+ currentMP: 0,
1713
+ err: "角色已死亡,无法使用恢复道具。"
1714
+ });
1715
+ return;
1716
+ }
1717
+ if (BattleData.isBattleByUserId(userId)) {
1718
+ const { goal, self } = BattleData.lastPlay[userId];
1719
+ const agentAll = [...goal, ...self];
1720
+ const agent = agentAll.find((item) => item?.userId == userId);
1721
+ if (!agent) return;
1722
+ if (agent.hp + (value.hp || 0) < agent.maxHp) {
1723
+ agent.hp += value.hp || 0;
1724
+ } else {
1725
+ agent.hp = agent.maxHp;
1726
+ }
1727
+ if (agent.mp + (value.mp || 0) < agent.maxMp) {
1728
+ agent.mp += value.mp || 0;
1729
+ } else {
1730
+ agent.mp = agent.maxMp;
1514
1731
  }
1732
+ fn && await fn({
1733
+ currentHP: agent.hp,
1734
+ currentMP: agent.mp
1735
+ });
1736
+ return;
1515
1737
  }
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);
1738
+ const { maxHp, maxMp } = User.getUserAttributeByUserId(userId);
1739
+ if (value.hp && !value.mp && userInfo.hp == maxHp) {
1740
+ fn && await fn({
1741
+ currentHP: userInfo.hp,
1742
+ currentMP: userInfo.mp,
1743
+ err: "当前血量已满,无需回复。"
1744
+ });
1745
+ return;
1746
+ }
1747
+ if (value.mp && !value.hp && userInfo.mp == maxMp) {
1748
+ fn && await fn({
1749
+ currentHP: userInfo.hp,
1750
+ currentMP: userInfo.mp,
1751
+ err: "当前蓝量已满,无需回复。"
1752
+ });
1753
+ return;
1754
+ }
1755
+ if (value.mp && value.hp && userInfo.mp == maxMp && userInfo.hp == maxHp) {
1756
+ fn && await fn({
1757
+ currentHP: userInfo.hp,
1758
+ currentMP: userInfo.mp,
1759
+ err: "当前状态全满,无需回复。"
1760
+ });
1761
+ return;
1762
+ }
1763
+ if (userInfo.hp + (value.hp || 0) < maxHp) {
1764
+ userInfo.hp += value.hp || 0;
1765
+ } else {
1766
+ userInfo.hp = maxHp;
1767
+ }
1768
+ if (userInfo.mp + (value.mp || 0) < maxHp) {
1769
+ userInfo.mp += value.mp || 0;
1770
+ } else {
1771
+ userInfo.mp = maxMp;
1524
1772
  }
1773
+ fn && await fn({
1774
+ currentHP: userInfo.hp,
1775
+ currentMP: userInfo.mp
1776
+ });
1777
+ await User.setDatabaseUserAttribute(userId);
1525
1778
  },
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
- }
1779
+ /** 给予玩家PP值 */
1780
+ async givePP(userId, value, fn) {
1781
+ const userInfo = User.userTempData[userId];
1782
+ if (!userInfo) return;
1783
+ const { maxPp } = User.getUserAttributeByUserId(userId);
1784
+ if (userInfo.pp + value < maxPp) {
1785
+ userInfo.pp += value;
1571
1786
  } 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
- }
1787
+ userInfo.pp = maxPp;
1788
+ }
1789
+ fn && await fn({
1790
+ currentPP: userInfo.pp
1791
+ });
1792
+ await User.setDatabaseUserAttribute(userId);
1793
+ },
1794
+ async lostPP(userId, value, fn) {
1795
+ const userInfo = User.userTempData[userId];
1796
+ if (!userInfo) return;
1797
+ if (userInfo.pp - value < 0) {
1798
+ fn && await fn({
1799
+ currentPP: userInfo.pp,
1800
+ err: "PP值不够,消耗失败!"
1581
1801
  });
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
- }
1802
+ return;
1803
+ }
1804
+ userInfo.pp -= value;
1805
+ fn && await fn({
1806
+ currentPP: userInfo.pp
1807
+ });
1808
+ await User.setDatabaseUserAttribute(userId);
1809
+ },
1810
+ /** 给予玩家货币 */
1811
+ async giveMonetary(userId, val, fn) {
1812
+ const [bindData] = await User.ctx.database.get("binding", { pid: userId });
1813
+ if (bindData && val) {
1814
+ const [currentM] = await User.ctx.database.get("monetary", { uid: bindData.aid });
1815
+ await User.ctx.monetary.gain(bindData.aid, val);
1816
+ fn && await fn({ val, currentVal: currentM.value += val });
1817
+ }
1818
+ },
1819
+ /** 收取玩家货币 */
1820
+ async lostMonetary(userId, val, fn) {
1821
+ const [bindData] = await User.ctx.database.get("binding", { pid: userId });
1822
+ if (bindData && val) {
1823
+ const [currentM] = await User.ctx.database.get("monetary", { uid: bindData.aid });
1824
+ if (currentM.value - val < 0) {
1825
+ fn && await fn({
1826
+ val: Math.abs(val),
1827
+ currentVal: currentM.value,
1828
+ err: "余额不足!"
1829
+ });
1830
+ return;
1589
1831
  }
1832
+ await User.ctx.monetary.cost(bindData.aid, val);
1833
+ fn && await fn({
1834
+ val: Math.abs(val),
1835
+ currentVal: currentM.value - val
1836
+ });
1837
+ }
1838
+ },
1839
+ /** 给予玩家指定道具 */
1840
+ async giveProps(userId, props, fn) {
1841
+ const userProps = Props.userPorpsTemp[userId];
1842
+ if (!userProps) return;
1843
+ const upProps = [];
1844
+ for (const item of props) {
1845
+ const propsItem = propsData[item.name];
1846
+ if (!propsItem) continue;
1847
+ userProps[item.name] = {
1848
+ name: propsItem.name,
1849
+ type: propsItem.type,
1850
+ value: 0
1851
+ };
1852
+ userProps[item.name].value += item.val || 1;
1853
+ upProps.push({ name: item.name, val: userProps[item.name].value });
1854
+ }
1855
+ fn && await fn({
1856
+ currentProps: upProps
1857
+ });
1858
+ await Props.setDatabasePropsData(userId);
1859
+ },
1860
+ /** 去除玩家指定道具 */
1861
+ async loseProps(userId, props, fn) {
1862
+ const userProps = Props.userPorpsTemp[userId];
1863
+ const propsItem = propsData[props.name];
1864
+ if (!userProps) return;
1865
+ if (!propsItem) {
1866
+ fn && await fn({
1867
+ currentProps: { name: props.name, val: 0 },
1868
+ err: "该道具信息不存在!"
1869
+ });
1870
+ return;
1871
+ }
1872
+ if (!userProps[props.name]) {
1873
+ userProps[props.name] = {
1874
+ name: propsItem.name,
1875
+ type: propsItem.type,
1876
+ value: 0
1877
+ };
1878
+ }
1879
+ if (userProps[props.name].value - (props.val || 1) < 0) {
1880
+ fn && await fn({
1881
+ currentProps: { name: props.name, val: userProps[props.name].value },
1882
+ err: `道具数量不足!剩余${userProps[props.name].value}个。`
1883
+ });
1884
+ return;
1590
1885
  }
1886
+ userProps[props.name].value -= props.val || 1;
1887
+ if (userProps[props.name].value == 0) delete userProps[props.name];
1888
+ fn && await fn({
1889
+ currentProps: { name: props.name, val: userProps[props.name]?.value || 0 }
1890
+ });
1891
+ await Props.setDatabasePropsData(userId);
1892
+ },
1893
+ /** 目标是否死亡 */
1894
+ isDie(userId) {
1895
+ return User.userTempData[userId]?.isDie;
1591
1896
  }
1592
1897
  };
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
1898
 
1669
1899
  // src/index.ts
1670
1900
  var name = "smmcat-gensokyo";
@@ -1786,10 +2016,22 @@ function apply(ctx, config) {
1786
2016
  await session.send(GensokyoMap.userAreaTextFormat(userData.playName, query));
1787
2017
  });
1788
2018
  ctx.command("幻想乡/个人属性").action(async ({ session }) => {
2019
+ const userData = await User.getUserAttribute(session);
2020
+ if (!userData) return;
2021
+ GensokyoMap.initUserPoistion(session, userData);
1789
2022
  return `您的属性如下:
1790
2023
  ` + User.userAttributeTextFormat(session.userId);
1791
2024
  });
2025
+ ctx.command("幻想乡/个人道具").action(async ({ session }) => {
2026
+ const userData = await User.getUserAttribute(session);
2027
+ if (!userData) return;
2028
+ GensokyoMap.initUserPoistion(session, userData);
2029
+ return await Props.getPropsDataByUserId(session.userId);
2030
+ });
1792
2031
  ctx.command("幻想乡/个人信息").userFields(["id"]).action(async ({ session }) => {
2032
+ const userData = await User.getUserAttribute(session);
2033
+ if (!userData) return;
2034
+ GensokyoMap.initUserPoistion(session, userData);
1793
2035
  const [data] = await ctx.database.get("monetary", { uid: session.user.id });
1794
2036
  return `[${User.userTempData[session.userId].playName}]:您当前货币为:${data?.value || 0}个`;
1795
2037
  });
@@ -1861,6 +2103,15 @@ function apply(ctx, config) {
1861
2103
  await BattleData.createBattleByUser(session, [{ userId: exist.userId }]);
1862
2104
  }
1863
2105
  });
2106
+ ctx.command("幻想乡/道具使用 <props>").action(async ({ session }, props) => {
2107
+ const userData = await User.getUserAttribute(session);
2108
+ if (!userData) return;
2109
+ GensokyoMap.initUserPoistion(session, userData);
2110
+ if (!props) {
2111
+ return `未选择道具使用,请选择道具,例如:/道具使用 红药`;
2112
+ }
2113
+ await Props.userProps(session, props);
2114
+ });
1864
2115
  ctx.command("幻想乡/技能查询 <goal>").action(async ({ session }, goal) => {
1865
2116
  if (!goal) return `请输入技能名,例如 /技能查询 重砍`;
1866
2117
  if (!skillFn[goal]) return `没有存在 ${goal} 技能!`;