曲曲机制

[!INFO] 实现类:shukaro.warptheory.handlers.WarpEventHandler + WarpHandler 概念来源:Thaumcraft 的「Warp(曲曲)」,本模组是其扩展

基本信息

玩家身上积累**曲曲值(warp)**后,会周期性随机触发「曲曲效果」—— 恶作剧式的异常事件(假雨、凋灵、物品栏打乱、假 Discord 提示音等)。

「曲曲」不是传送/空间理论,而是神秘学里的「扭曲/疯狂值」, 概念取自 Lovecraft 式与 Thaumcraft 的 Warp 设定。 模组名 WarpTheory 中的 “Theory” 指异常理论, 不是任何物理或空间理论。

触发条件

WarpEventHandler.livingUpdate(LivingEvent.LivingUpdateEvent):

if (!(e.entity instanceof EntityPlayer player)) return;
if (world.isRemote || player.ticksExisted <= 0) return;

boolean canApplyWarp = !player.isPotionActive(potionWarpWardID) && !wuss && !player.capabilities.isCreativeMode
        || WarpHandler.getUnavoidableCount(player) > 0;

if (!canApplyWarp || !ConfigHandler.allowWarpEffects) return;

三重豁免(任一成立即不触发):

豁免 来源
玩家有曲曲护盾药水 thaumcraft.common.config.Config.potionWarpWardID
wuss 模式 thaumcraft.common.config.Config.wuss(Thaumcraft 的调试模式)
玩家是创造模式 player.capabilities.isCreativeMode

但 WarpHandler.getUnavoidableCount(player) > 0 时强制绕过全部豁免 (运算符优先级:三个 && 先算,再 ||)。

⚠️ 直接 import static Thaumcraft 的配置字段 (Config.potionWarpWardID、Config.wuss)—— 这就是本模组 硬依赖 Thaumcraft 4.2.3.5+ 的根本原因。

触发概率:每 2000 tick 一次判定

int warpCounter = WarpHandler.Knowledge.getWarpCounter(player.getCommandSenderName());
if (ticks % 2000 == 0 && warpCounter > 0 && rand.nextInt(100) <= Math.sqrt(warpCounter)) {

2000 tick = 100 秒。判定条件:

  1. ticks % 2000 == 0 —— 每 100 秒一次机会
  2. warpCounter > 0 —— 该玩家有曲曲累积
  3. rand.nextInt(100) <= Math.sqrt(warpCounter) —— 概率为 sqrt(曲曲量)%

即曲曲值越高,触发越频繁,且是平方根增长(刻意压低斜率)。

有效曲曲值:三分法 + 护符减免

int effectiveWarp = (WarpHandler.getTotalWarp(player) * 2 + warpCounter) / 3;
effectiveWarp -= WarpHandler.faceplateReduction(player);
IWarpEvent queuedEvent = WarpHandler.queueOneEvent(player, effectiveWarp);
  • getTotalWarp(player) 是永久曲曲(来自物品/研究), warpCounter 是暂存曲曲(会随时间/事件消减);
  • 权重 2:1 偏向永久曲曲,整数除法向下取整;
  • faceplateReduction 是面纱(护符)减免,由 护符类物品 提供。

曲曲值消耗

int tempWarp = WarpHandler.getIndividualWarps(player)[2];
if (tempWarp > 0) {
    int cost = Math.min(queuedEvent.getCost(), tempWarp);
    WarpHandler.removeWarp(player, cost);
}

getIndividualWarps(player) 返回 3 元素数组,索引 [2] 是暂存曲曲。 消耗量取 min(效果代价, 现有暂存曲曲),即不会扣成负数。

IWarpEvent.getCost() 是 ceil(minWarp / 10.0),见 曲曲效果注册表。

队列模型

效果不是立即触发,而是入队:

  1. queueOneEvent(player, effectiveWarp) 按门槛筛选出符合的候选效果, 随机选一个入队(返回 null 表示无可用效果)。
  2. 每 20 tick(1 秒)以 rand.nextBoolean()(50%)出队一个执行:
if (ticks % 20 == 0 && rand.nextBoolean()) {
    IWarpEvent nextEvent = WarpHandler.dequeueEvent(player);
    ...
}

即效果触发有最多 1 秒的延迟,且队列天然削峰。

事件触发的其它订阅点

WarpEventHandler 还监听两个 LivingEvent 用于临时曲曲:

订阅方法 事件 用途
livingUpdate LivingEvent.LivingUpdateEvent 主循环(见上)
— LivingHurtEvent 受伤时可能累积曲曲
— LivingHealEvent 治疗时可能消减曲曲

配套接口 entity/IHurtable 与 IHealable 让本模组实体 (如 EntityDoppelganger)也能参与这套曲曲交互。

wussMode 配置

wussMode(ConfigHandler,默认 false)的注释是 "enables less expensive recipes"(启用更便宜的配方)。

它同时影响两处:

  1. 配方:WarpRecipes.init() 中 if (!ConfigHandler.wussMode) { … }, 开启后走另一套低成本配方分支(见 Warp 配方)。
  2. 曲曲:WarpEventHandler 直接 import 了 Thaumcraft 的 Config.wuss,两者是不同变量 —— 本模组的 wussMode 不会自动禁用曲曲效果,需靠 Thaumcraft 自己的 wuss 开关。

配置总开关

配置 字段 默认 作用
— ConfigHandler.allowWarpEffects ✅ 曲曲效果总开关
— ConfigHandler.allowGlobalWarpEffects ✅ 允许 isGlobal 效果
— ConfigHandler.allowMultiWarpEffects ✅ 允许一次触发多个效果
— ConfigHandler.allowServerKickWarpEffects ✅ 允许可能踢服的效果
— ConfigHandler.disableRebound — 关闭曲曲反弹
— ConfigHandler.permWarpMult — 永久曲曲倍率
— ConfigHandler.allowPermWarpRemoval ✅ 物品可否移除永久曲曲

逐项说明见 Warptheory 配置。

相关条目