骑马与砍杀中文站论坛

标题: 骑砍2技能系统(战争之风) [打印本页]

作者: 路过的罗格    时间: 2025-4-1 15:38
标题: 骑砍2技能系统(战争之风)
本帖最后由 路过的罗格 于 2025-4-1 16:02 编辑

源码:https://github.com/Luguode-Rogue/New_ZZZF/tree/master/New_ZZZF

整个流程已经跑通了,开始铺量往里面填代码



技能选择界面:

入口:SkillInventoryManager.OpenInventoryPresentation()
核心代码
  1.             // 切换游戏状态
  2.             var inventoryState = Game.Current.GameStateManager.CreateState<SkillInventoryState>();
  3.             inventoryState.InitializeLogic(_inventoryLogic);
  4.             Game.Current.GameStateManager.PushState(inventoryState, 0);
复制代码
界面代码:GauntletSkillScreen
核心代码
  1.             this._dataSource = new SPSkillVM(inventoryLogic, false/*mission != null && mission.DoesMissionRequireCivilianEquipment*/, new Func<WeaponComponentData, ItemObject.ItemUsageSetFlags>(this.GetItemUsageSetFlag), this.GetFiveStackShortcutkeyText(), this.GetEntireStackShortcutkeyText()); // 初始化数据源
  2.             this._gauntletLayer = new GauntletLayer(15, "GauntletLayer", true) // 创建 Gauntlet 层
  3.             base.AddLayer(this._gauntletLayer); // 添加层
  4.             this._gauntletMovie = this._gauntletLayer.LoadMovie("Inventory", this._dataSource); // 加载电影(界面)

复制代码
界面数据代码:SPSkillVM

界面Xml直接使用游戏本身的物品界面Inventory

新增一个技能的流程:
1.新建一个类,继承SkillBase,然后完成构造方法/Activate方法/CheckCondition方法。
[spoiler=嘲讽代码]
  1. using New_ZZZF.Systems;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using TaleWorlds.CampaignSystem.Extensions;
  8. using TaleWorlds.Core;
  9. using TaleWorlds.Engine;
  10. using TaleWorlds.InputSystem;
  11. using TaleWorlds.Library;
  12. using TaleWorlds.MountAndBlade;

  13. namespace New_ZZZF
  14. {
  15.     internal class ChaoFeng : SkillBase
  16.     {
  17.         public ChaoFeng()
  18.         {
  19.             SkillID = "ChaoFeng";      // 必须唯一
  20.             Type = SkillType.MainActive;    // 类型必须明确
  21.             Cooldown = 2;             // 冷却时间(秒)
  22.             ResourceCost = 0f;        // 消耗
  23.             Text = new TaleWorlds.Localization.TextObject("{=ZZZF0023}ChaoFeng");
  24.             Difficulty = null;// new List<SkillDifficulty> { new SkillDifficulty(50, "跑动"), new SkillDifficulty(5, "耐力") };//技能装备的需求
  25.             Description = new TaleWorlds.Localization.TextObject("{=ZZZF0024}嘲讽附近敌方单位,并持续大幅回复自身血量。受到嘲讽的单位会持续靠近施法者。持续时间:30秒。冷却时间:60秒。");
  26.         }
  27.         public override bool Activate(Agent agent)
  28.         {                    
  29.             // 每次创建新的状态实例
  30.             List<AgentBuff> newStates = new List<AgentBuff> { new ChaoFengBuffApplyToSelf(30f, agent), }; // 新实例
  31.             foreach (var state in newStates)
  32.             {
  33.                 state.TargetAgent = agent;
  34.                 agent.GetComponent<AgentSkillComponent>().StateContainer.AddState(state);
  35.             }
  36.             List<Agent> values= Script.GetTargetedInRange(agent, agent.GetEyeGlobalPosition(),30);
  37.             if (values!=null&&values.Count>0)
  38.             {
  39.                 foreach (var item in values)
  40.                 {
  41.                     // 每次创建新的状态实例
  42.                     newStates = new List<AgentBuff> { new ChaoFengBuffApplyToEnemy(30f, agent), }; // 新实例
  43.                     foreach (var state in newStates)
  44.                     {
  45.                         state.TargetAgent = item;
  46.                         item.GetComponent<AgentSkillComponent>().StateContainer.AddState(state);
  47.                     }
  48.                 }

  49.                 return true;
  50.             }

  51.             return false;
  52.         }
  53.         public override bool CheckCondition(Agent caster)
  54.         {
  55.             SkillSystemBehavior.ActiveComponents.TryGetValue(caster.Index, out var agentSkill);
  56.             if (agentSkill == null) { return false; }
  57.             if (caster.Health/ agentSkill.MaxHP<=0.5f)
  58.             {
  59.                 return true;
  60.             }
  61.             List<Agent> FoeList = Script.GetTargetedInRange(caster, caster.GetEyeGlobalPosition(), 30);
  62.             List<Agent> FriendList = Script.GetTargetedInRange(caster, caster.GetEyeGlobalPosition(), 30,true);
  63.             if (FoeList.Count>0)
  64.             {
  65.                 if (FoeList.Count > 5)
  66.                 {
  67.                     return true;
  68.                 }
  69.                 else if (FoeList.Count>2&&FriendList.Count>0)
  70.                 {
  71.                     return true;
  72.                 }
  73.             }
  74.             // 默认条件:Agent存活且非坐骑
  75.             return false;
  76.         }

  77.         public class ChaoFengBuffApplyToEnemy : AgentBuff
  78.         {
  79.             private float _timeSinceLastTick;
  80.             public ChaoFengBuffApplyToEnemy(float duration, Agent source)
  81.             {
  82.                 StateId = "ChaoFengBuffApplyToEnemy";
  83.                 Duration = duration;
  84.                 SourceAgent = source;
  85.                 _timeSinceLastTick = 0; // 新增初始化
  86.             }

  87.             public override void OnApply(Agent agent)
  88.             {
  89.                 agent.SetTargetAgent(SourceAgent);
  90.                 agent.SetTargetPosition(SourceAgent.Position.AsVec2);
  91.             }

  92.             public override void OnUpdate(Agent agent, float dt)
  93.             {
  94.                 SkillSystemBehavior.ActiveComponents.TryGetValue(this.SourceAgent.Index, out var agentSkillComponent);
  95.                 if (agentSkillComponent == null) { return; }
  96.                 // 累积时间
  97.                 _timeSinceLastTick += dt;

  98.                 //每秒刷一次状态
  99.                 if (_timeSinceLastTick >= 1f)
  100.                 {
  101.                     agent.SetTargetAgent(SourceAgent);
  102.                     agent.SetTargetPosition(SourceAgent.Position.AsVec2);
  103.                     _timeSinceLastTick -= 1f; // 重置计时器
  104.                 }
  105.             }

  106.             public override void OnRemove(Agent agent)
  107.             {
  108.                 agent.ClearTargetFrame();
  109.                 agent.InvalidateTargetAgent();
  110.             }
  111.         }
  112.         public class ChaoFengBuffApplyToSelf : AgentBuff
  113.         {
  114.             private float _timeSinceLastTick;
  115.             public ChaoFengBuffApplyToSelf(float duration, Agent source)
  116.             {
  117.                 StateId = "ChaoFengBuffApplyToSelf";
  118.                 Duration = duration;
  119.                 SourceAgent = source;
  120.                 _timeSinceLastTick = 0; // 新增初始化
  121.             }

  122.             public override void OnApply(Agent agent)
  123.             {
  124.             }

  125.             public override void OnUpdate(Agent agent, float dt)
  126.             {
  127.                 SkillSystemBehavior.ActiveComponents.TryGetValue(this.SourceAgent.Index, out var agentSkillComponent);
  128.                 if (agentSkillComponent == null) { return; }
  129.                 // 累积时间
  130.                 _timeSinceLastTick += dt;

  131.                 //每秒刷一次状态
  132.                 if (_timeSinceLastTick >= 1f)
  133.                 {

  134.                     ZZZF_SandboxAgentStatCalculateModel zZZF_SandboxAgentStatCalculate = MissionGameModels.Current.AgentStatCalculateModel as ZZZF_SandboxAgentStatCalculateModel;
  135.                     if (zZZF_SandboxAgentStatCalculate != null)
  136.                     {
  137.                         zZZF_SandboxAgentStatCalculate._dt = dt;
  138.                         agent.Health += (agentSkillComponent.MaxHP - agent.Health) * 0.5f;
  139.                         
  140.                     }
  141.                     _timeSinceLastTick -= 1f; // 重置计时器
  142.                 }
  143.             }

  144.             public override void OnRemove(Agent agent)
  145.             {
  146.                
  147.             }
  148.         }
  149.     }
  150. }
复制代码

[/spoiler]

2.在SkillFactory类的_skillRegistry字典中,添加这个新技能的信息。现在,这个技能就一个可以在打开技能界面时被看到了。
[spoiler=_skillRegistry]
  1.         // 技能注册表:技能ID -> 技能实例(硬编码参数)
  2.         public static readonly Dictionary<string, SkillBase> _skillRegistry = new Dictionary<string, SkillBase>
  3.         {
  4.             //空技能
  5.             {"NullSkill",new NullSkill() },
  6.             //// 主主动技能
  7.             { "JianQi", new JianQi() }  ,          // 剑气斩
  8.             { "ConeOfArrows", new ConeOfArrows() }   ,         // 多重射击
  9.             { "DaoShan", new DaoShan() }   ,         // 刀扇
  10.             {"ShadowStep",new ShadowStep() },//暗影步
  11.             {"DaDiJianTa",new DaDiJianTa() },
  12.             {"ZhanYi",new ZhanYi() },
  13.             {"JueXing",new JueXing() },
  14.             {"TianQi",new TianQi() },
  15.             {"GuWu",new GuWu() },
  16.             {"ChaoFeng",new ChaoFeng() },
  17.             {"DunWu",new DunWu() },
  18.             {"FengBaoZhiLi",new FengBaoZhiLi() },
  19.             {"ZhanHao",new ZhanHao() },
  20.             {"WeiYa",new WeiYa() },
  21.             {"JingXia",new JingXia() },
  22.             {"YingXiongZhuFu",new YingXiongZhuFu() },
  23.             {"KongNueCiFu",new KongNueCiFu() },
  24.             {"NaGouCiFu",new NaGouCiFu() },
  25.             {"JianQiCiFu",new JianQiCiFu() },
  26.             
  27.             //// 副主动技能
  28.             { "Rush", new Rush() },             // Rush
  29.             {"MagicShoot",new MagicShoot() },

  30.             //// 被动技能
  31.             {"Roll",new Roll() },
  32.             
  33.             //// 法术
  34.             { "Fireball", new FireballSkill() },               // 火球术
  35.             { "lingmashaodi", new lingmashaodi() },               //
  36.             { "HuiJianYuanZhen", new HuiJianYuanZhen() },               // 辉剑圆阵

  37.             
  38.             //// 战技
  39.             //{ "ShieldBash", new ShieldBashSkill() },           // 盾牌猛击

  40.         };
复制代码

[/spoiler]
3.完成技能文本的翻译部分。
比如嘲讽的文本是
  1. Text = new TaleWorlds.Localization.TextObject("{=ZZZF0023}ChaoFeng");
  2. Description = new TaleWorlds.Localization.TextObject("{=ZZZF0024}嘲讽附近敌方单位,并持续大幅回复自身血量。受到嘲讽的单位会持续靠近施法者。持续时间:30秒。冷却时间:60秒。");
复制代码
所以在_Module\ModuleData\languages\CNs\ZZZF_Skill-CN.xml中,添加对应的ZZZF0023/ZZZF0024号翻译
  1.   <string id="ZZZF0023" text="嘲讽"/>
  2.                 <string id="ZZZF0024" text="嘲讽附近敌方单位,并持续大幅回复自身血量。受到嘲讽的单位会持续靠近施法者。消耗耐力:20。持续时间:30秒。冷却时间:60秒。"/>
复制代码

新增一个buff状态
1.新建一个类,继承自AgentBuff,并且完成构造函数/OnApply等方法(可以为空)
2.对于强化人物属性(比如增加移动速度)的buff,需要在ZZZF_SandboxAgentStatCalculateModel类中,UpdateHumanStats方法内增加代码,实现一下对应buff下的属性强化。
    注意,单纯的调用agent.AgentDrivenProperties去修改强化数值,只能在修改的那一帧生效,所以必须使用复写UpdateHumanStats的方法,让他持续生效
3.对于强化伤害的buff,需要在WOW_Script_AgentStatCalculateModel方法中添加代码(百分比增伤),或者在\Systems\NewDamageModel.cs中其他的伤害相关代码中调整(固定数值增伤)
4.附加一个buff给士兵的代码
  1.         public override bool Activate(Agent agent)
  2.         {

  3.             // 每次创建新的状态实例
  4.             List<AgentBuff> newStates = new List<AgentBuff> { new ZhanYiBuff(8f, agent), }; // 新实例
  5.             foreach (var state in newStates)
  6.             {
  7.                 state.TargetAgent = agent;
  8.                 agent.GetComponent<AgentSkillComponent>().StateContainer.AddState(state);
  9.             }
  10.             return true;

  11.         }
复制代码


士兵技能配置:
New_ZZZF\_Module\ModuleData\troop_skills.xml
<Troop id="commander_1">中,troopid为NPCCharacter中的id。
  1. <NPCCharacter
  2.                 id="imperial_veteran_infantryman"
  3.                 default_group="Infantry"
  4.                 level="21"
  5.                 name="{=yrGYZsQ7}Imperial Veteran Infantryman"
  6.                 occupation="Soldier"
  7.                 culture="Culture.empire">
复制代码
技能则是填入SkillFactory._skillRegistry字典中的字符串



屏幕截图 2025-04-01 155759.jpg
31.jpg
32.jpg
33.jpg



作者: oder007    时间: 2025-4-1 17:59
哇哦,是大佬,赞美大佬




欢迎光临 骑马与砍杀中文站论坛 (https://bbs.mountblade.com.cn/) Powered by Discuz! X3.4