feat(collision): cadena herit→sa via fregada física (Fase 6)
Systems::Collision::detectWoundedChain itera parells d'enemics: si exactament un està herit i toquen (Physics::checkCollision), el sa entra en estat herit propagant last_hit_by_ → la cascada de morts segueix acreditant el shooter original. El rebot físic ja el gestiona PhysicsWorld; aquí només propaguem l'estat. Hook a detectAll just després de detectBulletEnemy: les balles tenen prioritat sobre la cadena del mateix frame. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -125,6 +125,36 @@ namespace Systems::Collision {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void detectWoundedChain(Context& ctx) {
|
||||||
|
const std::size_t N = ctx.enemies.size();
|
||||||
|
for (std::size_t i = 0; i < N; i++) {
|
||||||
|
Enemy& a = ctx.enemies[i];
|
||||||
|
if (!a.isCollidable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (std::size_t j = i + 1; j < N; j++) {
|
||||||
|
Enemy& b = ctx.enemies[j];
|
||||||
|
if (!b.isCollidable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const bool A_WOUNDED = a.isWounded();
|
||||||
|
const bool B_WOUNDED = b.isWounded();
|
||||||
|
if (A_WOUNDED == B_WOUNDED) {
|
||||||
|
continue; // ambos sanos o ambos heridos: nada que propagar
|
||||||
|
}
|
||||||
|
if (!Physics::checkCollision(a, b, 1.0F)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// El sano queda herido, propagando el shooter original.
|
||||||
|
if (A_WOUNDED) {
|
||||||
|
b.herir(a.getLastHitBy());
|
||||||
|
} else {
|
||||||
|
a.herir(b.getLastHitBy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void detectShipEnemy(Context& ctx) {
|
void detectShipEnemy(Context& ctx) {
|
||||||
constexpr float AMPLIFIER = Defaults::Game::COLLISION_SHIP_ENEMY_AMPLIFIER;
|
constexpr float AMPLIFIER = Defaults::Game::COLLISION_SHIP_ENEMY_AMPLIFIER;
|
||||||
|
|
||||||
@@ -198,6 +228,7 @@ namespace Systems::Collision {
|
|||||||
void detectAll(Context& ctx) {
|
void detectAll(Context& ctx) {
|
||||||
processWoundedDeaths(ctx); // expiran ANTES de ser tocadas por bala este frame
|
processWoundedDeaths(ctx); // expiran ANTES de ser tocadas por bala este frame
|
||||||
detectBulletEnemy(ctx);
|
detectBulletEnemy(ctx);
|
||||||
|
detectWoundedChain(ctx); // un herit pot ferir a un sa al fregar-lo
|
||||||
detectShipEnemy(ctx);
|
detectShipEnemy(ctx);
|
||||||
detectBulletPlayer(ctx);
|
detectBulletPlayer(ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ namespace Systems::Collision {
|
|||||||
// al `last_hit_by_` del enemy (si está set).
|
// al `last_hit_by_` del enemy (si está set).
|
||||||
void processWoundedDeaths(Context& ctx);
|
void processWoundedDeaths(Context& ctx);
|
||||||
|
|
||||||
|
// Si un enemy herido colisiona con uno sano (ni herido ni invulnerable),
|
||||||
|
// el sano también queda herido (efecto cadena). Propaga `last_hit_by_` para
|
||||||
|
// que el shooter original siga acreditándose la muerte en cascada. El rebote
|
||||||
|
// físico ya lo resuelve PhysicsWorld; aquí solo propagamos el estado.
|
||||||
|
void detectWoundedChain(Context& ctx);
|
||||||
|
|
||||||
// Detecta colisiones ship → enemy. Si hit, llama on_player_hit(player_id).
|
// Detecta colisiones ship → enemy. Si hit, llama on_player_hit(player_id).
|
||||||
void detectShipEnemy(Context& ctx);
|
void detectShipEnemy(Context& ctx);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user