Contexte
Depuis la session 113 phase 2.D, les aliens armés (Guards, AlienPriest, etc.)
déclarent tirer via AlienAI.attackWithProjectile qui appelle
AiWorld.spawnAlienProjectile. Mais l’implémentation runtime
(AiWorldAdapter.spawnAlienProjectile) tombait sur un fallback placeholder :
50% de chance d’appliquer les dégâts directement au joueur, sans bullet
visible, sans esquive possible.
Les structures AlienShot + AlienShotPool (50 slots, équivalent ASM
Plr_AlienShotDataPtr_l) ainsi que la branche « vraie bullet » dans
AiWorldAdapter.spawnRealAlienBullet étaient préparées, mais le système qui
fait avancer ces bullets et teste leur collision sur le joueur n’existait
pas.
Symptômes observés avant fix
--test-level ALIEN_GUARD: on entend (= log) les tirs alien et on perd
des HP de manière aléatoire, mais aucune balle visible à l’écran ; pas
moyen d’esquiver.GameAppState.javane compilait pas :import AlienBulletUpdateSystem
mais le fichier était absent du dépôt.
Modifications
Nouveau fichier combat/AlienBulletUpdateSystem.java :
Symétrique de BulletUpdateSystem (bullets joueur) mais spécialisé pour
les tirs hostiles :
– Itère sur AlienShotPool.getSlots(), ignore les slots libres (zoneId<0).
– Au premier update() après spawn : crée la Geometry placeholder
(sphère teintée rouge dominante, blend Additive si graphicType==2).
– Mouvement linéaire pos += vel * tpf + gravité optionnelle
(formule identique à BulletUpdateSystem pour symétrie ASM).
– Test collision joueur (priorité 1) : capsule verticale autour de
cam.getLocation(), rayon 0.45, demi-hauteur 0.6 JME (un peu plus
généreux que la capsule physique pour la lisibilité du hit). Sur hit :
playerHealth.takeDamage(shot.power) + impactSystem.spawnImpact(...).
– Test collision murs (priorité 2) via WorldRaycaster.castRay entre
oldPos et newPos ; impact au point exact + flash + kill bullet.
– Timeout sur BulT_Lifetime_l du GLF (fallback 500 frames Amiga si
lifetime < 0, comme BulletUpdateSystem).
– Couleur par bullet type : palette décalée vers le rouge
(Plasma alien rouge-rose, Lazer rouge pur, etc.) pour distinction visuelle
immédiate des tirs hostiles.
app/GameAppState.java :
- Câblage manquant ajouté dans
setupPhysics(), juste après l’attache
deAlienHitDetector:
java
alienShotPool = new AlienShotPool();
alienBulletUpdateSystem = new AlienBulletUpdateSystem(alienShotPool, glfRef, healthState);
alienBulletUpdateSystem.setRaycaster(raycaster);
alienBulletUpdateSystem.setImpactSystem(impactSystem);
sa.getStateManager().attach(alienBulletUpdateSystem);
aiWorld.setAlienShotPool(alienShotPool, glfRef);
Encadré partry/catchpour rester gracieux siTEST.LNKest absent
(le combat reste fonctionnel sans, juste sans bullets aliens visibles). cleanup(): détachealienBulletUpdateSystem, libèrealienShotPool.
Flux complet (alien armé tire sur le joueur)
AlienAI.doResponse (FIRE_FRAME == timer2)
→ AlienAI.performAttack
→ AlienAI.attackWithProjectile (responseBehaviour 2/5, bullet non hitscan)
→ AiWorld.spawnAlienProjectile (interface)
→ AiWorldAdapter.spawnAlienProjectile
→ spawnRealAlienBullet (pool branché)
→ alienShotPool.allocate() → AlienShot
→ calcule velocité vers cam.getLocation() avec BULLET_SPEED_CALIBRATION 0.15
Frames suivantes :
AlienBulletUpdateSystem.update
→ pour chaque slot actif : avance, gravity, test joueur, test mur, lifetime
→ si touche joueur : playerHealth.takeDamage(shot.power) + flash impact
→ si touche mur : flash impact + kill
→ si timeout : kill silencieux
Vérifications attendues
| Test | Avant 123 | Après 123 |
|---|---|---|
--test-level ALIEN_GUARD |
HP perdus aléatoirement, aucune balle visible | balles rouge-rose qui voyagent vers le joueur |
| Esquive en bougeant | impossible (placeholder direct damage) | possible (la balle vise la pos courante) |
| Tir alien dans un mur | aucun feedback | flash d’impact + balle disparaît |
--test-level ALIEN_BULLETS |
placeholder 50% silencieux | salve visible de chaque alien armé |
Limitations connues / TODO
- Bullets aliens = sphère placeholder rouge ; les vrais sprites
BulT_AnimData_vb glare.datviendront avec le sprite-billboard generic (post phase 3).- Pas encore de SFX au tir alien (l’AiWorldAdapter
playPositionalSoundest
un no-op tant que l’AudioManager JME n’est pas branché). - Pas de friendly fire : les bullets aliens ne touchent que le joueur
(firedBySlotignoré), conforme à l’ASM original. - Bullets de splash damage (rocket alien) : seul le hit direct fait des dégâts,
pas l’AOE. L’AOE viendra avec le système d’explosion partagé joueur/alien.
Pipeline pour tester
./gradlew compileJava # doit passer
./gradlew run --args="--test-level ALIEN_GUARD" # le plus net
./gradlew run --args="--test-level ALIEN_BULLETS" # multi-aliens
./gradlew run # niveau A standard