From f84e10b1ffbf8efeef83cea868b1920367d27520 Mon Sep 17 00:00:00 2001 From: narumi Date: Wed, 18 Sep 2024 23:42:31 +0800 Subject: [PATCH] Support classboard command spell effect --- .../battle/functions/function_executor.dart | 6 ++ lib/app/battle/models/skill.dart | 11 ++++ lib/app/battle/models/svt_entity.dart | 34 ++++++++--- lib/models/gamedata/buff.dart | 1 + lib/models/gamedata/class_board.dart | 58 ++++++++++++++++--- lib/models/gamedata/const_data.dart | 13 +++++ lib/models/gamedata/vals.dart | 2 + 7 files changed, 108 insertions(+), 17 deletions(-) diff --git a/lib/app/battle/functions/function_executor.dart b/lib/app/battle/functions/function_executor.dart index 3b73536d9..6c78507e2 100644 --- a/lib/app/battle/functions/function_executor.dart +++ b/lib/app/battle/functions/function_executor.dart @@ -88,6 +88,12 @@ class FunctionExecutor { battleData.functionResults.add(null); continue; } + final actMasterGenderType = dataVal.ActMasterGenderType ?? 0; + if (actMasterGenderType != 0) { + if (!(db.curUser.isGirl ? actMasterGenderType == 2 : actMasterGenderType == 1)) { + continue; + } + } final updatedResult = await FunctionExecutor.executeFunction( battleData, diff --git a/lib/app/battle/models/skill.dart b/lib/app/battle/models/skill.dart index 08452df72..236c71301 100644 --- a/lib/app/battle/models/skill.dart +++ b/lib/app/battle/models/skill.dart @@ -227,6 +227,14 @@ class BattleSkillInfoData { if (curSkill.type == SkillType.active) { await activator?.activateBuff(battleData, BuffAction.functionSkillAfter); } + for (final svt in wouldAffectTargets) { + if (type == SkillInfoType.commandSpell) { + final csId = curSkill.functions.firstOrNull?.svals.firstOrNull?.CommandSpellId; + if (csId == 1 || csId == 9) { + await svt.activateBuff(battleData, BuffAction.functionClassboardCommandSpellAfter, skillInfo: this); + } + } + } return true; } @@ -328,6 +336,7 @@ class CommonCustomSkills { 'Rate': 1000, 'Value': 1000, 'Unaffected': 1, + "CommandSpellId": 1, }) ], ) @@ -352,6 +361,7 @@ class CommonCustomSkills { 'Rate': 3000, 'Value': 10000, 'Unaffected': 1, + "CommandSpellId": 9, }) ], ) @@ -375,6 +385,7 @@ class CommonCustomSkills { 'Rate': 5000, 'Value': 10000, 'Unaffected': 1, + "CommandSpellId": 1001, }) ], ) diff --git a/lib/app/battle/models/svt_entity.dart b/lib/app/battle/models/svt_entity.dart index 37dc52f15..34427dd9a 100644 --- a/lib/app/battle/models/svt_entity.dart +++ b/lib/app/battle/models/svt_entity.dart @@ -1809,22 +1809,40 @@ class BattleServantData { for (final buff in collectBuffsPerAction(battleBuff.validBuffsActiveFirst, buffAction)) { final List selfTraits = fetchSelfTraits(buffAction, buff, this, cardData: card); final List? otherTraits = fetchOtherTraits(buffAction, buff, other, cardData: card); - if (await buff.shouldActivateBuff( battleData, selfTraits, opTraits: otherTraits, skillInfoType: skillInfo?.type, )) { - final skillId = buff.param; - BaseSkill? skill = db.gameData.baseSkills[skillId]; - skill ??= await showEasyLoading(() => AtlasApi.skill(skillId), mask: true); - if (skill == null) { + BaseSkill? skill; + if (buff.buff.type == BuffType.classboardCommandSpellAfterFunction) { + final spellId = buff.param; + final targetCommandSpell = db.gameData.classBoards.values + .expand((e) => e.squares) + .map((e) => e.targetCommandSpell) + .firstWhereOrNull((e) => e?.id == spellId); + if (targetCommandSpell != null) { + skill = targetCommandSpell.toSkill(); + } + if (skill == null) { + battleData.battleLogger.debug( + 'Buff ID [${buff.buff.id}]: ${S.current.command_spell}(classboard) [$spellId] ${S.current.not_found}'); + continue; + } battleData.battleLogger - .debug('Buff ID [${buff.buff.id}]: ${S.current.skill} [$skillId] ${S.current.not_found}'); - continue; + .function('$lBattleName - ${buff.buff.lName.l} ${S.current.command_spell}(classboard) [$spellId]'); + } else { + final skillId = buff.param; + skill = db.gameData.baseSkills[skillId]; + skill ??= await showEasyLoading(() => AtlasApi.skill(skillId), mask: true); + if (skill == null) { + battleData.battleLogger + .debug('Buff ID [${buff.buff.id}]: ${S.current.skill} [$skillId] ${S.current.not_found}'); + continue; + } + battleData.battleLogger.function('$lBattleName - ${buff.buff.lName.l} ${S.current.skill} [$skillId]'); } - battleData.battleLogger.function('$lBattleName - ${buff.buff.lName.l} ${S.current.skill} [$skillId]'); await FunctionExecutor.executeFunctions( battleData, skill.functions, diff --git a/lib/models/gamedata/buff.dart b/lib/models/gamedata/buff.dart index f150f2076..313f91824 100644 --- a/lib/models/gamedata/buff.dart +++ b/lib/models/gamedata/buff.dart @@ -477,6 +477,7 @@ enum BuffType { toFieldChangeField(10001), toFieldAvoidBuff(10002), toFieldSubIndividualityField(10003), + classboardCommandSpellAfterFunction(200001), ; final int value; diff --git a/lib/models/gamedata/class_board.dart b/lib/models/gamedata/class_board.dart index bd778e290..a0a6e2cb0 100644 --- a/lib/models/gamedata/class_board.dart +++ b/lib/models/gamedata/class_board.dart @@ -82,19 +82,28 @@ class ClassBoard with RouteInfo { NiceSkill? toSkill(ClassBoardPlan v) { Map skills = {}; - Map levels = {}; + Map skillLvs = {}; + Map spells = {}; + Map spellLvs = {}; for (final square in squares) { final targetSkill = square.targetSkill; - if (targetSkill == null) continue; - if (v.enhancedSquares.contains(square.id)) { - skills.putIfAbsent(targetSkill.id, () => targetSkill); - levels.addNum(targetSkill.id, square.upSkillLv); + final targetCommandSpell = square.targetCommandSpell; + if (targetSkill != null) { + if (v.enhancedSquares.contains(square.id)) { + skills.putIfAbsent(targetSkill.id, () => targetSkill); + skillLvs.addNum(targetSkill.id, square.upSkillLv); + } + } else if (targetCommandSpell != null) { + if (v.enhancedSquares.contains(square.id)) { + spells.putIfAbsent(targetCommandSpell.id, () => targetCommandSpell); + spellLvs.addNum(targetCommandSpell.id, square.upSkillLv); + } } } List functions = []; - for (final skillId in levels.keys) { + for (final skillId in skillLvs.keys) { final skill = skills[skillId]!; - final lv = levels[skillId]!.clamp(0, skill.maxLv); + final lv = skillLvs[skillId]!.clamp(0, skill.maxLv); if (lv == 0) continue; for (final func in skill.functions) { final func2 = NiceFunction.fromJson(func.toJson()); @@ -102,6 +111,37 @@ class ClassBoard with RouteInfo { functions.add(func2); } } + for (final spellId in spellLvs.keys) { + final spell = spells[spellId]!; + final lv = spellLvs[spellId]!.clamp(0, spell.functions.firstOrNull?.svals.length ?? 0); + if (lv == 0 || spell.functions.isEmpty) continue; + final func = spell.functions.first; + functions.add(NiceFunction( + funcId: -spellId, + funcType: FuncType.addState, + funcTargetType: FuncTargetType.self, + funcPopupText: spell.name, + funcPopupIcon: func.funcPopupIcon, + buffs: [ + Buff( + id: -spellId, + type: BuffType.classboardCommandSpellAfterFunction, + name: spell.name, + detail: spell.detail, + icon: func.funcPopupIcon, + ) + ], + svals: [ + DataVals({ + "Turn": -1, + "Count": -1, + "Rate": 5000, + // "ClassBoardId": id, + "Value": spellId, + "Value2": lv, + }) + ])); + } if (functions.isEmpty) return null; return NiceSkill( id: -(1000000 + DateTime.now().timestamp % 1000000), @@ -214,7 +254,7 @@ class ClassBoardSquare { @JsonSerializable() class ClassBoardCommandSpell { int id; - int commandSpellId; + int commandSpellId; // current only dump csId=1 one, but not csId=9. They are the same, but should always check csId // int lv; String name; String detail; @@ -234,7 +274,7 @@ class ClassBoardCommandSpell { NiceSkill toSkill({String? icon}) { return NiceSkill( - id: -commandSpellId, + id: -id, name: name, unmodifiedDetail: detail, icon: icon ?? ClassBoardSquare.csIcon(db.curUser.isGirl), diff --git a/lib/models/gamedata/const_data.dart b/lib/models/gamedata/const_data.dart index 956d22e75..7aada07b3 100644 --- a/lib/models/gamedata/const_data.dart +++ b/lib/models/gamedata/const_data.dart @@ -76,6 +76,18 @@ class ConstGameData { this.config = const ConstDataConfig(), this.destinyOrderSummons = const [], }) : buffTypeActionMap = {} { + if (buffActions.isNotEmpty) { + buffActions[BuffAction.functionClassboardCommandSpellAfter] = BuffActionInfo( + limit: BuffLimit.none, + plusTypes: [BuffType.classboardCommandSpellAfterFunction], + minusTypes: [], + baseParam: 0, + baseValue: 0, + isRec: true, + plusAction: BuffAction.none, + maxRate: [0], + ); + } for (final entry in buffActions.entries) { for (final type in [...entry.value.plusTypes, ...entry.value.minusTypes]) { buffTypeActionMap.putIfAbsent(type, () => []).add(entry.key); @@ -1245,6 +1257,7 @@ enum BuffAction { functionStepInAfter(142), shortenSkillAfterUseSkill(143), pierceSpecialInvincible(144), + functionClassboardCommandSpellAfter(301), ; final int value; diff --git a/lib/models/gamedata/vals.dart b/lib/models/gamedata/vals.dart index a123ee810..0b2693011 100644 --- a/lib/models/gamedata/vals.dart +++ b/lib/models/gamedata/vals.dart @@ -298,6 +298,8 @@ class DataVals { int? get AddCount => _vals['AddCount']; int? get RateCount => _vals['RateCount']; int? get DropRateCount => _vals['DropRateCount']; + // custom fields + int? get CommandSpellId => _vals['CommandSpellId']; List? _parseObjList(String key, T Function(Map json) fromJson) { final v = _vals[key];