fixing leveling xp reporting
This commit is contained in:
@@ -35,7 +35,8 @@ class Character:
|
||||
player_class: Character's class (determines base stats and skill trees)
|
||||
origin: Character's backstory origin (saved for AI DM narrative hooks)
|
||||
level: Current level
|
||||
experience: Current XP points
|
||||
experience: Current XP progress toward next level (resets on level-up)
|
||||
total_xp: Cumulative XP earned across all levels (never decreases)
|
||||
base_stats: Base stats (from class + level-ups)
|
||||
unlocked_skills: List of skill_ids that have been unlocked
|
||||
inventory: All items the character owns
|
||||
@@ -53,7 +54,8 @@ class Character:
|
||||
player_class: PlayerClass
|
||||
origin: Origin
|
||||
level: int = 1
|
||||
experience: int = 0
|
||||
experience: int = 0 # Current level progress (resets on level-up)
|
||||
total_xp: int = 0 # Cumulative XP (never decreases)
|
||||
|
||||
# Stats and progression
|
||||
base_stats: Stats = field(default_factory=Stats)
|
||||
@@ -315,6 +317,9 @@ class Character:
|
||||
"""
|
||||
Add experience points and check for level up.
|
||||
|
||||
Updates both current level progress (experience) and cumulative total (total_xp).
|
||||
The cumulative total never decreases, providing players a sense of overall progression.
|
||||
|
||||
Args:
|
||||
xp: Amount of experience to add
|
||||
|
||||
@@ -322,6 +327,7 @@ class Character:
|
||||
True if character leveled up, False otherwise
|
||||
"""
|
||||
self.experience += xp
|
||||
self.total_xp += xp # Track cumulative XP (never decreases)
|
||||
required_xp = self._calculate_xp_for_next_level()
|
||||
|
||||
if self.experience >= required_xp:
|
||||
@@ -334,15 +340,18 @@ class Character:
|
||||
"""
|
||||
Level up the character.
|
||||
|
||||
- Increases level
|
||||
- Resets experience to overflow amount
|
||||
- Increases level by 1
|
||||
- Resets experience to overflow amount (XP beyond requirement carries over)
|
||||
- Preserves total_xp (cumulative XP is never modified here)
|
||||
- Grants 1 skill point (level - unlocked_skills count)
|
||||
- Could grant stat increases (future enhancement)
|
||||
"""
|
||||
required_xp = self._calculate_xp_for_next_level()
|
||||
overflow_xp = self.experience - required_xp
|
||||
|
||||
self.level += 1
|
||||
self.experience = overflow_xp
|
||||
self.experience = overflow_xp # Reset current level progress
|
||||
# total_xp remains unchanged - it's cumulative and never decreases
|
||||
|
||||
# Future: Apply stat increases based on class
|
||||
# For now, stats are increased manually via skill points
|
||||
@@ -359,6 +368,19 @@ class Character:
|
||||
"""
|
||||
return int(100 * (self.level ** 1.5))
|
||||
|
||||
@property
|
||||
def xp_to_next_level(self) -> int:
|
||||
"""
|
||||
Get XP remaining until next level.
|
||||
|
||||
This is a computed property for UI display showing progress bars
|
||||
and "X/Y XP to next level" displays.
|
||||
|
||||
Returns:
|
||||
Amount of XP needed to reach next level
|
||||
"""
|
||||
return self._calculate_xp_for_next_level() - self.experience
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Serialize character to dictionary for JSON storage.
|
||||
@@ -374,6 +396,9 @@ class Character:
|
||||
"origin": self.origin.to_dict(),
|
||||
"level": self.level,
|
||||
"experience": self.experience,
|
||||
"total_xp": self.total_xp,
|
||||
"xp_to_next_level": self.xp_to_next_level,
|
||||
"xp_required_for_next_level": self._calculate_xp_for_next_level(),
|
||||
"base_stats": self.base_stats.to_dict(),
|
||||
"unlocked_skills": self.unlocked_skills,
|
||||
"inventory": [item.to_dict() for item in self.inventory],
|
||||
@@ -465,6 +490,7 @@ class Character:
|
||||
origin=origin,
|
||||
level=data.get("level", 1),
|
||||
experience=data.get("experience", 0),
|
||||
total_xp=data.get("total_xp", 0), # Default 0 for legacy data
|
||||
base_stats=base_stats,
|
||||
unlocked_skills=data.get("unlocked_skills", []),
|
||||
inventory=inventory,
|
||||
|
||||
@@ -1261,7 +1261,12 @@ class CombatService:
|
||||
xp_per_player = rewards.experience // max(1, len(player_combatants))
|
||||
gold_per_player = rewards.gold // max(1, len(player_combatants))
|
||||
|
||||
for player in player_combatants:
|
||||
# Distribute items evenly among players
|
||||
# For simplicity, give all items to each player in solo mode,
|
||||
# or distribute round-robin in multiplayer
|
||||
items_to_distribute = [Item.from_dict(item_dict) for item_dict in rewards.items]
|
||||
|
||||
for i, player in enumerate(player_combatants):
|
||||
if session.is_solo():
|
||||
char_id = session.solo_character_id
|
||||
else:
|
||||
@@ -1278,6 +1283,18 @@ class CombatService:
|
||||
# Add gold
|
||||
character.gold += gold_per_player
|
||||
|
||||
# Distribute items
|
||||
if session.is_solo():
|
||||
# Solo mode: give all items to the character
|
||||
for item in items_to_distribute:
|
||||
character.add_item(item)
|
||||
else:
|
||||
# Multiplayer: distribute items round-robin
|
||||
# Player i gets items at indices i, i+n, i+2n, etc.
|
||||
for idx, item in enumerate(items_to_distribute):
|
||||
if idx % len(player_combatants) == i:
|
||||
character.add_item(item)
|
||||
|
||||
# Save character
|
||||
self.character_service.update_character(character, user_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user