Skip to content

Support Spectres and Companions, and overhaul Spectre Library #936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 78 commits into
base: dev
Choose a base branch
from

Conversation

Blitz54
Copy link
Contributor

@Blitz54 Blitz54 commented Apr 8, 2025

Fixes #930 .

https://docs.google.com/spreadsheets/d/1oadXSCHczpyCgRxzTk3nRBeeOLlefZAzKM3ijwmWevY/edit?gid=0#gid=0
From Reddit and a Youtuber Truditoru. Could be very handy

Description of the problem being solved:

Spectre library did not show, so quick from from @LocalIdentity got it working. Still some smaller bugs, but for now getting some initial spectres in is important.

Exported the experience multiplier and monster category to minions and spectres. The category will be needed for Tame Beast/Companion.

Most skills included. Vaal Guard's skills are similar to player skills that haven't been fully implemented yet either. So when they are updated, Vaal Guard can be too.

Spectre gem costs 50 spirit always. It should be 50 * Monster experience multiplier, rounded to nearest 10. Eg, Dread Servant is 50 * 1.50 = 75. Rounded up to 80 to match in game. Same with Faridun Impaler and Filthy Crone. Both are 50 * 2.30 = 115. In game, both are 120.
https://poe2db.tw/us/Terracotta_Soldier#TerracottaSoldierTerracottaGuardianSceptreAmbush__
This one rounds down to 10 Spirit in game. But PoE2DB shows it as 20 on the site. So I believe the formula just rounds to nearest 10, not round up to nearest 10.

Issues:

EDIT: Tame Beast formula is round(Sqrt(MonsterExperience/100),2) * 30
Adding to the Companion formula. In game it appears to round normally. with 176 spirit, spirit shaman reserves 75 spirit in game. PR #725 changed rounding for both flat and percentage. The issue it closed was for flat, so maybe it's safe to change percentage rounding back to normal? If not, we will have to separate the calcs. For now I returned it to normal rounding.

After screenshot:

image

@Blitz54 Blitz54 added the enhancement New feature, calculation, or mod label Apr 9, 2025
@Blitz54 Blitz54 changed the title Add 4 Spectres and enable library Add 9 Spectres and enable library Apr 11, 2025
@Blitz54 Blitz54 changed the title Add 9 Spectres and enable library Add some Spectres and enable library Apr 28, 2025
@Blitz54 Blitz54 changed the title Add some Spectres and enable library Add some Spectres, enable library, and add calcs for reservation Apr 28, 2025
@Blitz54 Blitz54 changed the title Add some Spectres, enable library, and add calcs for reservation Support Spectres and Companions, and overhaul Spectre Library Jun 7, 2025
@Blitz54 Blitz54 marked this pull request as ready for review June 7, 2025 05:15
Copy link

@DaniilKi DaniilKi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI REVIEW BELOW:

  • 75mins worth of opus4 compute time was used -> with the goal to document the Specter Library changes and review them. Again, everything below is ai generated, tread lightly (still worth reading):

📈 Overall Assessment

This is an impressive, well-executed feature addition. The issues found are mostly safety/polish concerns rather than fundamental problems. The architecture is sound and the implementation follows PoB conventions well.

Recommendation: Merge after confirming the life table change is intentional and adding nil checks. Other issues can be addressed in follow-up PRs.


Technical Documentation: Spectres & Companions Implementation

High-Level Architecture

Core Concept

Spectres and Companions are implemented as special minion types that can be selected from a library of 927 pre-defined monsters. They integrate seamlessly with the existing minion system while adding their own unique mechanics.

Key Components

  1. Skill Identification

    • Skills starting with ^Spectre: are identified as spectre skills
    • Skills starting with ^Companion: are identified as companion/beast skills
    • This allows the system to handle them differently from regular minions
  2. Data Structure

    -- Each spectre/companion has:
    {
      name = "Monster Name",
      life = 1000,
      energyShield = 0,
      armour = 300,
      spectreReservation = 50,  -- Calculated value
      companionReservation = 30, -- Calculated value
      monsterCategory = "Beast",
      spawnLocation = {"The Coast", "The Ledge"},
      skillList = {"MeleeAtAnimationSpeed", "Leap"},
      -- ... more stats
    }
  3. Reservation Formulas

    • Spectres: 50 * ExperienceMultiplier, rounded to nearest 10
    • Companions: round(sqrt(ExperienceMultiplier/100), 2) * 30

Detailed Implementation

UI Flow (MinionListControl)

  1. Library Selection

    • User clicks "Spectre Library" or "Companion Library" button
    • Opens MinionListControl in appropriate mode
  2. Filtering System

    -- Monster type checkboxes:
    - Eldritch
    - Undead  
    - Demon
    - Construct
    - Humanoid
    - Beast
    - Show All
  3. Search & Sort

    • Real-time search across monster names
    • Sort by: Name, Life, Spirit Reservation, Combined HP, ES+Life+Armour
  4. Selection Process

    • User selects monster from filtered/sorted list
    • System updates gemInstance.skillMinion with monster ID
    • Skill gem name updates to show selected monster

Calculation Integration

  1. Life Calculation

    • Uses monsterAllyLifeTable instead of monsterLifeTable
    • Scales with minion life modifiers
  2. Reservation Calculation

    • Integrates with existing reservation system
    • Uses round instead of m_ceil for percentage-based reservations
  3. Stat Inheritance

    • Spectres inherit applicable minion modifiers
    • Energy shield calculation: Type.EnergyShield / 100 (no 0.4 multiplier)

Data Management

  1. Export Process

    Export/Scripts/minions.lua → Data/Minions.lua
    Export/Scripts/spectreList.lua → Data/Spectres.lua
    Export/Scripts/worldAreas.lua → Data/WorldAreas.lua
    
  2. Save Format

    • Only stores spectre/companion ID in builds
    • Full data loaded from static files at runtime
    • Minimizes save file size

Import/Export Support

  1. Build Sharing

    • Spectre selections preserved in build codes
    • Graceful handling of missing spectres in older PoB versions
  2. Validation

    • Checks if selected spectre ID exists in data
    • Falls back to default if invalid

Maintenance Guide

Adding New Spectres

  1. Update Export/Scripts/spectreList.lua with new monster data
  2. Ensure ExperienceMultiplier is set for reservation calculation
  3. Add appropriate skills to skill definitions
  4. Regenerate data files by running export scripts
  5. Test reservation calculations match in-game values

Modifying Formulas

  1. Edit formulas in Export/Scripts/minions.lua
  2. Regenerate Data/Minions.lua
  3. Test with known examples (Dread Servant, Faridun Impaler, etc.)

Debugging Tips

  1. Check skillMinion ID matches entries in data.spectres
  2. Verify WorldAreas is loaded if spawn locations crash
  3. Ensure round() function is available in environment
  4. Monitor performance with large spectre lists

This PR successfully implements a complete spectre/companion system with 927 spectres, proper UI integration, and formula-based reservation calculations. The implementation is well-architected and maintains backward compatibility.

✅ Excellent Implementation

Architecture & Code Quality

  • Clean separation using ^Spectre: and ^Companion: skill patterns
  • Excellent reuse of existing minion infrastructure
  • Well-structured MinionListControl with filtering and sorting
  • Proper data/UI/logic separation across modules

Data & Formulas

  • 927 spectres with comprehensive stats and spawn locations
  • Correct formula implementation in minions.lua:
    spectreReservation = round(50 * math.max(monsterVariety.ExperienceMultiplier/100, 0) / 10) * 10
    companionReservation = round(math.sqrt(monsterVariety.ExperienceMultiplier/100), 2) * 30

🔍 Issues Requiring Attention

Should Fix Before Merge:

  1. Life Table Change

    • Changed from monsterLifeTable to monsterAllyLifeTable
    • This will significantly change spectre HP values
    • Please confirm this is intentional to match game mechanics
  2. Missing nil checks

    • data.spectres[gemInstance.skillMinion] accessed without validation
    • self.data.minions[selected] in UpdateMinionDisplay
    • Add defensive checks to prevent crashes
  3. Round function availability

    • Uses round(value, 2) but Lua doesn't have this natively
    • Confirm it's defined in PoB's Common.lua or add implementation
  4. WorldAreas loading

    • data.worldAreas = {} declared but LoadModule not visible in diff
    • If not loaded elsewhere, tooltips will crash accessing spawn locations

Data Verification:

  1. Faridun Impaler discrepancy

    • Has spectreReservation = 110
    • Your example: 50 * 2.30 = 115 → 120
    • Please verify the ExperienceMultiplier value
  2. Energy Shield calculation (chunk 12)

    • Changed from 0.4 * Type.EnergyShield / 100 to Type.EnergyShield / 100
    • 2.5x increase - please confirm if matching game changes

📊 Performance Considerations

With 927 spectres, consider:

  • Search debouncing (100-200ms) to avoid lag
  • Lookup tables for O(1) name→ID access
  • List virtualization for large dropdowns

📝 ModCache.lua Note

Important: If you modified mod parsing logic, ensure you've regenerated ModCache.lua with Ctrl+F5. We couldn't verify this from the diff alone.

🔄 Intentional Changes Acknowledged

Per your PR description:

  • Rounding change from m_ceil to round for percentage reservations (PR #725 related)
  • Formula: rounds to nearest 10, not always up
  • Both changes appear correctly implemented

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature, calculation, or mod
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Vaal Guard Spectre
2 participants