mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-16 08:52:42 +00:00
Adv 2.0 Phase L2 step 3: arena boss-shaped bestiary
Reshapes the legacy ArenaMonster data into a boss-shaped arenaBosses map of DnDMonsterTemplate entries — the carrier the upcoming resolveArenaBoss (step 4) will hand to runZoneCombat + renderBossOutcome. IDs namespaced "arena_t<tier>_r<round>" so they don't collide with dndBestiary. HP/AC/Attack scale with tier via arenaTierBaseStats; within a tier, BaseLethality biases each monster by a ±30% band so round-1 anchors the bottom of the tier and round-4 the top. Stats are first-pass — final tuning happens during the ARENA_BOSS_FLOW flag soak. arenaBossPhaseTwoAt(tier) gates phase-two narration: T1–T2 = none, T3+ = 50% HP. The T4–T5 flavor barb piggybacks on the existing bossPhaseTwoPool path through ZoneArena. No callers yet — wiring lands in step 4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
// ── Arena Tier & Monster Definitions ────────────────────────────────────────
|
// ── Arena Tier & Monster Definitions ────────────────────────────────────────
|
||||||
//
|
//
|
||||||
// Five tiers, four monsters each. Death chance, rewards, and XP scale with tier.
|
// Five tiers, four monsters each. Death chance, rewards, and XP scale with tier.
|
||||||
@@ -190,6 +192,93 @@ func arenaGetMonster(tier, round int) *ArenaMonster {
|
|||||||
return &t.Monsters[round-1]
|
return &t.Monsters[round-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Adv 2.0 boss-flow bestiary (Phase L2 step 3) ────────────────────────────
|
||||||
|
//
|
||||||
|
// arenaBosses re-shapes the legacy arenaTiers data into boss-shaped
|
||||||
|
// DnDMonsterTemplate entries so resolveArenaBoss (Phase L2 step 4) can
|
||||||
|
// run an arena fight through the same runZoneCombat → renderBossOutcome
|
||||||
|
// flow that zone bosses use. Keyed by arenaBossID(tier, round) — IDs
|
||||||
|
// are namespaced "arena_t<tier>_r<round>" so they don't collide with
|
||||||
|
// dndBestiary keys.
|
||||||
|
//
|
||||||
|
// HP/AC/Attack are first-pass tier-banded values; BaseLethality biases
|
||||||
|
// each monster up or down within its tier band so round-1 is the
|
||||||
|
// weakest fight and round-4 is the cap. Final tuning happens during
|
||||||
|
// the ARENA_BOSS_FLOW flag soak (gogobee_legacy_migration.md §4 Risk).
|
||||||
|
var arenaBosses = map[string]DnDMonsterTemplate{}
|
||||||
|
|
||||||
|
// arenaBossID composes the canonical arena bestiary key.
|
||||||
|
func arenaBossID(tier, round int) string {
|
||||||
|
return fmt.Sprintf("arena_t%d_r%d", tier, round)
|
||||||
|
}
|
||||||
|
|
||||||
|
// arenaBossPhaseTwoAt returns the PhaseTwoAt fraction (of MaxHP) for an
|
||||||
|
// arena fight at the given tier. T1–T2 = no phase two; T3+ = 50% HP.
|
||||||
|
// The T4–T5 flavor barb piggybacks on the standard phase-two narration
|
||||||
|
// path through ZoneArena's bossPhaseTwoPool (populated alongside arena
|
||||||
|
// flavor when those lines land).
|
||||||
|
func arenaBossPhaseTwoAt(tier int) float64 {
|
||||||
|
if tier >= 3 {
|
||||||
|
return 0.5
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// arenaTierBaseStats returns the (HP, AC, Attack, AttackBonus, CR)
|
||||||
|
// baseline for a given arena tier. arenaMonsterToTemplate then biases
|
||||||
|
// HP/Attack by BaseLethality so within-tier ordering matches the legacy
|
||||||
|
// difficulty curve.
|
||||||
|
func arenaTierBaseStats(tier int) (hp, ac, atk, ab int, cr float32) {
|
||||||
|
switch tier {
|
||||||
|
case 1:
|
||||||
|
return 30, 13, 8, 4, 1
|
||||||
|
case 2:
|
||||||
|
return 80, 14, 14, 6, 4
|
||||||
|
case 3:
|
||||||
|
return 160, 15, 22, 7, 8
|
||||||
|
case 4:
|
||||||
|
return 260, 16, 32, 8, 13
|
||||||
|
case 5:
|
||||||
|
return 400, 18, 45, 10, 18
|
||||||
|
}
|
||||||
|
return 30, 13, 8, 4, 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// arenaMonsterToTemplate maps a legacy ArenaMonster onto a
|
||||||
|
// DnDMonsterTemplate. HP/AC/Attack scale with tier; within a tier,
|
||||||
|
// BaseLethality biases the curve via a ±30% band so round-1 sits at
|
||||||
|
// the bottom of the tier and round-4 at the top.
|
||||||
|
func arenaMonsterToTemplate(id string, m ArenaMonster, tier int) DnDMonsterTemplate {
|
||||||
|
hp, ac, atk, ab, cr := arenaTierBaseStats(tier)
|
||||||
|
bias := (m.BaseLethality - 0.5) * 0.6 // ≈ -0.24 .. +0.29
|
||||||
|
hp = int(float64(hp) * (1 + bias))
|
||||||
|
atk = int(float64(atk) * (1 + bias))
|
||||||
|
if hp < 1 {
|
||||||
|
hp = 1
|
||||||
|
}
|
||||||
|
if atk < 1 {
|
||||||
|
atk = 1
|
||||||
|
}
|
||||||
|
return DnDMonsterTemplate{
|
||||||
|
ID: id, Name: m.Name, CR: cr,
|
||||||
|
HP: hp, AC: ac, Attack: atk, AttackBonus: ab, Speed: 12,
|
||||||
|
BlockRate: 0.05,
|
||||||
|
Ability: m.Ability,
|
||||||
|
XPValue: arenaTiers[tier-1].BattleXP * 4,
|
||||||
|
Notes: m.Flavor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for ti, t := range arenaTiers {
|
||||||
|
tier := ti + 1
|
||||||
|
for ri, m := range t.Monsters {
|
||||||
|
id := arenaBossID(tier, ri+1)
|
||||||
|
arenaBosses[id] = arenaMonsterToTemplate(id, m, tier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Arena Death Flavor Text ─────────────────────────────────────────────────
|
// ── Arena Death Flavor Text ─────────────────────────────────────────────────
|
||||||
|
|
||||||
var arenaDeathMessages = []string{
|
var arenaDeathMessages = []string{
|
||||||
|
|||||||
Reference in New Issue
Block a user