
英雄核心 API
Hytale的RPG属性、战斗和进度框架。
HeroCore > https://github.com/HerotaleRPG/herocore/
HEROES RPG MOD 的必要依赖
Hytale 的 RPG 属性、战斗与成长框架。
HeroCore 是一个扩展 Hytale 原生 ECS(实体组件系统)的模式与公式库。它提供了主要属性、派生属性计算、多阶段伤害/治疗管线、状态效果、等级成长等功能——全部通过 Hytale 原生的 EntityStatMap、StaticModifier 和 ECS 事件系统来驱动。无需桥接类、无需并行的属性引擎、无需自定义事件总线。
版本: 0.2.0 服务端: Hytale 2026.02.17+ Java: 25 作者: Kainzo
目录
架构概览
HeroCorePlugin (JavaPlugin)
│
├── 模式层 ── HeroCore 拥有的定义
│ ├── RPGAttribute 枚举 62 个属性(主要 + 次要)
│ ├── DamageType 枚举 PHYSICAL, MAGICAL, FIRE, ICE 等
│ ├── HealType 枚举 SPELL, POTION, REGEN_TICK, PASSIVE, ENVIRONMENTAL
│ ├── DamageFlag 枚举 CRIT, DOT, AOE, MELEE, RANGED 等
│ └── CoreConfig 所有调节参数(伤害、治疗、派生、再生)
│
├── 数学层 ── 纯函数,可单元测试,无副作用
│ ├── AttributeDerivationFormulas 主要属性 → 次要属性加成数值
│ ├── DamageFormulas 抗性曲线,暴击判定,吸血
│ └── HealFormulas 治疗强度缩放,治疗暴击
│
├── ECS 组件 ── 在 setup() 中注册,存储在实体上
│ ├── HeroCoreStatsComponent 主要基础值 (STR/DEX/INT/FAITH/VIT/RES) 持久化
│ ├── HeroCoreProgressionComponent 等级,经验,升级所需经验 持久化
│ ├── CombatStateComponent 战斗状态标志 + dt 累积器 临时
│ └── StatusEffectIndexComponent 激活效果 ID + 剩余秒数 临时
│
├── ECS 系统 ── 全部继承原生 Hytale 系统类型
│ ├── HeroCoreSetupSystem HolderSystem — 确保实体添加时拥有组件
│ ├── AttributeDerivationSystem EntityTickingSystem — 写入 StaticModifiers (在 Recalculate 之前)
│ ├── CombatTimeoutSystem DelayedEntitySystem — 超时后退出战斗
│ └── StatusEffectTickSystem DelayedEntitySystem — 使计时效果过期
│
├── 伤害管线 ── EntityEventSystem 链 (SystemDependency 排序)
│ AttackDamageBonusSystem → FallDamageReductionSystem → ResistanceMitigationSystem
│ → CriticalHitSystem → LifestealSystem → MinimumDamageSystem → DamageApplicationSystem
│
├── 治疗管线 ── EntityEventSystem 链
│ HealingPowerScalingSystem → HealingReceivedBonusSystem → HealCritSystem
│
├── 注册表 ── 供下游插件使用的 API 门面
│ ├── LevelingRegistry 经验授予,等级查询,档案管理
│ ├── MobRegistry 生物/NPC 档案注册与查找
│ └── ZoneModifierRegistry 区域修饰器 (v0.3 计划)
│
└── 原生 Hytale (使用但不替换)
├── EntityStatMap 所有属性值的单一数据源
├── StaticModifier 所有修饰器的应用
├── RegeneratingValue 再生 (通过 EntityStatType JSON 资源配置)
├── BuilderCodec 组件持久化
└── CommandBuffer.invoke() ECS 事件调度
设计原则
- 无并行基础设施。 HeroCore 将
StaticModifier条目写入EntityStatMap。没有第二个属性容器,也没有在系统间同步数值的桥接。 - 运行时处处使用
Ref<EntityStore>。 UUID 仅用于持久化。所有方法、事件和系统传递的都是实时实体句柄。 - 所有系统均继承原生 Hytale 类型。
EntityTickingSystem、DelayedEntitySystem、EntityEventSystem、HolderSystem— 无自定义系统抽象。 - 纯数学运算与 ECS 接线分离。
DamageFormulas、HealFormulas、AttributeDerivationFormulas是静态纯函数。单元测试无需服务端实例。 - 所有持久化使用
BuilderCodec。 加入/退出事件时不使用 Gson 序列化。组件作为实体存储保存周期的一部分进行序列化。
插件生命周期
HeroCorePlugin 继承 JavaPlugin 并遵循标准 Hytale 模块模式:
| 阶段 | 执行内容 |
|---|---|
preLoad() |
从 mods/herocore/config.json 加载 CoreConfig(若无则回退到内置默认值) |
setup() |
通过 getEntityStoreRegistry() 注册全部 4 个组件、4 个 ECS 事件类型和所有系统 |
start() |
通过 HeroCoreStatTypes.update() 解析自定义属性类型索引并进行验证 |
shutdown() |
记录清理关闭日志 |
清单文件
{
"Group": "Herotale",
"Name": "Herocore",
"Version": "0.2.0",
"Main": "net.herotale.herocore.impl.HeroCorePlugin",
"IncludesAssetPack": true
}
ECS 组件
所有组件通过 HeroCoreComponentRegistry.registerComponents() 在 setup() 中注册。每个组件遵循标准模式:实现 Component<EntityStore>、拷贝构造函数、clone()、静态 ComponentType 句柄。
HeroCoreStatsComponent (持久化)
持有六个主要 RPG 属性的基础值。这些是 AttributeDerivationSystem 的输入。
| 字段 | 类型 | 描述 |
|---|---|---|
strength |
float |
物理伤害、挖掘速度、方块强度 |
dexterity |
float |
暴击率、攻击速度、闪避、移动速度 |
intelligence |
float |
法术强度、法力值、法术暴击、魔法抗性 |
faith |
float |
治疗强度、法力值、法力回复、治疗暴击、增益强度 |
vitality |
float |
最大生命值、生命回复、护甲、物理抗性 |
resolve |
float |
控制抗性、减益抗性、体力回复、威胁值 |
编解码键: HC_Strength、HC_Dexterity、HC_Intelligence、HC_Faith、HC_Vitality、HC_Resolve
HeroCoreProgressionComponent (持久化)
追踪玩家等级和经验值成长。
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
level |
int |
1 | 当前等级 |
currentXP |
float |
0 | 已累积的升级经验值 |
xpToNextLevel |
float |
100 | 下一次升级所需经验值 |
编解码键: HC_Level、HC_CurrentXP、HC_XPToNextLevel
CombatStateComponent (临时)
使用基于 dt 的计时(非挂钟时间)追踪实体是否处于战斗状态。通过 enterCombat() 重置,通过 tickElapsed(dt) 累积。
| 方法 | 描述 |
|---|---|
enterCombat() |
设置战斗状态,将计时器重置为 0 |
tickElapsed(float dt) |
累积自上次受伤以来的时间(仅在战斗状态时) |
isInCombat() |
战斗状态时返回 true |
getSecondsSinceLastDamage() |
自 enterCombat() 以来经过的秒数 |
StatusEffectIndexComponent (临时)
StatusEffectTickSystem 读取的轻量索引,用于使效果过期。实际的属性修改作为 StaticModifier 条目存储在 EntityStatMap 中。效果过期时,StatusEffectTickSystem 使用跟踪的 ModifierRef 列表自动移除所有关联的修饰器。
public static class EffectEntry {
public final int stacks;
public float remainingSeconds; // 每个滴答由 dt 递减
// 修饰器跟踪,用于过期时自动清理
public void trackModifier(int statIndex, String modifierKey);
public List<ModifierRef> getModifierRefs();
public record ModifierRef(int statIndex, String modifierKey) {}
}
| 方法 | 描述 |
|---|---|
addEffect(id, stacks, durationSeconds) |
注册一个新的效果 |
getEffect(id) |
通过 ID 获取 EffectEntry(用于在应用修饰器后调用 trackModifier()) |
removeEffect(id) |
通过 ID 移除效果 |
getActiveEffects() |
所有激活效果的映射表 |
属性系统
RPGAttribute 枚举
RPGAttribute 是所有 RPG 属性的权威分类。它定义了 62 个属性,涵盖多个类别:
| 类别 | 示例 |
|---|---|
| 主要属性 | STRENGTH、DEXTERITY、INTELLIGENCE、FAITH、VITALITY、RESOLVE |
| 战斗 — 物理 | MAX_HEALTH、ARMOR、ATTACK_DAMAGE、ATTACK_SPEED、CRIT_CHANCE、LIFESTEAL |
| 战斗 — 魔法 | SPELL_POWER、SPELL_CRIT_CHANCE、MAGIC_PENETRATION、MAGIC_RESIST |
| 元素 | ELEMENTAL_DAMAGE_FIRE、ELEMENTAL_RESIST_ICE、ICE_RESISTANCE_PERCENT 等 |
| 治疗 | HEALING_POWER、HEALING_RECEIVED_BONUS、HEAL_CRIT_CHANCE |
| 资源 | MAX_MANA、MAX_STAMINA、MANA_REGEN、HEALTH_REGEN |
| 机动 | MOVE_SPEED、JUMP_HEIGHT、MINING_SPEED |
| 成长 | XP_GAIN_MULTIPLIER、RARE_DROP_CHANCE |
HeroCoreStatTypes
在运行时从 EntityStatType JSON 资源解析自定义 RPG 属性类型索引。遵循 DefaultEntityStatTypes 的模式。
// 在 start() 之后,这些方法返回有效的 int 索引
HeroCoreStatTypes.getCritChance(); // herocore:crit_chance
HeroCoreStatTypes.getAttackDamage(); // herocore:attack_damage
HeroCoreStatTypes.getSpellPower(); // herocore:spell_power
HeroCoreStatTypes.getPhysicalResistance(); // herocore:physical_resistance
HeroCoreStatTypes.getMagicResist(); // herocore:magic_resist
HeroCoreStatTypes.getAttackSpeed(); // herocore:attack_speed
HeroCoreStatTypes.getMoveSpeed(); // herocore:move_speed
HeroCoreStatTypes.getMiningSpeed(); // herocore:mining_speed
HeroCoreStatTypes.getHealingPower(); // herocore:healing_power
HeroCoreStatTypes.getCritDamageMultiplier(); // herocore:crit_damage_multiplier
// 通过资源 ID 字符串动态查找
HeroCoreStatTypes.getIndex("herocore:lifesteal");
// 辅助方法:从实体引用读取属性值
float value = HeroCoreStatTypes.getStatValue(entityRef, statIndex);
HeroCoreModifiers
HeroCore 使用的所有修饰器键都是 HeroCoreModifiers 中的常量。修饰器调用中没有内联字符串。
// 派生属性(由 AttributeDerivationSystem 写入)
HeroCoreModifiers.DERIVED_MAX_HEALTH // "HC_derived_max_health"
HeroCoreModifiers.DERIVED_CRIT_CHANCE // "HC_derived_crit_chance"
HeroCoreModifiers.DERIVED_SPELL_POWER // "HC_derived_spell_power"
HeroCoreModifiers.DERIVED_ATTACK_DAMAGE // "HC_derived_attack_damage"
HeroCoreModifiers.DERIVED_MOVE_SPEED // "HC_derived_move_speed"
HeroCoreModifiers.DERIVED_ARMOR // "HC_derived_armor"
// ... 共 30+ 个常量
// 动态键构建器
HeroCoreModifiers.effect("burn", "health"); // "HC_effect_burn_health"
HeroCoreModifiers.gear("chest_iron", "armor"); // "HC_gear_chest_iron_armor"
HeroCoreModifiers.derived("custom_stat"); // "HC_derived_custom_stat"
属性派生
工作原理
AttributeDerivationSystem 是一个 EntityTickingSystem,每帧运行。它从 HeroCoreStatsComponent 读取六个主要属性,并将派生属性加成作为 StaticModifier 条目写入实体的 EntityStatMap。
它实现了 EntityStatsSystems.StatModifyingSystem(标记接口),并通过 SystemDependency 声明 BEFORE EntityStatsSystems.Recalculate。这确保了:
- HeroCore 将派生修饰器写入
EntityStatMap - Hytale 原生的
Recalculate系统处理所有修饰器 - 最终计算值可供游戏系统读取
下游的 stat-modifying 系统也必须声明 BEFORE EntityStatsSystems.Recalculate 以避免竞争条件:
@Nonnull
@Override
public Set<Dependency<EntityStore>> getDependencies() {
return Set.of(
new SystemDependency<>(Order.BEFORE, EntityStatsSystems.Recalculate.class)
);
}
HeroCoreStatsComponent (主要基础值)
│
▼
AttributeDerivationFormulas.computeDerived() ← 纯数学运算
│
▼
EntityStatMap.putModifier() ← 写入命名修饰器
│
▼
EntityStatsSystems.Recalculate ← 原生 Hytale (在之后运行)
所有修饰器使用 ADDITIVE 叠加到 ModifierTarget.MAX 上。 这是有意为之——基于百分比的属性应叠加相加。资源的 max 字段负责上限处理。
派生公式
| 派生属性 | 公式 | 来源属性 |
|---|---|---|
| 物理抗性 | (VIT + RES) / 2 |
活力,意志 |
| 法术强度 | (INT + FAITH) / 2 |
智力,信仰 |
| 暴击率 | min(1.0, DEX / 200) |
敏捷 |
| 暴击伤害倍率 | 1.5 + (STR + INT) / 500 |
力量,智力 |
| 攻击伤害 | STR / 10 |
力量 |
| 移动速度 | 1.0 + DEX / 500 |
敏捷 |
| 攻击速度 | 1.0 + DEX / 300 |
敏捷 |
| 魔法抗性 | INT / 10 |
智力 |
| 治疗强度 | FAITH / 10 |
信仰 |
| 挖掘速度 | 1.0 + STR / 500 |
力量 |
这些公式位于 AttributeDerivationFormulas.computeDerived() 中——一个纯静态函数。所有公式都有 13 个单元测试覆盖。
伤害管线
伤害流经由 SystemDependency 排序的 EntityEventSystem<EntityStore, HeroCoreDamageEvent> 实现链。每个阶段从 EntityStatMap 读取属性值并修改事件的 modifiedAmount。
管线阶段(按执行顺序)
| # | 系统 | 功能 |
|---|---|---|
| 1 | AttackDamageBonusSystem |
按攻击者的 attack_damage 属性缩放伤害 |
| 2 | FallDamageReductionSystem |
按受害者的 fall_damage_reduction 属性减少坠落伤害(仅对 DamageType.FALL 生效——跳过所有其他伤害类型)。HeroCore 新增——不在基础重构指南管线中。通过 SystemDependency 声明 AFTER AttackDamageBonusSystem。 |
| 3 | ResistanceMitigationSystem |
应用元素/魔法抗性(非物理抗性——那是原生系统处理的) |
| 4 | CriticalHitSystem |
从 crit_chance 判定暴击,乘以 crit_damage_multiplier |
| 5 | LifestealSystem |
按伤害的 lifesteal % 治疗攻击者(派发 HeroCoreHealEvent) |
| 6 | MinimumDamageSystem |
强制执行可配置的最小伤害下限 |
| 7 | DamageApplicationSystem |
通过 subtractStatValue() 将最终伤害写入 EntityStatMap |
HeroCoreDamageEvent
public class HeroCoreDamageEvent extends CancellableEcsEvent {
@Nullable Ref<EntityStore> attacker; // null = 环境伤害
DamageType damageType; // PHYSICAL, FIRE 等
float rawAmount; // 原始伤害
float modifiedAmount; // 当前值(由管线修改)
boolean isCrit; // 由 CriticalHitSystem 设置
}
派发伤害
从任何可以访问 CommandBuffer 的 ECS 系统:
// 向目标实体派发伤害——流经整个管线
cb.invoke(targetRef, new HeroCoreDamageEvent(attackerRef, DamageType.PHYSICAL, 25f));
// 环境伤害(无攻击者)
cb.invoke(targetRef, new HeroCoreDamageEvent(null, DamageType.FIRE, 10f));
CommandBuffer.invoke() 是同步的——事件会按顺序流过所有管线阶段。
取消伤害
任何管线阶段(或下游插件的系统)都可以取消:
event.setCancelled(true); // 所有后续阶段都会检查 isCancelled()
治疗管线
与伤害模式相同。三个 EntityEventSystem<EntityStore, HeroCoreHealEvent> 阶段:
| # | 系统 | 功能 |
|---|---|---|
| 1 | HealingPowerScalingSystem |
按治疗者的 healing_power 属性缩放治疗量(适用于 SPELL/PASSIVE 治疗,可选 REGEN_TICK) |
| 2 | HealingReceivedBonusSystem |
应用目标的 healing_received_bonus 属性 |
| 3 | HealCritSystem |
从 heal_crit_chance 判定治疗暴击,乘以 heal_crit_multiplier |
HeroCoreHealEvent
public class HeroCoreHealEvent extends CancellableEcsEvent {
@Nullable Ref<EntityStore> healer;
HealType healType; // SPELL, POTION, REGEN_TICK, PASSIVE, ENVIRONMENTAL
float rawAmount;
float modifiedAmount;
boolean isCrit;
}
派发治疗
cb.invoke(targetRef, new HeroCoreHealEvent(healerRef, HealType.SPELL, 50f));
战斗状态与超时
CombatStateComponent
实体在受到伤害时进入战斗状态(DamageApplicationSystem 调用 combat.enterCombat())。计时器通过世界滴答 dt 累积——不依赖挂钟时间。
CombatTimeoutSystem
一个 DelayedEntitySystem,每 0.5 秒触发一次(有意比 StatusEffectTickSystem 的 0.25 秒慢——战斗超时不需亚秒级精度,0.5 秒可减少不必要的迭代)。遍历拥有 CombatStateComponent 的实体,检查 secondsSinceLastDamage > combatTimeoutSeconds(可配置,默认 8.0 秒,来自配置)。超时到时:
- 设置
inCombat = false - 通过
cb.invoke()派发CombatExitEvent——下游插件可以响应此事件
CombatExitEvent
public class CombatExitEvent extends EcsEvent {
// 标记事件——无字段。战斗超时到期时派发。
}
状态效果
效果工作方式
- 应用: 将
StaticModifier条目写入EntityStatMap,在StatusEffectIndexComponent中记录效果,并调用trackModifier()注册每个修饰器以便自动清理 - 滴答:
StatusEffectTickSystem每 0.25 秒将remainingSeconds减去dt(有意设快——状态效果需要亚秒级精度) - 过期: 当
remainingSeconds <= 0时,StatusEffectTickSystem从EntityStatMap中移除所有追踪的修饰器(通过ModifierRef列表),并移除索引条目。滴答系统拥有完整的清理权——调用者只需在应用时调用trackModifier()
应用效果(下游代码)
// 写入属性修饰器
EntityStatMap statMap = store.getComponent(ref, EntityStatsModule.get().getEntityStatMapComponentType());
String modKey = HeroCoreModifiers.effect("burn", "health_regen");
statMap.putModifier(healthRegenIndex, modKey,
new StaticModifier(ModifierTarget.MAX, CalculationType.ADDITIVE, -5f));
// 在索引中记录以便自动过期
StatusEffectIndexComponent index = store.getComponent(ref, StatusEffectIndexComponent.getComponentType());
index.addEffect("burn", 1, 10f); // 1 层,10 秒
// 注册修饰器以便过期时自动清理
StatusEffectIndexComponent.EffectEntry entry = index.getEffect("burn");
entry.trackModifier(healthRegenIndex, modKey);
// StatusEffectTickSystem 将在效果过期时移除该修饰器
StatusEffectDefinition (API 数据记录)
// 在 api/status/StatusEffect.java 中——构建器模式
StatusEffect effect = StatusEffect.builder()
.id("herocore:burn")
.durationSeconds(5f) // 秒——与基于 dt 的 ECS 计时一致
.source("fire_trap")
.stacks(3)
.build();
升级与成长
经验值曲线
HeroCore 通过 XpCurve 提供三种经验值曲线实现:
| 类型 | 工厂方法 | 描述 |
|---|---|---|
| 指数型 | XpCurve.exponential(baseXp, growthRate) |
标准 RPG 曲线 |
| 线性型 | XpCurve.linear(xpPerLevel) |
每级固定经验值 |
| 离散型 | XpCurve.discrete(long[] thresholds) |
自定义阈值 |
通过 XpCurveFactory 提供的预设:
XpCurveFactory.standard()— 基数 100,增长率 1.15XpCurveFactory.fast()— 基数 50,增长率 1.10XpCurveFactory.slow()— 基数 200,增长率 1.25XpCurveFactory.flatCurve()— 每级 1000 经验值
LevelingProfile
LevelingProfile profile = LevelingProfile.builder()
.id("combat")
.maxLevel(60)
.xpCurve(XpCurve.exponential(100, 1.15))
.build();
LevelingRegistry
注册档案和授予经验值:
LevelingRegistry reg = HeroCore.get().getLevelingRegistry();
reg.register(profile);
// 在具有 Ref、Store 和 CommandBuffer 访问权限的 ECS 系统中:
reg.grantXP(entityRef, store, cb, "combat", 150.0, XPSource.KILL);
int level = reg.getLevel(entityRef, store, "combat");
等级事件
// EcsEvent——通过 ECS 事件系统派发
public class LevelUpEvent extends EcsEvent {
int oldLevel, newLevel;
}
public class LevelDownEvent extends EcsEvent {
int oldLevel, newLevel;
}
当经验值获得导致实体计算等级提升时(通过 LevelingRegistry.grantXP())派发 LevelUpEvent。当通过 LevelingRegistry.setXP() 明确将经验值设低,且重新计算的等级低于先前等级时,派发 LevelDownEvent。两个事件都携带旧等级和新等级值。
配置
配置从 mods/herocore/config.json 加载。如果该文件不存在,则从内置的 hero-core-defaults.json 复制默认值。
配置段
| 段 | 关键字段 |
|---|---|
modifierStacking |
maxPercentAdditive、multiplicativeCap |
damage |
critDamageBaseMultiplier(默认 2.0)、minimumDamage(默认 1.0)、maxResistanceReduction(默认 0.9) |
heal |
healCritBaseMultiplier、healingPowerScalesRegenTick、healingPowerScalesPassive |
resourceRegen |
tickIntervalSeconds(默认 2.0)、outOfCombatBonusMultiplier、combatTimeoutSeconds(默认 8.0) |
leveling |
defaultMaxLevel(60)、sourceWeights(每个 XPSource 的倍率) |
attributeDerivation |
每个属性的派生系数(活力、力量、敏捷、智力、信仰、意志) |
defenseDerivation |
每个伤害类型的抗性派生系数 |
Heroes RPG Mod 实现指南
本节是一个实用清单,用于将 HeroCore 接入完整的 RPG Mod:升级与经验值、主要属性、派生/次要属性以及装备集成。
1)升级与经验值
- 定义一个或多个
LevelingProfile条目(战斗、制作、采集等)。 - 在插件
setup()或start()期间在LevelingRegistry中注册档案。 - 通过
LevelingRegistry.grantXP()从游戏事件中授予经验值。
LevelingRegistry leveling = HeroCore.get().getLevelingRegistry();
leveling.register(LevelingProfile.builder()
.id("combat")
.maxLevel(60)
.xpCurve(XpCurve.exponential(100, 1.15))
.build());
// 在具有 Store + CommandBuffer 的 ECS 系统中颁发经验值
leveling.grantXP(entityRef, store, cb, "combat", 120.0, XPSource.KILL);
通过 ECS 事件响应成长:
reg.registerSystem(new EntityEventSystem<EntityStore, LevelUpEvent>(LevelUpEvent.class) {
@Override
public Query<EntityStore> getQuery() {
return HeroCoreStatsComponent.getComponentType();
}
@Override
protected void handle(int index, ArchetypeChunk<EntityStore> chunk,
Store<EntityStore> store, CommandBuffer<EntityStore> cb,
LevelUpEvent event) {
HeroCoreStatsComponent stats = chunk.getComponent(index, HeroCoreStatsComponent.getComponentType());
stats.setStrength(stats.getStrength() + 1f);
stats.setVitality(stats.getVitality() + 2f);
}
});
2)主要属性与次要属性
- 主要属性 位于
HeroCoreStatsComponent中(STR/DEX/INT/FAITH/VIT/RES)。 - 次要属性 由
AttributeDerivationSystem每帧派生并写入EntityStatMap。 - 派生值由
AttributeDerivationFormulas计算,并作为StaticModifier条目应用。
如果你修改主要属性,不要手动重新计算次要属性。下一个滴答将更新修饰器:
HeroCoreStatsComponent stats = store.getComponent(ref, HeroCoreStatsComponent.getComponentType());
stats.setDexterity(stats.getDexterity() + 5f);
读取次要属性始终通过 EntityStatMap:
EntityStatMap statMap = store.getComponent(ref, EntityStatsModule.get().getEntityStatMapComponentType());
int critIdx = HeroCoreStatTypes.getCritChance();
float critChance = statMap.get(critIdx).get();
3)装备、物品栏与物品事件
HeroCore 不直接实现物品栏或装备事件。使用 Hytale 的物品栏或装备事件(或你自己的 Mod 的物品系统),并将其转换为属性修饰器。
推荐模式:
- 监听物品装备/卸下或物品栏变更事件(在 HeroCore 外部)。
- 使用
HeroCoreModifiers.gear()键应用或移除修饰器。 - 如果需要,将任何装备状态存储在你自己的组件中,而不是 HeroCore 中。
// 示例:应用胸甲护甲加成
String key = HeroCoreModifiers.gear("chestplate_iron", "armor");
int armorIdx = HeroCoreStatTypes.getPhysicalResistance();
statMap.putModifier(armorIdx, key,
new StaticModifier(Modifier.ModifierTarget.MAX, StaticModifier.CalculationType.ADDITIVE, 12f));
// 卸下时移除
statMap.removeModifier(armorIdx, key);
如果你的项目已经有物品栏事件层,这就是将物品转换为属性效果的桥接点。
下游集成指南
依赖声明
在你的下游插件的 manifest.json 中:
{
"Dependencies": {
"Herotale:Herocore": "*"
}
}
读取属性
所有属性都在 EntityStatMap 中。HeroCore 提供属性索引解析器:
// 从实体读取 HeroCore 定义的属性
EntityStatMap stats = store.getComponent(ref, EntityStatsModule.get().getEntityStatMapComponentType());
int critIdx = HeroCoreStatTypes.getCritChance();
float critChance = stats.get(critIdx).get(); // 0.0–1.0
// 读取原生 Hytale 属性
int healthIdx = DefaultEntityStatTypes.getHealth();
float health = stats.get(healthIdx).get();
// 便捷辅助方法
float value = HeroCoreStatTypes.getStatValue(ref, HeroCoreStatTypes.getSpellPower());
拦截伤害管线
使用 SystemDependency 注册一个 EntityEventSystem,将你的逻辑插入现有阶段之间:
@Override
protected void setup() {
var reg = getEntityStoreRegistry();
reg.registerSystem(new EntityEventSystem<EntityStore, HeroCoreDamageEvent>(HeroCoreDamageEvent.class) {
@Override
public Query<EntityStore> getQuery() {
// 返回一个匹配拥有 HeroCoreStatsComponent 的实体的查询
return HeroCoreStatsComponent.getComponentType();
}
@Override
public Set<Dependency<EntityStore>> getDependencies() {
return Set.of(
new SystemDependency<>(Order.AFTER, CriticalHitSystem.class),
new SystemDependency<>(Order.BEFORE, LifestealSystem.class)
);
}
@Override
protected void handle(int index, ArchetypeChunk<EntityStore> chunk,
Store<EntityStore> store, CommandBuffer<EntityStore> cb,
HeroCoreDamageEvent event) {
if (event.isCancelled()) return;
// 你的自定义伤害修改逻辑在此
// 例如:特定职业的伤害加成、元素交互
}
});
}
响应升级
reg.registerSystem(new EntityEventSystem<EntityStore, LevelUpEvent>(LevelUpEvent.class) {
@Override
public Query<EntityStore> getQuery() {
return HeroCoreStatsComponent.getComponentType();
}
@Override
protected void handle(int index, ArchetypeChunk<EntityStore> chunk,
Store<EntityStore> store, CommandBuffer<EntityStore> cb,
LevelUpEvent event) {
HeroCoreStatsComponent rpg = chunk.getComponent(index, HeroCoreStatsComponent.getComponentType());
// 在升级时缩放属性——派生系统将在下一滴答中获取更改
rpg.setVitality(20f + event.getNewLevel() * 2f);
rpg.setStrength(15f + event.getNewLevel() * 1.5f);
}
});
响应战斗退出
reg.registerSystem(new EntityEventSystem<EntityStore, CombatExitEvent>(CombatExitEvent.class) {
@Override
public Query<EntityStore> getQuery() {
// 匹配拥有 CombatStateComponent 的实体
return CombatStateComponent.getComponentType();
}
@Override
protected void handle(int index, ArchetypeChunk<EntityStore> chunk,
Store<EntityStore> store, CommandBuffer<EntityStore> cb,
CombatExitEvent event) {
// 实体离开战斗——触发脱离战斗效果、UI 变更等
}
});
修改主要属性
直接写入 HeroCoreStatsComponent。AttributeDerivationSystem 会在下一个滴答自动重新计算派生修饰器:
HeroCoreStatsComponent stats = store.getComponent(ref, HeroCoreStatsComponent.getComponentType());
stats.setStrength(stats.getStrength() + 5f);
// 下一滴答:AttributeDerivationSystem 将更新后的修饰器写入 EntityStatMap
写入自定义修饰器
使用 HeroCoreModifiers 键约定以确保命名空间安全:
EntityStatMap statMap = store.getComponent(ref, EntityStatsModule.get().getEntityStatMapComponentType());
int critIdx = HeroCoreStatTypes.getCritChance();
// 应用修饰器(使用你的插件前缀命名空间)
// Hytale API:putModifier(int statIndex, String key, Modifier modifier)
statMap.putModifier(critIdx, "myplugin:elixir_crit_boost",
new StaticModifier(Modifier.ModifierTarget.MAX, StaticModifier.CalculationType.ADDITIVE, 0.1f));
// 稍后移除
// Hytale API:removeModifier(int statIndex, String key)
statMap.removeModifier(critIdx, "myplugin:elixir_crit_boost");
**关于
putModifier参数顺序的说明:
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。