koishi-plugin-maple-warriors 0.0.1 → 0.0.3

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
@@ -34,13 +34,13 @@ var DEFAULT_PREY_DATA = [
34
34
  "野兔 1 3-5 2-4 2-4 1-3 5-50"
35
35
  ];
36
36
  var Config = import_koishi.Schema.object({
37
- preyData: import_koishi.Schema.array(import_koishi.Schema.string()).role("table").default(DEFAULT_PREY_DATA).description("猎物数据,每行格式:猎物名 权重 体质 攻击 韧性 暴击 敏捷(权重是固定数值,属性可以是固定数值或范围,如1-10)"),
37
+ preyData: import_koishi.Schema.array(import_koishi.Schema.string()).role("table").default(DEFAULT_PREY_DATA).description("猎物数据,每行格式:猎物名 权重 体质 攻击 防御 暴击 敏捷(权重是固定数值,属性可以是固定数值或范围,如1-10)"),
38
38
  battleMessageInterval: import_koishi.Schema.number().min(1).max(5).default(2).description("战斗消息发送间隔(秒)")
39
39
  });
40
40
  function calculateRates(character) {
41
41
  const resistance = (character.toughness / (character.toughness + 90)).toFixed(4);
42
42
  const critRate = (character.crit / (character.crit + 90)).toFixed(4);
43
- const chargeTime = (1 + 280 / (character.agility + 70)).toFixed(2);
43
+ const chargeTime = (1 + 720 / (character.agility + 80)).toFixed(2);
44
44
  const dodgeRate = (0.2 * character.agility / (character.agility + 90)).toFixed(4);
45
45
  return { resistance, critRate, chargeTime, dodgeRate };
46
46
  }
@@ -233,7 +233,7 @@ function apply(ctx, config) {
233
233
  等级: ${character.level}
234
234
  体质: ${character.constitution} (HP: ${character.currentHp}/${character.maxHp})
235
235
  攻击: ${character.attack}
236
- 韧性: ${character.toughness} (抗性: ${(parseFloat(rates.resistance) * 100).toFixed(2)}%)
236
+ 防御: ${character.toughness} (韧性: ${(parseFloat(rates.resistance) * 100).toFixed(2)}%)
237
237
  暴击: ${character.crit} (暴击率: ${(parseFloat(rates.critRate) * 100).toFixed(2)}%)
238
238
  敏捷: ${character.agility} (蓄力: ${rates.chargeTime}s 闪避率: ${(parseFloat(rates.dodgeRate) * 100).toFixed(2)}%)
239
239
  状态: ${character.status}${character.statusEndTime ? " 剩余" + formatRemainingTime(character.statusEndTime) : ""}
@@ -300,7 +300,7 @@ ${itemsText || "空空如也"}`;
300
300
  }
301
301
  __name(checkCharacterStatus, "checkCharacterStatus");
302
302
  ctx.command("猫武士", "猫武士插件 - 帮助菜单");
303
- ctx.command("猫武士/修改名字 <name>", "修改角色名字").example("修改名字 火焰猫").example("修改名字 闪电虎").action(async ({ session }, name2) => {
303
+ ctx.command("猫武士/修改名字 <name>", "修改角色名字").example("修改名字 火星").action(async ({ session }, name2) => {
304
304
  if (!name2 || name2.trim().length === 0) {
305
305
  return "格式错误!正确格式:修改名字 角色名";
306
306
  }
@@ -343,27 +343,26 @@ ${itemsText || "空空如也"}`;
343
343
  let character = await getOrCreateCharacter(userId);
344
344
  return await formatCharacterInfo(character);
345
345
  });
346
- ctx.command("猫武士/训练 <attrs>", "训练提升属性").example("训练 体质 体质 攻击").example("训练 体质").example("训练 随机").action(async ({ session }, attrs) => {
346
+ ctx.command("猫武士/训练 <...args>", "训练提升属性").example("训练 体质 体质 攻击").example("训练 体质").example("训练 随机").action(async ({ session }, ...args) => {
347
347
  const userId = session.userId;
348
348
  let character = await getOrCreateCharacter(userId);
349
- const statusCheck = checkCharacterStatus(character);
350
- if (!statusCheck.canAct) {
351
- return statusCheck.message;
352
- }
353
349
  const today = getTodayDateString();
354
350
  if (character.lastTrainDate && isSameDay(character.lastTrainDate, today)) {
355
351
  return "今天已经训练过了,要注意劳逸结合哦!";
356
352
  }
357
- if (!attrs) {
353
+ const statusCheck = checkCharacterStatus(character);
354
+ if (!statusCheck.canAct) {
355
+ return statusCheck.message;
356
+ }
357
+ if (args.length === 0) {
358
358
  return "格式错误!正确格式:训练 属性1 属性2 属性3(可重复,若只指定一项,则其余两项随机提升)或 训练 随机";
359
359
  }
360
- const attrList = attrs.trim().split(/\s+/);
361
- if (attrList.length === 1 && attrList[0] === "随机") {
362
- const validAttrs2 = ["体质", "攻击", "韧性", "暴击", "敏捷"];
360
+ if (args.length === 1 && args[0] === "随机") {
361
+ const validAttrs2 = ["体质", "攻击", "防御", "暴击", "敏捷"];
363
362
  const attrMap2 = {
364
363
  "体质": "constitution",
365
364
  "攻击": "attack",
366
- "韧性": "toughness",
365
+ "防御": "toughness",
367
366
  "暴击": "crit",
368
367
  "敏捷": "agility"
369
368
  };
@@ -385,30 +384,30 @@ ${itemsText || "空空如也"}`;
385
384
  return `训练成功!你好像领悟了什么……
386
385
  ${changes2.join(" ")}`;
387
386
  }
388
- if (attrList.length > 3) {
387
+ if (args.length > 3) {
389
388
  return "只能指定3个属性(可以重复),不要太贪心哦!";
390
389
  }
391
- const validAttrs = ["体质", "攻击", "韧性", "暴击", "敏捷"];
390
+ const validAttrs = ["体质", "攻击", "防御", "暴击", "敏捷"];
392
391
  const attrMap = {
393
392
  "体质": "constitution",
394
393
  "攻击": "attack",
395
- "韧性": "toughness",
394
+ "防御": "toughness",
396
395
  "暴击": "crit",
397
396
  "敏捷": "agility"
398
397
  };
399
- for (const attr of attrList) {
398
+ for (const attr of args) {
400
399
  if (!validAttrs.includes(attr)) {
401
400
  return `属性名错误!有效的属性有:${validAttrs.join("、")}`;
402
401
  }
403
402
  }
404
403
  const updates = {};
405
404
  const attributeCounts = {};
406
- for (const attr of attrList) {
405
+ for (const attr of args) {
407
406
  const field = attrMap[attr];
408
407
  updates[field] = (updates[field] || character[field] || 0) + 1;
409
408
  attributeCounts[attr] = (attributeCounts[attr] || 0) + 1;
410
409
  }
411
- for (let i = 0; i < 3 - attrList.length; i++) {
410
+ for (let i = 0; i < 3 - args.length; i++) {
412
411
  const randomAttr = validAttrs[Math.floor(Math.random() * validAttrs.length)];
413
412
  const field = attrMap[randomAttr];
414
413
  updates[field] = (updates[field] || character[field] || 0) + 1;
@@ -450,7 +449,7 @@ ${changes.join(" ")}`;
450
449
  const crit = parseAttributeRange(selectedPrey.crit);
451
450
  const agility = parseAttributeRange(selectedPrey.agility);
452
451
  const preyHp = constitution * 5;
453
- const chargeTime = parseFloat((1 + 280 / (agility + 70)).toFixed(2));
452
+ const chargeTime = parseFloat((1 + 720 / (agility + 80)).toFixed(2));
454
453
  const prey = {
455
454
  name: selectedPrey.name,
456
455
  constitution,
@@ -474,7 +473,7 @@ ${changes.join(" ")}`;
474
473
  await session.send(`发现猎物: ${prey.name}
475
474
  体质: ${prey.constitution} (HP: ${prey.hp})
476
475
  攻击: ${prey.attack}
477
- 韧性: ${prey.toughness} (抗性: ${(parseFloat(preyRates.resistance) * 100).toFixed(2)}%)
476
+ 防御: ${prey.toughness} (韧性: ${(parseFloat(preyRates.resistance) * 100).toFixed(2)}%)
478
477
  暴击: ${prey.crit} (暴击率: ${(parseFloat(preyRates.critRate) * 100).toFixed(2)}%)
479
478
  敏捷: ${prey.agility} (蓄力: ${preyRates.chargeTime}s 闪避率: ${(parseFloat(preyRates.dodgeRate) * 100).toFixed(2)}%)`);
480
479
  await new Promise((resolve) => setTimeout(resolve, 2e3));
@@ -489,9 +488,18 @@ ${changes.join(" ")}`;
489
488
  agility: character.agility,
490
489
  hp: character.currentHp,
491
490
  maxHp: character.maxHp,
492
- chargeTime: parseFloat((1 + 280 / (character.agility + 70)).toFixed(2)),
491
+ chargeTime: parseFloat((1 + 720 / (character.agility + 80)).toFixed(2)),
493
492
  nextAttackTime: 0
494
493
  };
494
+ await executeBattle(
495
+ session,
496
+ player,
497
+ prey,
498
+ config.battleMessageInterval,
499
+ false,
500
+ // 不是训练模式
501
+ abortController
502
+ );
495
503
  const today2 = getTodayDateString();
496
504
  const updates = {
497
505
  lastHuntDate: today2,
@@ -508,6 +516,7 @@ ${changes.join(" ")}`;
508
516
  const items = parseItemsString(character.items);
509
517
  items[selectedPrey.name] = (items[selectedPrey.name] || 0) + 1;
510
518
  updates.items = serializeItems(items);
519
+ await session.send(`捕猎成功!获得物品 ${selectedPrey.name}*1`);
511
520
  }
512
521
  }
513
522
  await ctx.database.set("maple_warriors", { userId }, updates);
@@ -584,7 +593,7 @@ ${changes.join(" ")}`;
584
593
  }
585
594
  if (item.toughnessBonus) {
586
595
  updates.toughness = character.toughness + item.toughnessBonus * count;
587
- changes.push(`韧性+${item.toughnessBonus * count}`);
596
+ changes.push(`防御+${item.toughnessBonus * count}`);
588
597
  }
589
598
  if (item.critBonus) {
590
599
  updates.crit = character.crit + item.critBonus * count;
@@ -654,6 +663,7 @@ ${changes.join(" ")}`;
654
663
  });
655
664
  }
656
665
  battleManager.endBattle(channelId);
666
+ return;
657
667
  } else {
658
668
  return "当前没有正在进行的战斗。";
659
669
  }
@@ -688,7 +698,7 @@ ${changes.join(" ")}`;
688
698
  if (item.hpBonus) bonuses.push(`HP+${item.hpBonus}`);
689
699
  if (item.constitutionBonus) bonuses.push(`体质+${item.constitutionBonus}`);
690
700
  if (item.attackBonus) bonuses.push(`攻击+${item.attackBonus}`);
691
- if (item.toughnessBonus) bonuses.push(`韧性+${item.toughnessBonus}`);
701
+ if (item.toughnessBonus) bonuses.push(`防御+${item.toughnessBonus}`);
692
702
  if (item.critBonus) bonuses.push(`暴击+${item.critBonus}`);
693
703
  if (item.agilityBonus) bonuses.push(`敏捷+${item.agilityBonus}`);
694
704
  let result = `物品: ${item.name}
@@ -701,7 +711,7 @@ ${changes.join(" ")}`;
701
711
  }
702
712
  return result.trim();
703
713
  });
704
- ctx.command("猫武士/添加物品 <...args>", "添加或修改物品").example("添加物品 老鼠 体质 1 很常见的老鼠").example("添加物品 治疗药水 hp 10 恢复生命值").action(async ({ session }, ...args) => {
714
+ ctx.command("猫武士/添加物品 <...args>", "添加或修改物品").example("添加物品 老鼠 hp 1 很常见的老鼠").example("添加物品 治疗药水 hp 10 恢复生命值").action(async ({ session }, ...args) => {
705
715
  if (args.length < 1) {
706
716
  return "格式错误!正确格式:添加物品 物品名 [属性 增加数 ...] [介绍]";
707
717
  }
@@ -716,13 +726,13 @@ ${changes.join(" ")}`;
716
726
  agilityBonus: 0
717
727
  };
718
728
  let i = 1;
719
- const validAttrs = ["HP", "hp", "体质", "攻击", "韧性", "暴击", "敏捷"];
729
+ const validAttrs = ["HP", "hp", "体质", "攻击", "防御", "暴击", "敏捷"];
720
730
  const attrMap = {
721
731
  "HP": "hpBonus",
722
732
  "hp": "hpBonus",
723
733
  "体质": "constitutionBonus",
724
734
  "攻击": "attackBonus",
725
- "韧性": "toughnessBonus",
735
+ "防御": "toughnessBonus",
726
736
  "暴击": "critBonus",
727
737
  "敏捷": "agilityBonus"
728
738
  };
@@ -751,7 +761,7 @@ ${changes.join(" ")}`;
751
761
  if (fieldName) {
752
762
  updates[fieldName] = value;
753
763
  } else {
754
- return `属性名错误!有效的属性有:${["HP", "体质", "攻击", "韧性", "暴击", "敏捷"].join("、")}`;
764
+ return `属性名错误!有效的属性有:${["HP", "体质", "攻击", "防御", "暴击", "敏捷"].join("、")}`;
755
765
  }
756
766
  i += 2;
757
767
  }
@@ -762,7 +772,7 @@ ${changes.join(" ")}`;
762
772
  description,
763
773
  createdAt: /* @__PURE__ */ new Date()
764
774
  });
765
- return `修改${itemName}成功!`;
775
+ return `修改物品成功!`;
766
776
  } else {
767
777
  await ctx.database.create("maple_warriors_items", {
768
778
  name: itemName,
@@ -770,7 +780,7 @@ ${changes.join(" ")}`;
770
780
  description,
771
781
  createdAt: /* @__PURE__ */ new Date()
772
782
  });
773
- return `添加${itemName}成功!`;
783
+ return `添加物品成功!`;
774
784
  }
775
785
  });
776
786
  ctx.command("猫武士/物品列表 [page]", "查看物品列表").example("物品列表").example("物品列表 2").action(async ({ session }, page = "1") => {
@@ -810,13 +820,18 @@ ${changes.join(" ")}`;
810
820
  ctx.command("猫武士/战斗训练 <target:user>", "与指定用户的角色进行训练战斗(不消耗HP)").example("战斗训练 @火星").action(async ({ session }, target) => {
811
821
  const channelId = session.channelId;
812
822
  const userId = session.userId;
823
+ let targetUserId = target;
824
+ if (target.includes(":")) {
825
+ const parts = target.split(":");
826
+ targetUserId = parts[parts.length - 1];
827
+ }
813
828
  if (battleManager.isBattling(channelId)) {
814
829
  return "请等待当前战斗结束!";
815
830
  }
816
- if (!target) {
831
+ if (!targetUserId) {
817
832
  return "请指定训练对手!正确格式:战斗训练 @用户名";
818
833
  }
819
- if (target === userId) {
834
+ if (targetUserId === userId) {
820
835
  return "不能和自己进行战斗训练哦!";
821
836
  }
822
837
  let player1 = await getOrCreateCharacter(userId);
@@ -824,7 +839,11 @@ ${changes.join(" ")}`;
824
839
  if (!statusCheck.canAct) {
825
840
  return statusCheck.message;
826
841
  }
827
- let player2 = await getOrCreateCharacter(target);
842
+ let player2Characters = await ctx.database.get("maple_warriors", { userId: targetUserId });
843
+ if (player2Characters.length === 0) {
844
+ return "战斗失败!对方尚未生成角色";
845
+ }
846
+ let player2 = player2Characters[0];
828
847
  const opponentStatusCheck = checkCharacterStatus(player2);
829
848
  if (!opponentStatusCheck.canAct) {
830
849
  return `对手目前状态不佳,无法进行战斗训练:${opponentStatusCheck.message}`;
@@ -842,7 +861,7 @@ ${changes.join(" ")}`;
842
861
  hp: player1.currentHp,
843
862
  // 使用当前HP
844
863
  maxHp: player1.maxHp,
845
- chargeTime: parseFloat((1 + 280 / (player1.agility + 70)).toFixed(2)),
864
+ chargeTime: parseFloat((1 + 720 / (player1.agility + 80)).toFixed(2)),
846
865
  nextAttackTime: 0
847
866
  };
848
867
  const player2Char = {
@@ -855,7 +874,7 @@ ${changes.join(" ")}`;
855
874
  hp: player2.currentHp,
856
875
  // 使用当前HP
857
876
  maxHp: player2.maxHp,
858
- chargeTime: parseFloat((1 + 280 / (player2.agility + 70)).toFixed(2)),
877
+ chargeTime: parseFloat((1 + 720 / (player2.agility + 80)).toFixed(2)),
859
878
  nextAttackTime: 0
860
879
  };
861
880
  const abortController = battleManager.getAbortController(channelId);
@@ -902,8 +921,8 @@ ${changes.join(" ")}`;
902
921
  }
903
922
  __name(apply, "apply");
904
923
  async function executeBattle(session, player1, player2, battleMessageInterval, isTraining = false, abortController) {
905
- const originalHp1 = player1.hp;
906
- const originalHp2 = player2.hp;
924
+ const initialHp1 = player1.hp;
925
+ const initialHp2 = player2.hp;
907
926
  const rates1 = calculateRates({
908
927
  toughness: player1.toughness,
909
928
  crit: player1.crit,
@@ -957,21 +976,18 @@ async function executeBattle(session, player1, player2, battleMessageInterval, i
957
976
  }
958
977
  const baseDamage = attacker.attack * (0.5 + Math.random());
959
978
  let initialDamage = Math.ceil(baseDamage);
960
- let totalDamage = initialDamage;
961
979
  const attackerCritRate = attacker === player1 ? critRate1 : critRate2;
962
980
  let isCritical = false;
963
981
  if (Math.random() < attackerCritRate) {
964
- totalDamage *= 2;
982
+ initialDamage *= 2;
965
983
  isCritical = true;
966
984
  battleMessage += ` 暴击!`;
967
985
  }
986
+ battleMessage += ` 造成了${initialDamage}点伤害。`;
968
987
  const reduceAmount = defender.toughness * Math.random();
969
- const reducedDamage = Math.min(Math.ceil(reduceAmount), totalDamage);
970
- const finalDamage = totalDamage - reducedDamage;
988
+ const reducedDamage = Math.min(Math.ceil(reduceAmount), initialDamage);
989
+ const finalDamage = initialDamage - reducedDamage;
971
990
  if (finalDamage <= 0) {
972
- if (isCritical) {
973
- battleMessage += ` 造成了${totalDamage}点伤害。`;
974
- }
975
991
  battleMessage += ` 被${defender.name}抵挡住了!`;
976
992
  await session.send(battleMessage);
977
993
  currentTime = attackTime;
@@ -979,11 +995,6 @@ async function executeBattle(session, player1, player2, battleMessageInterval, i
979
995
  }
980
996
  defender.hp -= finalDamage;
981
997
  if (defender.hp < 0) defender.hp = 0;
982
- if (isCritical) {
983
- battleMessage += ` 造成了${totalDamage}点伤害。`;
984
- } else {
985
- battleMessage += ` 造成了${initialDamage}点伤害。`;
986
- }
987
998
  battleMessage += ` ${defender.name}抵挡了${reducedDamage}点伤害,实际造成${finalDamage}点伤害。${defender.name} HP: ${defender.hp}`;
988
999
  await session.send(battleMessage);
989
1000
  if (defender.hp <= 0) {
@@ -993,10 +1004,12 @@ async function executeBattle(session, player1, player2, battleMessageInterval, i
993
1004
  currentTime = attackTime;
994
1005
  }
995
1006
  if (currentTime > maxBattleTime && player1.hp > 0 && player2.hp > 0) {
996
- if (player1.hp > player2.hp) {
997
- await session.send(`战斗超时!${player1.name} 剩余HP更高,获得胜利!`);
1007
+ const player1Loss = initialHp1 - player1.hp;
1008
+ const player2Loss = initialHp2 - player2.hp;
1009
+ if (player1Loss < player2Loss) {
1010
+ await session.send(`战斗超时!${player1.name} 损失HP较少,获得胜利!`);
998
1011
  } else if (player2.hp > player1.hp) {
999
- await session.send(`战斗超时!${player2.name} 剩余HP更高,获得胜利!`);
1012
+ await session.send(`战斗超时!${player2.name} 损失HP较少,获得胜利!`);
1000
1013
  } else {
1001
1014
  await session.send(`战斗超时!双方平局!`);
1002
1015
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-maple-warriors",
3
3
  "description": "-",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/lib/index.d.ts DELETED
@@ -1,47 +0,0 @@
1
- import { Context, Schema } from 'koishi';
2
- export declare const using: readonly ["database"];
3
- declare module 'koishi' {
4
- interface Tables {
5
- maple_warriors: MapleWarrior;
6
- maple_warriors_items: MapleItem;
7
- }
8
- }
9
- export interface MapleWarrior {
10
- id: number;
11
- userId: string;
12
- name: string;
13
- level: number;
14
- constitution: number;
15
- attack: number;
16
- toughness: number;
17
- crit: number;
18
- agility: number;
19
- currentHp: number;
20
- maxHp: number;
21
- status: string;
22
- previousStatus: string;
23
- statusEndTime: Date | null;
24
- items: string;
25
- lastTrainDate: string;
26
- lastHuntDate: string;
27
- updatedAt: Date;
28
- }
29
- export interface MapleItem {
30
- id: number;
31
- name: string;
32
- hpBonus: number;
33
- constitutionBonus: number;
34
- attackBonus: number;
35
- toughnessBonus: number;
36
- critBonus: number;
37
- agilityBonus: number;
38
- description: string;
39
- createdAt: Date;
40
- }
41
- export declare const name = "maple-warriors";
42
- export interface Config {
43
- preyData: string[];
44
- battleMessageInterval: number;
45
- }
46
- export declare const Config: Schema<Config>;
47
- export declare function apply(ctx: Context, config: Config): void;