PEAK
You are viewing a potentially older version of this package. View Latest Version
Install with App

Details

Date Uploaded
2 days ago
Downloads
46
Size
127KB

Ping Point Use Item

PEAK · Version 2.6.13

English

Hold Z to choose one of eight items, then use a successful native Ping (default middle mouse, or your remapped/controller binding) to spawn it at the marked point or launch a Frisbee toward a nearby target. Each successful Ping can also add a native networked music-trail batch with the vanilla bugle sound. Cloud-platform rescue takes priority when a nearby falling player and platform budget qualify. Seven items have independent Cooking / Collision settings. Choose Unlimited (default) or Limited usage; Frisbee is always unlimited.

Installation

  • Install BepInExPack_PEAK first. Required dependency: BepInEx-BepInExPack_PEAK-5.4.75301.
  • Install this package with a mod manager, or place PingPointUseItem.dll in your active PEAK BepInEx profile's BepInEx/plugins/PingPointUseItem/ folder.
  • Before upgrading, remove every old InstantCookExplosion.dll from the active profile's plugins folder, along with its old PDB/deps files. Do not load old and new plugins together.
  • Launch the game to create BepInEx/config/rua.PingPointUseItem.cfg. New defaults: enabled, Cure-All selected, and Unlimited. New Music Trail / Spacing Meters configs default to 8; an existing user value, including 5, is retained and is not overwritten. Removed Music Trail speed/lifetime keys are ignored if they remain in an existing config; the plugin does not rewrite the game config.
  • SymbioticGhost and SenseOfDirection integrations are optional, not required dependencies.

Controls

  1. Hold Z, point at an available wheel item, and release Z to save the selection for the next Ping.
  2. Aim at a surface and use the game's Ping binding. Generation follows a successful native Ping hit and its original cooldown; there is no separate spawning ray, Ping RPC or cooldown.
  3. Counts are centered directly on each icon. Unlimited shows ∞ (INF if the font lacks the symbol); exhausted finite items cannot be selected.

All character states are eligible without a fullyConscious/spectator permission gate, and climbing no longer blocks the item wheel. An active valid Character.localCharacter with data, its bound PointPinger and both local Photon owners are still required, along with room, focus, blocking-menu and native/custom-wheel guards. Missing GUI wheel references during loading fail closed. Disabled-plugin and nonlocal native Ping behavior is unchanged.

Music Trail

  • After the existing successful Ping frame guard, the plugin captures Camera.main.transform.position and the exact native Ping hit.point. Let L be the captured camera-to-Ping distance and S be the current user-configured Spacing Meters value; new configs default to 8 m, while existing values such as 5 are not overwritten. Music may use only the camera-relative path [2, L-S] measured toward the native Ping. Define length = L-S-2: if length < 0, skip music only; if length == 0, emit one point at distance 2 m; if length > 0, sample every S from distance 2 through L-S, including eligible bounds and deduplicating coincident points. Short paths are not clamped to the native Ping hit, and the exact native Ping hit is never sampled; the upper bound is L-S.
  • One original network resource 0_Items/bugle_magic is spawned per sampled endpoint, up to the performance cap of 32 instances. When more than 32 samples are eligible, retain the first 16 head samples and last 16 tail samples, with no additional clamp to the Ping hit. Fixed endpoints are captured once; the selected item/rescue behavior remains independent. Music busy blocks only another music batch, and remains busy until the whole batch and each horn's cleanup deadline are finished. All other item/rescue and music-busy rules remain unchanged.
  • Every instance uses the original network item and RPCs, so unmodded clients receive the native resource and protocol. The local owner starts the first wave: Trails uses the native first cycle only, with a loop duration of 1 s, a burst at time 0, count 4, burst cycles 1, delay 0, lifetime 2 s, World-space; VFX_Music remains native continuous World-space emission with lifetime 1.5 s. The plugin does not wait for a continuous musical note and does not impose the old 0.1 s internal floor. It waits for the actual first Trails wave to reach burst count 4 at its native timing and does not alter simulationSpace.
  • After the configurable initial-emission window (default 0.01 s, clamped to 0.01–0.9 s), runtime waits for the actual first Trails burst/time rather than a continuous-note estimate, and rejects a setup that would reach a second Trails burst. When the first pulse completes, the owner successfully sends native RPC_EndToot; that first successful send starts the per-horn timer. The owner then sets the root Rigidbody kinematic and parks the item at fixed world y = -1000. This stays inside the native Item.Update cleanup bounds (y < -2000 or y > 4000, which can trigger owner cleanup after about 2 s) and prevents old physics interpolation from moving the stopped instance.
  • Effect Playback Seconds and Destroy Delay Seconds are snapshotted independently for each horn. The clock starts at that horn's first successfully sent RPC_EndToot: phase 1 is playback, then phase 2 is destroy delay, with independent 0–8 s limits and a 16 s maximum total. A zero value permits immediate phase advancement and network destroy. There is no automatic particle-lifetime wait, Ping/RTT extra time, or old 8 s total cap.
  • During parking, native ItemOptimizer may disable the Item and its syncer, but it does not disable BugleSFX or either particle system. World-space particles are retained until the horn's deadline, then the root is destroyed; they are not paused or cleared. Playback duration does not extend native particle lifetime: early root destruction truncates remaining particles, while a positive destroy delay may still show particles that remain. Bounded errors fail safely. Pickup, ownership loss, or room loss releases tracking safely without parking or destroying a held item; only a valid owner destroys an unheld Ground instance.
  • The temporary-instance guard suppresses normal owner BugleSFX.UpdateTooting until the horn's deadline; ordinary held bugles are unaffected. No normal held-item use, confetti, box, extra buff, synthetic effect, or dynamic speed calculation is added. Frame cadence and the brief native RPC_EndToot audio fade mean exact instantaneous silence is not guaranteed; the new timers do not control that native audio fade. Network remote actual timing and an exact remote wave are not guaranteed; mixed-client visuals/physics and multiplayer synchronization still require actual in-game testing.

For a non-conscious local actor, the controlled native canPing postfix permits Ping only when the original inCooldown is false and these guards pass. The CharacterInput.Sample(bool) postfix only ORs the existing Ping flag with the enabled native action_ping.WasPressedThisFrame(), preserving remaps, controller bindings and other mods' flags. A Sample(false) from a state/mod can still supplement only Ping if the explicit guards pass; menu-blocked sampling cannot. No action/map is enabled, no Sample(true) is forced, and movement/jump input is not changed. Null/disabled actions and unavailable hooks are diagnosed once per reason and supplemental input is refused. The game or an optional ghost mod must still run the actual input/Ping path: GodCam can skip Sample, and this plugin adds no independent GodCam sampling or broad ResetInput hook.

Wheel labels refresh on opening, quota decrement/reclaim/reset/stage rewards, mode/spectator transitions, language changes and data rebuilds. Stable frames do not reformat all slices; the display observer samples spectator state once per frame and uses one mode/quota snapshot. Each label caches its entry, finite/unlimited presentation, raw finite count and font context: quota events format/assign only changed labels, and unchanged unlimited labels do not repeat the ∞/INF lookup. Label creation, language changes and data rebuilds clear that cache; font changes invalidate the affected label. Button availability still updates from the current snapshot. Pending item data is retried and rebuilt with aligned item/data indices. Mouse/controller selection, Z release and Ping generation still authorize independently; stale invalid selections are cleared. Centered labels, INF fallback, disabled button styling and deferred layout compensation remain.

The Eight Items

Wheel item Default path
Cure-All Cooking
Dynamite Cooking
AntiZooka Cooking
Frisbee Throw; always unlimited
PandorasBox Cooking
曲迁菇 (WarpFungus) Collision
踏板菇 (shelf mushroom) Collision
灵药菇 (healing puff mushroom) Collision

Cooking invokes the item's original cooking explosion. Collision launches the original network item and relies on native collision/throw behavior. The seven non-Frisbee entries each have an independent mode setting; changing modes does not add an effect missing from the game's prefab.

Paths that lack the required native components or fail preflight checks are rejected without a substitute effect. The healing puff mushroom can be physically launched but has no guaranteed healing effect in Collision mode. WarpFungus Collision requires a terrain Ping and a suitable native throw path. Original game logic controls explosion, break, warp, healing, and effect-child behavior.

Frisbee

  • Always unlimited, never charged, and never reclaimed or destroyed merely because you hold one.
  • Searches around the successful Ping point. Eligible nonplayers take priority over players within the radius; within each tier, the nearest actual collider surface wins. Targets include ground items, recognized props, creatures, and non-player-controlled characters.
  • Ordinary targets first use a direct route from that same successful Ping surface toward the already-selected target. The route uses the captured Ping point, surface normal, and Ping collider, aims through the selected collider bounds center, resolves the first actual surface hit belonging to that same target, checks solid default-layer line of sight, and places the Frisbee outside the Ping surface using its actual oriented collider support. If the direct route is blocked, too tight, zero-length, degenerate, or cannot be validated, it falls back to the existing target-near multi-direction approaches against that same target.
  • Both the preflight and final launch validate true spawn penetration and the complete body path with target-first collision ordering. Convex-only prefab checks defer exact validation to the final runtime Rigidbody.SweepTestAll; moving targets or changed obstacles can therefore reject or switch the route before release.
  • Rejects self, held items, projectiles, disabled/trigger colliders, and unsupported terrain or airwalls. A blocked or unsuitable launch path can prevent a throw.
  • Uses an original network item with real rigidbody collision and owner cleanup, not a fabricated hit. Different clients may observe different trajectories or actual collision-trigger outcomes for the same spawned Frisbee. Unmodded players can observe it through native networking, but exact client observations and effect synchronization still require manual multiplayer testing; synchronization is not guaranteed.

ArrowShooter Targets

  • If the already-selected collider has a native ArrowShooter ancestor, a dedicated route replaces ordinary direct/fallback flight. It reads the trap's native cached pos/forward and public range; it never guesses direction from the mesh, retargets, or falls back to a target-near throw. Missing cached data, unsupported non-Default Frisbee colliders, or no safe bounded shifted placement reject the attempt.
  • Placement moves one selected trap collider's full projected length forward along the native ray. Box uses scaled/rotated half-axis support; Mesh uses mesh.bounds half axes transformed by TransformVector; Sphere uses scaled diameter; Capsule uses scaled segment projection plus diameter. Unsupported geometry can use the selected collider's world bounds projection, explicitly logged as a conservative AABB approximation. Zero/nonfinite measurements reject. No particle, arrow-child, renderer, or guessed model dimensions are included. Length is remeasured before creation and final runtime launch. Candidate search starts at backSupport + 0.02 + epsilon + trapLength, not at the old position with a later shift. All shapes' signed support remains in use, so a negative root distance alone does not imply the solid body is behind the ray origin. Insufficient range/space rejects without returning to the old near-muzzle position. Logs include ray origin/forward, trap length, measurement basis, shift, minimum root distance and start/end projected distances.
  • The original network Frisbee must fit in range before the first solid native AllPhysical blocker. A real solid shape, not just its root, must intersect the native ray. Start/end penetration and the complete 0.02 m toward-muzzle micro-path are checked, including final actual-body sweeps and the exact native first hit after dynamic release. Compound/convex geometry requires exact runtime validation.
  • Prefab preflight checks structure: native AllPhysical must include Default, and enabled solid source colliders must be Default. A missing root Rigidbody or its detectCollisions=false is allowed here; each collider's nearest-parent Rigidbody must match that root, or be absent when the root is absent. Independent child bodies are rejected. After native Item.Awake/AddPhysics initializes the instance, its root Rigidbody, detectCollisions, actual collider attachment and ownership/Ground state remain mandatory. Temporary kinematic parking is allowed only before dynamic release. The plugin does not add a body or force collision detection on. Diagnostics report observed prefab metadata; earlier compound rejection alone does not establish that the source root body was missing.
  • Only PhotonNetwork.OfflineMode allows a missing/disabled original ItemPhysicsSyncer: offline residence uses local physics without requiring network synchronization. A one-player online room is not this exception. Online requires the original active root syncer; missing, disabled or inactive hierarchy rejects with separate diagnostics. The plugin never adds or enables a syncer, and calls native ForceSyncForFrames only when the original component is present and active. If mode changes to online without an eligible syncer, residence stops safely. Release/residence logs distinguish offline localphysics from online nativeforcedsync. This corrects the offline eligibility gate, not proof of why a previous component was missing/inactive, nor a network synchronization guarantee.
  • Dedicated facing uses the scaled convex mesh-local dimensions, not the root-local bounding widths. The mesh thin axis is transformed through its child-local rotation into a root-local plane normal, then aligned with the cached sensor ray. With multiple valid convex meshes, the largest product of the two longer dimensions wins; equal face areas keep the first mesh in the existing list (equal thin dimensions prefer up). No valid convex mesh means rejection. The positive normal/ray dot must be >= 0.9999 before spawning, after instance placement, and during residence; runtime checks both actual mesh-child orientation and body rotation. All shapes still participate in clearance, centers, overlap and sweeps. No collider size or ordinary-flight orientation changes. Native gravity/interpolation differences on unmodded replicas remain possible.
  • After that bounded real motion, it remains at a fixed body position/rotation with zero velocity, gravity off, and isKinematic=false, wakes the body, and requests synchronization through the original active ItemPhysicsSyncer when available under the mode policy above. Micro-motion is independent of Throw / Speed. The existing Throw / Lifetime Seconds (0.5 default, 0.05–10) starts at release and includes micro-motion. Real collisions, invalid body/item/target state, changed obstruction/selected trap length, or timeout cause owner cleanup.
  • The trap's original per-tick item sensor needs a solid Default-layer dynamic Rigidbody, not a velocity minimum. Native ammo/reload and firing remain untouched: empty/reloading traps get no extended lifetime, and a lifetime spanning reload can allow multiple native shots. Ammo is read only through the public getter for bounded diagnostics. This is not a shield or guaranteed safe trigger: native secondary ray/player damage and master-client visuals still apply. No fire RPC, synthetic collision, or custom effect is emitted; mixed-client/host synchronization remains unverified.

Cloud-Platform Rescue

  • Enabled by default, after the existing successful Ping hit and before resolving the selected wheel item. Search includes self and remote registered real player bodies, not NPCs, zombie/bot characters or ghost cameras. The nearest eligible Character.Center within the rescue radius wins; exactly equal squared distances use the smaller Photon ViewID. No self preference or target-ownership requirement is added.
  • A target must be alive, registered, non-grounded, and have an enabled actual ragdoll body. No stamina, fall-duration, climbing, water, carried, or natural-fall restriction is applied; the target may be the local player's actual ghost body. The nearest Character.Center within the radius wins, with smaller Photon ViewID breaking exact distance ties.
  • Clearance uses the combined world bounds of enabled ragdoll colliders excluding Item colliders. The body bottom is sampled at the center of a five-point horizontal rectangle whose width/depth are multiplied by sqrt(0.5): four corners plus center cast downward. Triggers, the target's own body and its held item are ignored; other players and platforms are valid. A solid hit at distance 0 through the configured threshold inclusive rejects; no hit qualifies. Origin contact is checked with a tiny actual overlap query, not an AABB claim.
  • Rescue selection and rescue errors are bounded diagnostics. Successful planning logs clearance, target, estimated platform position, actual support, quota and errors; stable frames do not scan or log. Resource and geometry caches invalidate when the item database/resource reference or active scene changes.
  • Consume one canonical 踏板菇 quota, independently of its Cooking/Collision setting. Unlimited and temporary spectator Unlimited do not charge. No eligible target or exhausted quota leaves the selected item's original behavior intact. After takeover, planning/validation/network failures cancel this Ping without retargeting or selected-item fallback. Charge only after successful original platform network creation; an initialization or Warp RPC failure afterward does not refund the quota or delete the native platform. No 曲迁菇 quota or intermediate WarpFungus is used.
  • Resolve 云雾菇 by its unique exact Simplified Chinese displayed name plus CloudFungus, then use its native instantiateOnBreak resource via PhotonNetwork.Instantiate("0_Items/" + prefab.name, ...). One upright random yaw is reused for both plans and creation. No extra wheel entry, guessed resource name, custom RPC/protocol, cooking, cleanup timer or follow-player behavior is added. Native platform effects/lifetime remain unchanged.
  • Platform overlap with terrain, props or any current player body is permitted and is not queried/rejected. Before the first Warp, preflight accepts Box/Sphere/Capsule colliders and MeshCollider sharedMesh.bounds, validates body collision-layer compatibility, and completes the five-point clearance check. It captures fixed P = target.Character.Center and positive finite L = max(target.refs.mainRenderer.bounds.size); the platform root estimate uses expected upper-surface center P - up * L and the reused upright yaw. After the first Warp, support validation reads only the platform's enabled solid colliders with downward Collider.Raycast; no target body, model length, clearance or post-init collision-layer query is performed.
  • Before the first Warp, recheck public Ping/room/local/plugin guards, target identity, radius, five-point clearance, all target body colliders and layer compatibility, and the platform quota. Capture fixed P = target.Character.Center and L = max(target.refs.mainRenderer.bounds.size.x/y/z); invalid or nonpositive renderer bounds reject. The platform estimate uses P - up * L as its expected upper-surface center. No target body collider, body model length, or clearance is read after the first Warp.
  • After subscribing, dispatch the first native WarpPlayerRPC(P, false) and wait up to 5 real-time seconds for that target's local WarpCompleted; this event is local observation, not remote-owner acknowledgement. Recheck mode/quota and target identity, then stop if an unrelated native Warp is already running before platform creation. Charge immediately after successful native platform creation, then wait up to 5 real-time seconds for platform initialization and validate only its enabled solid support. Subscribe again before dispatching the same fixed WarpPlayerRPC(P, false) and wait up to 5 real-time seconds for the second local completion. Timeouts and invalid stages do not retry or fall back; a created platform is not destroyed or refunded. After the second Warp the player may still be above the platform for a short fall and can take damage; no immunity is added.
  • Native Warp handles body velocity reset, local climbing stop, temporary body/held-item collision changes and sinceGrounded reset; it does not automatically revive, clear passedOut or reset fallSeconds on this path. Other players can receive this original RPC without installing this plugin. Platform creation and character RPC use different Photon views and are not an atomic network transaction. Logs record five-point clearance, selected target, estimated platform position, actual support, Center destination and quota outcomes. Live physics/network ordering remains untested; this does not guarantee a catch or eliminate all fall damage.

Limited Mode

  • Seven non-Frisbee items each start at 1 use. A use is deducted after successful network-item creation, not merely on a Ping attempt; a later initialization or native-effect failure does not refund it.
  • Holding one of these seven automatically reclaims it when ownership/inventory validation succeeds: Cure-All and PandorasBox grant +3 to their matching quotas; the other finite items grant +1. Confirm both canonical IDs and the reward before removal; counts saturate at Int32.MaxValue. This is not a free copy. Frisbee is excluded; stage rewards remain +1.
  • A genuinely new vanilla stage gives +1 to each of the seven while enabled and configured Limited. This includes Void and teammate-driven progress. Each stage rewards once per run; repeats/backtracking do not pay again. Lighting a campfire alone does not award uses.
  • Startup, loading, save synchronization, and late joining establish a current-stage baseline without historical rewards. Progress while disabled or configured Unlimited is not awarded later.
  • A new run resets quotas and stage history. New local-character initialization, dead-to-alive revival, and manually changing Unlimited to Limited reset the seven quotas to 1 without clearing visited-stage history.
  • Spectating/Ghost free-fly temporarily treats usage as Unlimited. Entering or leaving that state does not reset counts or stage history. Stage rewards still apply if configured Limited and enabled.

Configuration

Edit BepInEx/config/rua.PingPointUseItem.cfg. Exact section/key names and defaults:

Section / key Default Values / purpose
General / Enabled true All-state native Ping spawning/Z wheel; original input bindings, cooldown and menu guards
General / Item Cure-All One of the eight entries; saved by wheel selection
General / Usage Mode Unlimited Unlimited or Limited
Trigger Modes / Cure-All Cooking Cooking or Collision
Trigger Modes / Dynamite Cooking Cooking or Collision
Trigger Modes / AntiZooka Cooking Cooking or Collision
Trigger Modes / PandorasBox Cooking Cooking or Collision
Trigger Modes / WarpFungus Collision Cooking or Collision; wheel entry 曲迁菇
Trigger Modes / 踏板菇 Collision Cooking or Collision
Trigger Modes / 灵药菇 Collision Cooking or Collision
Collision / Cleanup Delay Seconds 0.5 0–30 seconds; original launched item only, not effect children
Throw / Target Search Radius 5 0.1–30 meters around this successful Ping point
Throw / Speed 60 1–200 meters/second
Throw / Lifetime Seconds 0.5 0.05–10 seconds from actual Frisbee release
Music Trail / Enabled true Add a native 8 m-spaced music-trail batch after each successful Ping; busy music does not block items/rescue
Music Trail / Spacing Meters 8 0.1–100 meters; existing user values are retained; samples the camera-relative [2, L-S] path with eligible-bound inclusion and deduplication
Music Trail / Initial Emission Seconds 0.01 0.01–0.9 seconds; runtime waits for the actual first Trails burst of 4 at native timing and rejects a second-loop burst
Music Trail / Effect Playback Seconds 3 0–8 seconds per horn after its first successfully sent RPC_EndToot; does not extend native particle lifetime
Music Trail / Destroy Delay Seconds 0 0–8 seconds per horn after playback; zero permits immediate network destroy; playback plus delay is at most 16 seconds
Rescue / Enabled true Prioritize native cloud-platform/Warp rescue on successful Ping
Rescue / Target Search Radius 5 0.1–30 meters around the successful Ping point
Rescue / Minimum Clearance Meters 5 0.1–30 meters; solid hit at or below the threshold rejects

Package And Limits

Intended installable package contents:

icon.png
README.md
manifest.json
plugins/
  PingPointUseItem/
    PingPointUseItem.dll

DLL version 2.6.13, plugin GUID rua.PingPointUseItem. Only BepInExPack_PEAK is mandatory. Rescue uses Enabled, Target Search Radius, and Minimum Clearance Meters; Music Trail uses Enabled, Spacing Meters, Initial Emission Seconds, Effect Playback Seconds, and Destroy Delay Seconds. New spacing defaults to 8, but existing user values are retained; removed speed/lifetime bindings are ignored if left in an existing config, and unrelated settings/defaults remain unchanged. All game references, including Unity.InputSystem.dll and UnityEngine.ParticleSystemModule.dll, are read-only with Private=false and are not bundled. This source/build update does not deploy to or update the game installation directory. Do not install source, test binaries, or old Release artifacts as plugins.

Local Build

Run from the project directory with restored .NET build assets and the game's referenced assemblies available:

dotnet build PingPointUseItem.csproj -c Release --no-restore -p:UseSharedCompilation=false
dotnet run --project Tests\LogicHarness.csproj -c Release --no-restore -p:UseSharedCompilation=false

The plugin output is Release/PingPointUseItem.dll. Its BepInPlugin version is 2.6.13, matching README/manifest; the game Unity.InputSystem.dll and UnityEngine.ParticleSystemModule.dll references are Private=false and are not copied into Release. These commands build/test inside this workspace, not deploy into the game installation.

Actual in-game visuals, physics, ghost controls, mixed-mod lobbies, and multiplayer synchronization have not been verified; this README makes no game-validation claim. Native effects and launch acceptance remain game-version dependent; real multiplayer testing is still required.

简体中文

按住 Z 从八种物品中选择,再通过一次成功的原生 Ping(默认鼠标中键,或重绑/手柄绑定),在标记点生成物品,或向附近目标投掷飞盘。每次成功 Ping 还可附加使用原版号角声音的原生网络音乐尾迹批次。七种非飞盘物品可以分别设置 Cooking / Collision。配额默认 Unlimited(无限),也可选择 Limited(有限);飞盘始终无限。

安装

  • 先安装 BepInExPack_PEAK。必需依赖为 BepInEx-BepInExPack_PEAK-5.4.75301。
  • 使用模组管理器安装本包,或将 PingPointUseItem.dll 放入当前 PEAK BepInEx 配置环境的 BepInEx/plugins/PingPointUseItem/ 目录。
  • 升级前,删除当前环境 plugins 目录中的所有旧 InstantCookExplosion.dll,以及对应的旧 PDB/deps 文件,不要同时加载新旧插件。
  • 启动游戏后生成 BepInEx/config/rua.PingPointUseItem.cfg。新默认值:启用、选择 Cure-All、Unlimited。若现有配置仍有已移除的 Music Trail 速度/时长键,会被忽略;插件不会改写游戏配置。
  • SymbioticGhost 和 SenseOfDirection 仅为可选集成,不是必需依赖。

操作

  1. 按住 Z,指向轮盘中可用的物品,松开 Z,保存下一次 Ping 使用的选择。
  2. 瞄准表面并使用游戏的 Ping 绑定。生成跟随成功的原版 Ping 命中及原有冷却,没有额外生成射线、Ping RPC 或独立冷却。
  3. 数量直接居中显示在各图标中心。无限显示 ∞,字体不支持时显示 INF;有限物品耗尽后不可选择。

所有角色状态均不再受 fullyConscious/观战权限门槛限制,攀爬也不再阻止物品轮盘。仍要求有效且 active 的 Character.localCharacter、角色 data、绑定该角色的 PointPinger,以及角色和 pinger 的两个本地 Photon 所有权;房间、焦点、阻塞菜单与原生/自定义轮盘互斥条件仍有效。加载时 GUI 轮盘引用缺失则安全拒绝。插件禁用或非本地对象的原生 Ping 行为保持不变。

音乐尾迹

  • 在现有成功 Ping 的 frameguard 之后,捕获 Camera.main.transform.position 和原生 Ping 的精确 hit.point。令 L 为捕获的相机到 Ping 距离,S 为当前用户配置的 Spacing Meters;新配置默认 8 米,已有值(例如 5)不覆盖。音乐只能使用从相机沿相机到原生 Ping 方向测量的 [2, L-S] 路径。令 length=L-S-2:length<0 仅跳过音乐;length=0 只生成距离相机 2 米 的一个点;length>0 按 S 从 2 采样到 L-S,包含有效上下界并去重重合点。短路径不再钳到 Ping 点,也不采样精确 Ping 点;上界固定为 L-S。
  • 每个采样端点生成一个原生网络资源 0_Items/bugle_magic,出于性能最多 32 个实例。超过 32 个合格采样点时,只保留前 16 个头部点和后 16 个尾部点,不再额外钳到 Ping 点。固定端点只捕获一次;选中物品/救援路径保持独立。音乐 busy 只阻止新的音乐批次,并持续到整批实例及每个号角的清理 deadline 全部结束。其他物品、救援和音乐 busy 规则保持不变。
  • 每个实例使用原生网络物品和 RPC,因此未安装本插件的客户端仍接收原生资源和协议。owner 启动第一波:Trails 只使用原生第一循环,循环时长 1 秒,在时间 0 burst,数量 4、burst cycles 1、delay 0、寿命 2 秒、World-space;VFX_Music 保持原生连续 World-space 发射,寿命 1.5 秒。插件不等待连续音乐音符,也不再施加旧的 0.1 秒内部下限;它等待实际第一波 Trails 达到 burst 数量 4 及其原生时序。插件不修改 simulationSpace。
  • 经过可配置的初始发射窗口(默认 0.01 秒,范围 0.01–0.9 秒)后,运行时等待实际第一波 Trails 的 burst/时序,而不是连续音符估算,并拒绝会到达第二次 Trails burst 的设置。首个 pulse 完成后,owner 成功发送原生 RPC_EndToot;首次成功发送即启动该号角计时器。随后将根 Rigidbody 设为 kinematic,并把物品停放到固定世界坐标 y = -1000。这会避开原生 Item.Update 的清理边界(y < -2000 或 y > 4000,越界可能约 2 秒后触发 owner 清理),也避免停止后的旧物理插值继续移动实例。
  • Effect Playback Seconds 和 Destroy Delay Seconds 按每个号角分别快照。时钟只从该号角首次成功发送 RPC_EndToot 开始:阶段 1 为播放,阶段 2 为销毁延迟,两阶段独立且各为 0–8 秒,总计最多 16 秒。零值允许立即推进阶段并进行网络销毁。不自动等待粒子寿命,不增加 Ping/RTT 额外时间,也没有旧的总计 8 秒上限。
  • 停放期间,原生 ItemOptimizer 可能禁用 Item 及其 syncer,但不会禁用 BugleSFX 或两个粒子系统。World-space 粒子保留到该号角 deadline,再销毁根对象;不会 Pause 或 Clear。播放时长不会延长原生粒子寿命:提前销毁会截断剩余粒子,正的销毁延迟仍可能显示尚未到期的粒子。有界错误会安全失败。拾取、所有权丢失或房间丢失时安全释放 tracking,不停放也不销毁被持有物品;只有有效 owner 才销毁未持有的 Ground 实例。
  • 临时实例的保护会持续到该号角 deadline,期间抑制 owner 的普通 BugleSFX.UpdateTooting,普通手持号角不受影响。不加入正常手持使用、彩纸、箱子、额外增益、合成效果或动态速度计算。frame cadence 和原生 RPC_EndToot 的短暂音频淡出意味着不能保证某个精确时刻完全无声;新计时器不控制该原生音频淡出。远端实际时序和完全一致的远端波形不保证;混合客户端的视觉/物理及多人同步仍需实际游戏测试。

非清醒本地角色的原生 canPing postfix 只在原版 inCooldown=false 且上述 guards 通过时放行。CharacterInput.Sample(bool) postfix 只将现有 Ping 标志与已启用原生 action_ping.WasPressedThisFrame() 做 OR,保留重绑、手柄及其他模组已有标志。状态/模组传入 Sample(false) 时,只要独立 guards 通过仍可仅补 Ping;菜单阻断时不能补。不会启用 action/action map、强制 Sample(true) 或修改移动/跳跃。action 为 null/禁用或 hook 不可用时,按原因有界记录并拒绝补输入。仍需要游戏或可选幽灵模组实际执行输入/Ping 路径;GodCam 可跳过 Sample,本插件不新增独立 GodCam 采样或广泛 ResetInput hook。

轮盘数字在打开、配额扣除/回收/重置/阶段奖励、模式/观战变化、语言变化及数据重建时刷新。稳定帧不重新格式化全部扇区;显示观察器每帧查询一次观战状态,整盘使用一份模式/配额快照。每个标签缓存条目、有限/无限显示模式、原始有限次数与字体上下文:配额事件只格式化/赋值变化标签,无限标签不因隐藏次数变化重复查询 ∞/INF。标签创建、语言变化和数据重建清除缓存,字体变化使对应标签失效;按钮可用性仍从当前快照更新。未就绪数据持续重试,完成后按一致条目索引重建。鼠标/手柄选择、Z 释放和 Ping 生成仍独立进行实时授权,失效选择会清除。保留居中数字、INF 回退、禁用按钮样式及延迟布局补偿。

八种物品

轮盘物品 默认路径
Cure-All Cooking
Dynamite Cooking
AntiZooka Cooking
Frisbee Throw,始终无限
PandorasBox Cooking
曲迁菇(WarpFungus) Collision
踏板菇 Collision
灵药菇 Collision

Cooking 调用物品原有的烹饪爆炸;Collision 发射原始网络物品,依靠其原生碰撞或投掷行为。七种非飞盘物品可以分别切换路径,但切换设置不会凭空添加游戏预制体没有的效果。

缺少必需原生组件或未通过发射前校验的路径会被拒绝,不使用替代效果。灵药菇在 Collision 下可以物理发射,但不保证产生治疗效果。曲迁菇的 Collision 需要对地形 Ping,并满足原生投掷条件。爆炸、破碎、传送、治疗和效果子物体仍由游戏原有逻辑决定。

飞盘

  • 始终无限、不扣次数,不会仅因手持飞盘而回收或销毁它。
  • 以本次成功 Ping 点为中心搜索。半径内的合格非玩家目标优先于玩家;同类优先选择最近的实际碰撞体表面。目标包括地面物品、识别的场景道具、生物及非玩家控制的角色。
  • 普通目标首先从这次成功 Ping 的同一标记表面,向已经选定的同一目标尝试直达路径。直达路径会携带并使用 Ping 的 point、normal 和 collider,先朝选定碰撞体的 bounds 中心瞄准,再解析该方向上属于同一目标的第一个真实表面,检查默认实体碰撞层的视线,并根据最终朝向下的真实碰撞体支撑范围,将飞盘放在 Ping 表面外侧。若直达被阻挡、空间不足、方向为零、标记点退化或无法验证,则对同一目标回退到原有的目标附近多方向方案。
  • 预检和最终释放都会检查真实生成穿透,以及按目标优先顺序的完整刚体路径。仅凸网格的预制体检查会推迟到最终运行时 Rigidbody.SweepTestAll;目标移动或障碍变化可能在释放前拒绝或切换路径。
  • 排除自身、手持物品、投射物、禁用或触发器碰撞体,以及不支持的地形和空气墙。路径受阻或不适合发射时可能不会投掷。
  • 使用原始网络物品、真实刚体碰撞及所有者清理,不伪造命中。不同客户端观察同一个生成的飞盘时,轨迹或实际碰撞触发结果可能存在差异。未安装本模组的玩家可以通过原生网络观察它,但各客户端的具体表现及效果同步仍需实际多人测试,不保证同步一致。

ArrowShooter 箭陷阱目标

  • 已选定碰撞体的祖先存在原生 ArrowShooter 时,专用路径替代普通直达与回退飞行。只读取陷阱缓存的 pos、forward 和公开 range,不根据模型猜朝向、不重新选目标,也不回退到目标附近投掷。缓存缺失、飞盘实体碰撞体不在 Default 层,或有界前移搜索找不到安全位置时拒绝。
  • 放置位置沿原版射线正方向前移当前所选陷阱实体碰撞体的整段投影长度。Box 使用缩放旋转后的半轴支撑,Mesh 使用 mesh.bounds 半轴经 TransformVector 变换后的投影,Sphere 使用缩放直径,Capsule 使用缩放线段投影加直径。不支持的形状可使用所选 collider 的世界 bounds 投影,日志明确标记为保守 AABB 近似;零值或非有限测量拒绝。不计粒子、箭子对象、renderer 或猜测的模型长度。生成前和真实发射前重新测量,候选搜索直接从 backSupport + 0.02 + epsilon + trapLength 开始,不先找旧安全点再事后平移。仍使用全部形状的有符号支撑,根投影距离为负不等于实体位于射线起点之后。射程或空间不足时拒绝,不退回旧枪口附近位置。日志记录射线起点/正方向、陷阱长度、测量依据、前移量、最小根距离及起终点投影距离。
  • 原始网络飞盘必须位于射程内、原生 AllPhysical 首个实体障碍之前;必须是实际实体形状穿过原生射线,而非只有根节点在线上。检查起点/终点穿透及向枪口移动 0.02 米的完整微路径,最终还需真实刚体扫描和动态释放后的原生首命中校验。复合形状和凸网格必须通过运行时精确验证。
  • 预制体预检只检查结构:原生 AllPhysical 必须包含 Default,源碰撞体的已启用实体形状必须在 Default 层。此阶段允许根 Rigidbody 缺失,也忽略其 detectCollisions=false;每个碰撞体最近父刚体只能是根刚体,根缺失时只能为 null,独立子刚体会被拒绝。实例经原生 Item.Awake/AddPhysics 初始化后,仍严格要求根刚体、detectCollisions、真实碰撞体刚体归属和所有权/Ground 状态。仅释放前允许临时 kinematic 停放,释放后必须 dynamic;插件不主动添加刚体或强行开启碰撞检测。诊断记录当次实际元数据,旧复合拒绝日志本身不能证明源根刚体缺失。
  • 仅 PhotonNetwork.OfflineMode 允许原始 ItemPhysicsSyncer 缺失或禁用:离线驻留使用本地物理,不要求网络同步。人数为 1 的联机房间不属于此例外。联机仍要求原根节点 syncer 存在且 active,分别诊断缺失、disabled 或层级 inactive 并拒绝;不添加或强行启用 syncer。只有原组件存在且 active 时才调用原生 ForceSyncForFrames。若驻留期间变为联机而没有有效 syncer,会安全停止。释放/驻留日志区分 offline localphysics 与 online nativeforcedsync。这是离线条件误拦截修正,不代表已证明之前组件缺失/失效的原因,也不保证网络同步效果。
  • 专用朝向使用已缩放的凸网格局部尺寸,不是根局部包围宽度。将网格最薄轴经子节点局部旋转变换为根坐标平面法线,再对准缓存射线。多个有效凸网格选择另外两个较长尺寸乘积最大的面;面积相同保留原列表首个,薄轴尺寸相同时优先 up。没有有效凸网格则拒绝。生成前、实例放置后及驻留期间,法线与射线的正点积必须 >= 0.9999;运行时同时验证实际网格子 Transform 朝向与刚体旋转。全部形状仍参与支撑间距、中心、重叠与扫掠,不放大碰撞体、不改变普通飞行朝向。未装模组副本的原生重力或插值差异仍可能存在。
  • 有界真实微移动结束后,保持刚体位置与旋转固定,速度为零、无重力、isKinematic=false,唤醒刚体,按上述离线/联机规则在原有 active ItemPhysicsSyncer 可用时请求同步。微移动不受 Throw / Speed 影响。沿用 Throw / Lifetime Seconds(默认 0.5,范围 0.05–10),从释放开始计时并包含微移动时间。真实碰撞、物品/刚体/目标状态失效、障碍或所选陷阱长度变化、超时会触发所有者清理。
  • 陷阱原生逐帧检测只要求命中 Default 层的实体动态刚体,没有最低速度要求。不修改弹药、装填或发射:空弹/装填期间不延长飞盘寿命,寿命覆盖装填时可触发原生多次射击。只通过公开弹药 getter 做有界诊断。此模式不是护盾,也不保证安全触发:原生第二次射线、玩家伤害和主客户端视觉行为仍有效。不调用发射 RPC、不伪造碰撞、不发送自定义效果;混合客户端及主机同步仍未实测。

云平台救援

  • 默认开启,在现有成功 Ping 命中后、解析轮盘所选物品前优先检查。搜索自身和远端已注册真实玩家身体,不搜索 NPC、僵尸/机器人或幽灵镜头。选半径内距离最近的合格 Character.Center,平方距离完全相同时取较小 Photon ViewID,不优先自身、不要求目标本地所有权。
  • 目标必须未死亡、已注册、未落地,并有启用的实际布娃娃身体;可包含本地玩家的实际幽灵身体。不再限制耐力、坠落时长、攀爬、涉水、携带或自然坠落状态。先按 Character.Center 与 Ping 点的半径筛选,再对候选执行五点净空查询。
  • 净空使用排除 Item 的启用布娃娃碰撞体联合世界 bounds:下沿为五点射线起点,水平宽/深乘 sqrt(0.5),查询四角和中心。触发器、自身身体和 CharacterData.currentItem 被忽略;其他玩家和平台有效。实体命中距离 0 到阈值(含) 拒绝,无命中通过;原点接触使用小半径实际 OverlapSphereNonAlloc,不使用旋转/凹网格 AABB 冒充实体。
  • 救援诊断只输出有界的五点净空、目标选择、估计平台位置、实际支撑、额度和错误信息;无合格目标或零额度会明确保留选中物品回退,成功 Ping 也只记录一次,不逐帧扫描或建立无限坐标键。旧的轨迹预测、水状态和耐力/坠落原因字段不再属于此路径。救援直接创建云平台,不会生成可见的中间云雾菇物品;实际物理和联机顺序仍待实测。
  • 使用一份原生 ID 对应的踏板菇配额,不受其 Cooking/Collision 设置影响;Unlimited 和观战临时 Unlimited 不扣次。没有合格目标或配额耗尽时保留原选中物品行为;接管后规划/校验/网络失败取消本次 Ping,不重选目标、不回退选中物品。原平台网络创建成功才扣次;之后初始化或 Warp RPC 失败不退额度、不删除原生平台。不消耗曲迁菇额度,不生成中间曲迁菇。
  • 以唯一的**精确简体中文显示名“云雾菇”加 CloudFungus**解析原生 instantiateOnBreak,走 PhotonNetwork.Instantiate("0_Items/" + prefab.name, ...)。每次只抽一次直立随机 yaw,供两次规划和创建共用。不增轮盘条目、不猜资源、不新增 RPC/协议、烹饪/清理计时或跟随逻辑,保留原平台效果和寿命。
  • 首次 Warp 前重新检查公共 Ping/UI/房间/本地所有权守卫、目标身份、原半径、五点净空、身体碰撞箱/碰撞层兼容和踏板菇额度,并捕获固定 P=target.Character.Center、L=max(target.refs.mainRenderer.bounds.size);无效模型直接拒绝。平台估计上表面中心为 P-up*L。首次 Warp 后不再读取目标身体碰撞箱、模型长度或净空;若首次完成后发现其他原生 Warp 正在运行,则不创建平台。
  • 允许平台与地形、道具或任何当前玩家身体重叠,不查询/拒绝这些重叠。 预制体预检支持 Box/Sphere/Capsule 碰撞体以及使用 MeshCollider.sharedMesh.bounds 的网格碰撞体;几何会结合层级变换与缩放转换,无需顶点、三角形数据或 CPU 可读性。随机直立 yaw 供固定平台根坐标估算和创建复用;预期平台上表面中心为 P-up*L。原生实例初始化后,仅对平台自身启用实体碰撞体向下调用 Collider.Raycast 确认实际向上支撑面,不读取目标身体,也不因重叠拒绝。
  • 发送前建立 WarpCompleted 订阅,再按 WarpPlayerRPC(P,false) 首次传送并最多等待 5 秒本机该目标的匹配完成事件;完成后复查模式/额度及身份、房间、启用状态,成功创建平台后立即扣一份 canonical 踏板菇并刷新轮盘。平台支撑面就绪后再次订阅并发送同一个固定 P 的第二次 Warp,等待最多 5 秒完成。完成事件只是本机观察,不证明远端 owner 已完成;超时/失效停止且不重试、不回退,已创建平台不销毁、不退额度。第二次传送后玩家仍可能在平台上方短暂下落并受伤害,不新增免伤。
  • 原生 Warp 负责身体清速、停止本机攀爬、临时身体/手持物碰撞切换及 sinceGrounded 重置;该路径不会自动复活、解除 passedOut 或重置 fallSeconds。其他玩家无须安装本插件即可接收原 RPC,但平台创建和角色 RPC 属不同 Photon View,不是网络原子事务。日志包含五点净空、目标、估计平台位置、真实支撑、Center 落点和额度结果;不再记录旧的碰撞点、Ping 时域或轨迹快照字段。实际物理和联机顺序待实测,不保证绝对接住或消除所有坠落伤害。

Limited 配额

  • 七种非飞盘物品初始各 1 次。成功创建网络物品后扣除,而非仅尝试 Ping 就扣除;之后初始化或原生效果失败不退还次数。
  • 手持这七种物品之一时,所有权及背包校验通过后会自动回收:Cure-All 和 PandorasBox 对应配额各 +3,其他有限物品 +1。 移除前确认两种 canonical 原生 ID、奖励大小和 Int32.MaxValue 饱和结果;这不是免费复制。飞盘不回收,阶段奖励仍为 +1。
  • 插件启用且配置为 Limited 时,首次进入本轮未访问的原版阶段,为七种物品各 +1。包括 Void 和队友带来的阶段推进;重复进入或回退不重复奖励。仅点燃篝火不会增加次数。
  • 初次启动、读档、存档同步及中途加入只建立当前阶段基线,不补发历史奖励。禁用或配置为 Unlimited 期间经过的阶段,之后不会追溯补发。
  • 新一轮游戏重置配额与阶段历史。新本机角色初始化、死亡后复活、手动从 Unlimited 切到 Limited 会将七种配额重置为 1,但不清除阶段历史。
  • 观战或幽灵自由飞行期间,使用暂按 Unlimited 处理。进入或离开此状态不重置已有次数或阶段历史。只要配置仍是 Limited 且插件启用,阶段奖励仍有效。

配置

编辑 BepInEx/config/rua.PingPointUseItem.cfg。以下为准确的配置区段、键名和默认值:

区段 / 键名 默认值 可选值 / 用途
General / Enabled true 所有状态的原生 Ping 生成/Z 轮盘;保留绑定、冷却和菜单限制
General / Item Cure-All 八种物品之一;轮盘选择后保存
General / Usage Mode Unlimited Unlimited 或 Limited
Trigger Modes / Cure-All Cooking Cooking 或 Collision
Trigger Modes / Dynamite Cooking Cooking 或 Collision
Trigger Modes / AntiZooka Cooking Cooking 或 Collision
Trigger Modes / PandorasBox Cooking Cooking 或 Collision
Trigger Modes / WarpFungus Collision Cooking 或 Collision;轮盘对应曲迁菇
Trigger Modes / 踏板菇 Collision Cooking 或 Collision
Trigger Modes / 灵药菇 Collision Cooking 或 Collision
Collision / Cleanup Delay Seconds 0.5 0–30 秒;只清理原始发射物品,不清理效果子物体
Throw / Target Search Radius 5 0.1–30 米,以本次成功 Ping 点为中心
Throw / Speed 60 1–200 米/秒
Throw / Lifetime Seconds 0.5 飞盘实际释放起 0.05–10 秒
Music Trail / Enabled true 每次成功 Ping 附加默认 8 米间距的原生音乐尾迹批次;音乐 busy 不阻断物品/救援
Music Trail / Spacing Meters 8 0.1–100 米;已有用户值保留;在相机相对 [2, L-S] 路径上采样,包含有效边界并去重
Music Trail / Initial Emission Seconds 0.01 0.01–0.9 秒;运行时等待实际第一波 Trails 的 4 个 burst 及原生时序,并拒绝第二循环 burst
Music Trail / Effect Playback Seconds 3 每个号角首次成功发送 RPC_EndToot 后的 0–8 秒;不会延长原生粒子寿命
Music Trail / Destroy Delay Seconds 0 每个号角播放后的 0–8 秒;零值可立即网络销毁;播放加延迟最多 16 秒
Rescue / Enabled true 成功 Ping 优先原生云平台/Warp 救援
Rescue / Target Search Radius 5 成功 Ping 点周围 0.1–30 米
Rescue / Minimum Clearance Meters 5 0.1–30 米;命中小于等于阈值拒绝

包内容与限制

预期安装包结构如下:

icon.png
README.md
manifest.json
plugins/
  PingPointUseItem/
    PingPointUseItem.dll

DLL 版本为 2.6.13,插件 GUID 为 rua.PingPointUseItem。必需依赖只有 BepInExPack_PEAK;Rescue 配置为 Enabled、Target Search Radius、Minimum Clearance Meters,Music Trail 配置为 Enabled、Spacing Meters、Initial Emission Seconds、Effect Playback Seconds、Destroy Delay Seconds;新间距默认 8,但已有用户值保留;已移除的速度/时长绑定若仍在现有配置中会被忽略,其他配置/默认值不变。包括 Unity.InputSystem.dll 和 UnityEngine.ParticleSystemModule.dll 的全部游戏引用均只读且为 Private=false,不打包复制。本次源码/编译更新不部署或更新游戏安装目录。不要将源码、测试程序或旧 Release 文件作为插件安装。

本地构建

在项目目录执行以下命令,前提是 .NET 构建资产已还原,游戏引用程序集可用:

dotnet build PingPointUseItem.csproj -c Release --no-restore -p:UseSharedCompilation=false
dotnet run --project Tests\LogicHarness.csproj -c Release --no-restore -p:UseSharedCompilation=false

插件输出为 Release/PingPointUseItem.dll;BepInPlugin 版本为 2.6.13,与 README/manifest 一致。游戏 Unity.InputSystem.dll 和 UnityEngine.ParticleSystemModule.dll 引用为 Private=false,不会复制到 Release。这些命令只在工作区构建/测试,不部署到游戏安装目录。

尚未验证实际游戏内视觉、物理、幽灵操作、混合模组大厅及多人同步;本文不作游戏验证声明。原生效果和发射条件仍受游戏版本影响,真实多人环境仍需测试。

Thunderstore development is made possible with ads. Please consider making an exception to your adblock.