骑马与砍杀中文站论坛
标题:
骑砍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()
核心代码
// 切换游戏状态
var inventoryState = Game.Current.GameStateManager.CreateState<SkillInventoryState>();
inventoryState.InitializeLogic(_inventoryLogic);
Game.Current.GameStateManager.PushState(inventoryState, 0);
复制代码
界面代码:GauntletSkillScreen
核心代码
this._dataSource = new SPSkillVM(inventoryLogic, false/*mission != null && mission.DoesMissionRequireCivilianEquipment*/, new Func<WeaponComponentData, ItemObject.ItemUsageSetFlags>(this.GetItemUsageSetFlag), this.GetFiveStackShortcutkeyText(), this.GetEntireStackShortcutkeyText()); // 初始化数据源
this._gauntletLayer = new GauntletLayer(15, "GauntletLayer", true) // 创建 Gauntlet 层
base.AddLayer(this._gauntletLayer); // 添加层
this._gauntletMovie = this._gauntletLayer.LoadMovie("Inventory", this._dataSource); // 加载电影(界面)
复制代码
界面数据代码:SPSkillVM
界面Xml直接使用游戏本身的物品界面Inventory
新增一个技能的流程:
1.新建一个类,继承SkillBase,然后完成构造方法/Activate方法/CheckCondition方法。
[spoiler=嘲讽代码]
using New_ZZZF.Systems;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.CampaignSystem.Extensions;
using TaleWorlds.Core;
using TaleWorlds.Engine;
using TaleWorlds.InputSystem;
using TaleWorlds.Library;
using TaleWorlds.MountAndBlade;
namespace New_ZZZF
{
internal class ChaoFeng : SkillBase
{
public ChaoFeng()
{
SkillID = "ChaoFeng"; // 必须唯一
Type = SkillType.MainActive; // 类型必须明确
Cooldown = 2; // 冷却时间(秒)
ResourceCost = 0f; // 消耗
Text = new TaleWorlds.Localization.TextObject("{=ZZZF0023}ChaoFeng");
Difficulty = null;// new List<SkillDifficulty> { new SkillDifficulty(50, "跑动"), new SkillDifficulty(5, "耐力") };//技能装备的需求
Description = new TaleWorlds.Localization.TextObject("{=ZZZF0024}嘲讽附近敌方单位,并持续大幅回复自身血量。受到嘲讽的单位会持续靠近施法者。持续时间:30秒。冷却时间:60秒。");
}
public override bool Activate(Agent agent)
{
// 每次创建新的状态实例
List<AgentBuff> newStates = new List<AgentBuff> { new ChaoFengBuffApplyToSelf(30f, agent), }; // 新实例
foreach (var state in newStates)
{
state.TargetAgent = agent;
agent.GetComponent<AgentSkillComponent>().StateContainer.AddState(state);
}
List<Agent> values= Script.GetTargetedInRange(agent, agent.GetEyeGlobalPosition(),30);
if (values!=null&&values.Count>0)
{
foreach (var item in values)
{
// 每次创建新的状态实例
newStates = new List<AgentBuff> { new ChaoFengBuffApplyToEnemy(30f, agent), }; // 新实例
foreach (var state in newStates)
{
state.TargetAgent = item;
item.GetComponent<AgentSkillComponent>().StateContainer.AddState(state);
}
}
return true;
}
return false;
}
public override bool CheckCondition(Agent caster)
{
SkillSystemBehavior.ActiveComponents.TryGetValue(caster.Index, out var agentSkill);
if (agentSkill == null) { return false; }
if (caster.Health/ agentSkill.MaxHP<=0.5f)
{
return true;
}
List<Agent> FoeList = Script.GetTargetedInRange(caster, caster.GetEyeGlobalPosition(), 30);
List<Agent> FriendList = Script.GetTargetedInRange(caster, caster.GetEyeGlobalPosition(), 30,true);
if (FoeList.Count>0)
{
if (FoeList.Count > 5)
{
return true;
}
else if (FoeList.Count>2&&FriendList.Count>0)
{
return true;
}
}
// 默认条件:Agent存活且非坐骑
return false;
}
public class ChaoFengBuffApplyToEnemy : AgentBuff
{
private float _timeSinceLastTick;
public ChaoFengBuffApplyToEnemy(float duration, Agent source)
{
StateId = "ChaoFengBuffApplyToEnemy";
Duration = duration;
SourceAgent = source;
_timeSinceLastTick = 0; // 新增初始化
}
public override void OnApply(Agent agent)
{
agent.SetTargetAgent(SourceAgent);
agent.SetTargetPosition(SourceAgent.Position.AsVec2);
}
public override void OnUpdate(Agent agent, float dt)
{
SkillSystemBehavior.ActiveComponents.TryGetValue(this.SourceAgent.Index, out var agentSkillComponent);
if (agentSkillComponent == null) { return; }
// 累积时间
_timeSinceLastTick += dt;
//每秒刷一次状态
if (_timeSinceLastTick >= 1f)
{
agent.SetTargetAgent(SourceAgent);
agent.SetTargetPosition(SourceAgent.Position.AsVec2);
_timeSinceLastTick -= 1f; // 重置计时器
}
}
public override void OnRemove(Agent agent)
{
agent.ClearTargetFrame();
agent.InvalidateTargetAgent();
}
}
public class ChaoFengBuffApplyToSelf : AgentBuff
{
private float _timeSinceLastTick;
public ChaoFengBuffApplyToSelf(float duration, Agent source)
{
StateId = "ChaoFengBuffApplyToSelf";
Duration = duration;
SourceAgent = source;
_timeSinceLastTick = 0; // 新增初始化
}
public override void OnApply(Agent agent)
{
}
public override void OnUpdate(Agent agent, float dt)
{
SkillSystemBehavior.ActiveComponents.TryGetValue(this.SourceAgent.Index, out var agentSkillComponent);
if (agentSkillComponent == null) { return; }
// 累积时间
_timeSinceLastTick += dt;
//每秒刷一次状态
if (_timeSinceLastTick >= 1f)
{
ZZZF_SandboxAgentStatCalculateModel zZZF_SandboxAgentStatCalculate = MissionGameModels.Current.AgentStatCalculateModel as ZZZF_SandboxAgentStatCalculateModel;
if (zZZF_SandboxAgentStatCalculate != null)
{
zZZF_SandboxAgentStatCalculate._dt = dt;
agent.Health += (agentSkillComponent.MaxHP - agent.Health) * 0.5f;
}
_timeSinceLastTick -= 1f; // 重置计时器
}
}
public override void OnRemove(Agent agent)
{
}
}
}
}
复制代码
[/spoiler]
2.在SkillFactory类的_skillRegistry字典中,添加这个新技能的信息。现在,这个技能就一个可以在打开技能界面时被看到了。
[spoiler=_skillRegistry]
// 技能注册表:技能ID -> 技能实例(硬编码参数)
public static readonly Dictionary<string, SkillBase> _skillRegistry = new Dictionary<string, SkillBase>
{
//空技能
{"NullSkill",new NullSkill() },
//// 主主动技能
{ "JianQi", new JianQi() } , // 剑气斩
{ "ConeOfArrows", new ConeOfArrows() } , // 多重射击
{ "DaoShan", new DaoShan() } , // 刀扇
{"ShadowStep",new ShadowStep() },//暗影步
{"DaDiJianTa",new DaDiJianTa() },
{"ZhanYi",new ZhanYi() },
{"JueXing",new JueXing() },
{"TianQi",new TianQi() },
{"GuWu",new GuWu() },
{"ChaoFeng",new ChaoFeng() },
{"DunWu",new DunWu() },
{"FengBaoZhiLi",new FengBaoZhiLi() },
{"ZhanHao",new ZhanHao() },
{"WeiYa",new WeiYa() },
{"JingXia",new JingXia() },
{"YingXiongZhuFu",new YingXiongZhuFu() },
{"KongNueCiFu",new KongNueCiFu() },
{"NaGouCiFu",new NaGouCiFu() },
{"JianQiCiFu",new JianQiCiFu() },
//// 副主动技能
{ "Rush", new Rush() }, // Rush
{"MagicShoot",new MagicShoot() },
//// 被动技能
{"Roll",new Roll() },
//// 法术
{ "Fireball", new FireballSkill() }, // 火球术
{ "lingmashaodi", new lingmashaodi() }, //
{ "HuiJianYuanZhen", new HuiJianYuanZhen() }, // 辉剑圆阵
//// 战技
//{ "ShieldBash", new ShieldBashSkill() }, // 盾牌猛击
};
复制代码
[/spoiler]
3.完成技能文本的翻译部分。
比如嘲讽的文本是
Text = new TaleWorlds.Localization.TextObject("{=ZZZF0023}ChaoFeng");
Description = new TaleWorlds.Localization.TextObject("{=ZZZF0024}嘲讽附近敌方单位,并持续大幅回复自身血量。受到嘲讽的单位会持续靠近施法者。持续时间:30秒。冷却时间:60秒。");
复制代码
所以在_Module\ModuleData\languages\CNs\ZZZF_Skill-CN.xml中,添加对应的
ZZZF0023/
ZZZF0024号翻译
<string id="ZZZF0023" text="嘲讽"/>
<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给士兵的代码
public override bool Activate(Agent agent)
{
// 每次创建新的状态实例
List<AgentBuff> newStates = new List<AgentBuff> { new ZhanYiBuff(8f, agent), }; // 新实例
foreach (var state in newStates)
{
state.TargetAgent = agent;
agent.GetComponent<AgentSkillComponent>().StateContainer.AddState(state);
}
return true;
}
复制代码
士兵技能配置:
New_ZZZF\_Module\ModuleData\troop_skills.xml
<Troop id="commander_1">中,troopid为NPCCharacter中的id。
<NPCCharacter
id="imperial_veteran_infantryman"
default_group="Infantry"
level="21"
name="{=yrGYZsQ7}Imperial Veteran Infantryman"
occupation="Soldier"
culture="Culture.empire">
复制代码
技能则是填入SkillFactory._skillRegistry字典中的字符串
作者:
oder007
时间:
2025-4-1 17:59
哇哦,是大佬,赞美大佬
欢迎光临 骑马与砍杀中文站论坛 (https://bbs.mountblade.com.cn/)
Powered by Discuz! X3.4