feat(bounce): bullet_manager 命中弹跳分支(优先于pierce)+跳过已访问+_find_nearest_unvisited 寻的

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-24 15:11:16 +08:00
co-authored by Claude Opus 4.8
parent 6b910697a9
commit 3eb6049b39
+40
View File
@@ -73,6 +73,10 @@ func _check_collision(bullet_idx: int, base: int) -> bool:
var dist_sq: float = dx * dx + dy * dy
if dist_sq > query_r * query_r:
continue
if _bullet_contexts.has(bullet_idx):
var vt = _bullet_contexts[bullet_idx].get("visited_targets", null)
if vt != null and entity_id in vt:
continue # 弹跳已命中过此敌:跳过,避免密集群内重复命中
# 命中:通过 DamageContextPool 发出伤害
var ctx_id: int = DamageContextPool.acquire(b_dmg, b_mult, b_type, b_own, false, 0.0)
EnemyManager.apply_damage_from_context(entity_id, ctx_id)
@@ -99,6 +103,25 @@ func _check_collision(bullet_idx: int, base: int) -> bool:
if payload_id >= 0:
var parent_depth: int = int(cold.get("trigger_parent_depth", 0))
SpellEvaluator.execute_sub(payload_id, hit_pos, b_own, parent_depth + 1)
# bounce 处理(优先于 pierce):命中后弹向最近未访问敌人,伤害递减
var bounce: int = int(cold.get("bounce_remaining", 0))
if bounce > 0:
var visited: Array = cold.get("visited_targets", [])
visited.append(entity_id)
var next_id: int = _find_nearest_unvisited(Vector2(bx, by), float(cold.get("bounce_range", 250.0)), visited)
if next_id >= 0:
var np: Vector2 = EnemyManager.get_pos_by_id(next_id)
var spd: float = Vector2(_data[base + 2], _data[base + 3]).length()
var dir: Vector2 = (np - Vector2(bx, by)).normalized()
_data[base + 2] = dir.x * spd
_data[base + 3] = dir.y * spd
_data[base + 7] *= float(cold.get("bounce_decay", 0.9))
cold["bounce_remaining"] = bounce - 1
cold["visited_targets"] = visited
_bullet_contexts[bullet_idx] = cold
return false
_swap_and_pop(bullet_idx)
return true
# pierce 处理
var pierce: int = int(cold.get("pierce_remaining", 0))
if pierce > 0:
@@ -174,6 +197,23 @@ func sync_multimesh(mm: MultiMesh) -> void:
0.0, Vector2(r * 2.0, r * 2.0), 0.0,
Vector2(_data[base + 0], _data[base + 1])))
## 弹跳寻的:query_circle 半径内滤除已访问/哨兵,取最近 entity_id;无则 -1
func _find_nearest_unvisited(origin: Vector2, radius: float, visited: Array) -> int:
var hits: PackedInt32Array = SpatialGrid.query_circle(origin, radius)
var best_id: int = -1
var best_sq: float = radius * radius
for eid in hits:
if eid in visited:
continue
var p: Vector2 = EnemyManager.get_pos_by_id(eid)
if p == Vector2(-9999.0, -9999.0):
continue
var d: float = origin.distance_squared_to(p)
if d <= best_sq:
best_sq = d
best_id = eid
return best_id
func get_nearest_enemy_pos(origin: Vector2, max_dist: float = 9999.0) -> Vector2:
return EnemyManager.get_nearest_pos(origin, max_dist)