refactor: 删除战斗模块冗余代码,增加克洛斯地心入口
- 移除了 fight 包下多个冗余的结构体和接口定义 - 删除了未使用的战斗状态机和技能限制效果相关代码 - 移除了多余的 XML 注释内容
This commit is contained in:
54
logic/service/fight/battle/effect/EnumEffectTrigger.go
Normal file
54
logic/service/fight/battle/effect/EnumEffectTrigger.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package effect
|
||||
|
||||
import "github.com/tnnmigga/enum"
|
||||
|
||||
type EnumEffectTrigger string
|
||||
|
||||
var EffectTrigger = enum.New[struct {
|
||||
OnBattleStart EnumEffectTrigger `enum:"OnBattleStart"` // 战斗开始时触发
|
||||
BeforeSort EnumEffectTrigger `enum:"BeforeSort"` // 先手顺序判定前触发
|
||||
BeforeUseSkillCheck EnumEffectTrigger `enum:"BeforeUseSkillCheck"` // 使用技能前检查(PP、状态等)
|
||||
AfterUseSkillCheck EnumEffectTrigger `enum:"AfterUseSkillCheck"` // 使用技能检查后触发
|
||||
BeforeMultiHit EnumEffectTrigger `enum:"BeforeMultiHit"` // 多段攻击开始前触发
|
||||
BeforeHit EnumEffectTrigger `enum:"BeforeHit"` // 攻击命中前触发
|
||||
OnCritPreDamage EnumEffectTrigger `enum:"OnCritPreDamage"` // 暴击判定成功且伤害计算前触发
|
||||
PreDamage EnumEffectTrigger `enum:"PreDamage"` // 技能伤害计算前触发(增伤/减伤等)
|
||||
OnHit EnumEffectTrigger `enum:"OnHit"` // 技能命中时触发
|
||||
OnMiss EnumEffectTrigger `enum:"OnMiss"` // 技能未命中时触发
|
||||
AfterAttacked EnumEffectTrigger `enum:"AfterAttacked"` // 被攻击后触发(受击判定)
|
||||
OnDefeat EnumEffectTrigger `enum:"OnDefeat"` // 精灵被击败时触发
|
||||
SkillUseEnd EnumEffectTrigger `enum:"SkillUseEnd"` // 技能使用结束后触发
|
||||
OnBeforeCalculateDamage EnumEffectTrigger `enum:"OnBeforeCalculateDamage"` // 最终伤害计算前触发
|
||||
OnDamage EnumEffectTrigger `enum:"OnDamage"` // 造成伤害时触发
|
||||
Shield EnumEffectTrigger `enum:"Shield"` // 护盾值变化时触发
|
||||
PostDamage EnumEffectTrigger `enum:"PostDamage"` // 伤害结算后触发(血量扣除后)
|
||||
OnCritPostDamage EnumEffectTrigger `enum:"OnCritPostDamage"` // 暴击伤害结算后触发
|
||||
OnTransform EnumEffectTrigger `enum:"OnTransform"` // 精灵变形/进化时触发
|
||||
OnTransformEnd EnumEffectTrigger `enum:"OnTransformEnd"` // 变形/进化结束时触发
|
||||
BeforeTransform EnumEffectTrigger `enum:"BeforeTransform"` // 变形/进化前触发
|
||||
AfterTransform EnumEffectTrigger `enum:"AfterTransform"` // 变形/进化后触发
|
||||
TurnStart EnumEffectTrigger `enum:"TurnStart"` // 回合开始时触发
|
||||
TurnEnd EnumEffectTrigger `enum:"TurnEnd"` // 回合结束时触发
|
||||
OnBeforeAddMark EnumEffectTrigger `enum:"OnBeforeAddMark"` // 添加印记前触发
|
||||
OnAnyMarkAdded EnumEffectTrigger `enum:"OnAnyMarkAdded"` // 任何印记添加时触发
|
||||
OnRemoveMark EnumEffectTrigger `enum:"OnRemoveMark"` // 移除印记时触发
|
||||
OnMarkCreated EnumEffectTrigger `enum:"OnMarkCreated"` // 印记创建时触发
|
||||
OnMarkDestroy EnumEffectTrigger `enum:"OnMarkDestroy"` // 印记销毁时触发
|
||||
OnMarkDurationEnd EnumEffectTrigger `enum:"OnMarkDurationEnd"` // 印记持续回合结束时触发
|
||||
OnStackBefore EnumEffectTrigger `enum:"OnStackBefore"` // 堆叠效果前触发
|
||||
OnStack EnumEffectTrigger `enum:"OnStack"` // 堆叠效果触发
|
||||
OnBeforeConsumeStack EnumEffectTrigger `enum:"OnBeforeConsumeStack"` // 消耗堆叠前触发
|
||||
OnConsumeStack EnumEffectTrigger `enum:"OnConsumeStack"` // 消耗堆叠时触发
|
||||
OnBeforeHeal EnumEffectTrigger `enum:"OnBeforeHeal"` // 治疗前触发
|
||||
OnHeal EnumEffectTrigger `enum:"OnHeal"` // 治疗生效时触发
|
||||
BeforeRageGain EnumEffectTrigger `enum:"BeforeRageGain"` // 增怒前触发
|
||||
BeforeRageLoss EnumEffectTrigger `enum:"BeforeRageLoss"` // 减怒前触发
|
||||
OnRageGain EnumEffectTrigger `enum:"OnRageGain"` // 增怒时触发
|
||||
OnRageLoss EnumEffectTrigger `enum:"OnRageLoss"` // 减怒时触发
|
||||
OnSwitchIn EnumEffectTrigger `enum:"OnSwitchIn"` // 精灵出战/上场时触发
|
||||
OnSwitchOut EnumEffectTrigger `enum:"OnSwitchOut"` // 精灵下场时触发
|
||||
OnOwnerSwitchIn EnumEffectTrigger `enum:"OnOwnerSwitchIn"` // 所属玩家精灵出战时触发
|
||||
OnOwnerSwitchOut EnumEffectTrigger `enum:"OnOwnerSwitchOut"` // 所属玩家精灵下场时触发
|
||||
BeforeEffect EnumEffectTrigger `enum:"BeforeEffect"` // 效果生效前触发
|
||||
AfterEffect EnumEffectTrigger `enum:"AfterEffect"` // 效果生效后触发
|
||||
}]()
|
||||
215
logic/service/fight/battle/effect/effect.go
Normal file
215
logic/service/fight/battle/effect/effect.go
Normal file
@@ -0,0 +1,215 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/badu/bus"
|
||||
"github.com/tnnmigga/enum"
|
||||
)
|
||||
|
||||
// ========================
|
||||
// BattleMode 枚举
|
||||
// ========================
|
||||
|
||||
type EnumBattleMode string
|
||||
|
||||
var BattleMode = enum.New[struct {
|
||||
PVE EnumBattleMode `enum:"3"`
|
||||
PVP EnumBattleMode `enum:"1"`
|
||||
}]()
|
||||
|
||||
// ========================
|
||||
// Effect 框架
|
||||
// ========================
|
||||
|
||||
type ContextType interface {
|
||||
SourceID() string
|
||||
}
|
||||
|
||||
type EffectContext struct {
|
||||
Parent ContextType
|
||||
Trigger EnumEffectTrigger
|
||||
Container *EffectContainer
|
||||
Effect *Effect
|
||||
Available bool
|
||||
Success bool
|
||||
Done bool
|
||||
}
|
||||
|
||||
func (c *EffectContext) Stop() { c.Done = true }
|
||||
func (c *EffectContext) SourceID() string {
|
||||
if c.Container != nil {
|
||||
return c.Container.ID
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
type EffectFunc func(ctx *EffectContext, next func())
|
||||
|
||||
type Effect struct {
|
||||
ID string
|
||||
Priority int
|
||||
Triggers []EnumEffectTrigger
|
||||
Condition func(*EffectContext) bool
|
||||
Apply EffectFunc
|
||||
}
|
||||
|
||||
type EffectContainer struct {
|
||||
ID string
|
||||
Effects []*Effect
|
||||
Subs []*bus.Listener[*EffectContext]
|
||||
Battle *Battle
|
||||
Parent ContextType
|
||||
}
|
||||
|
||||
func NewEffectContainer(id string, effects []*Effect, battle *Battle, parent ContextType) *EffectContainer {
|
||||
c := &EffectContainer{
|
||||
ID: id,
|
||||
Effects: effects,
|
||||
Battle: battle,
|
||||
Parent: parent,
|
||||
}
|
||||
// 自动订阅 triggers
|
||||
for _, e := range effects {
|
||||
for _, trig := range e.Triggers {
|
||||
sub := battle.GetTopic(trig).Sub(func(ctx *EffectContext) {
|
||||
if ctx.Available && e.Apply != nil {
|
||||
ctx.Effect = e
|
||||
c.executeWithPriority([]*EffectContext{ctx})
|
||||
}
|
||||
})
|
||||
c.Subs = append(c.Subs, sub)
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// done/next 执行队列,按优先级
|
||||
func (c *EffectContainer) executeWithPriority(queue []*EffectContext) {
|
||||
sort.SliceStable(queue, func(i, j int) bool {
|
||||
return queue[i].Effect.Priority > queue[j].Effect.Priority
|
||||
})
|
||||
var runNext func(idx int)
|
||||
runNext = func(idx int) {
|
||||
if idx >= len(queue) {
|
||||
return
|
||||
}
|
||||
ctx := queue[idx]
|
||||
if ctx.Available {
|
||||
ctx.Effect.Apply(ctx, func() {
|
||||
runNext(idx + 1)
|
||||
})
|
||||
} else {
|
||||
runNext(idx + 1)
|
||||
}
|
||||
}
|
||||
runNext(0)
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Battle
|
||||
// ========================
|
||||
|
||||
type Battle struct {
|
||||
Turn int
|
||||
topics map[EnumEffectTrigger]*bus.Topic[*EffectContext]
|
||||
}
|
||||
|
||||
func NewBattle() *Battle {
|
||||
allTriggers := []EnumEffectTrigger{
|
||||
EffectTrigger.OnBattleStart,
|
||||
EffectTrigger.BeforeSort,
|
||||
EffectTrigger.BeforeUseSkillCheck,
|
||||
EffectTrigger.AfterUseSkillCheck,
|
||||
EffectTrigger.BeforeMultiHit,
|
||||
EffectTrigger.BeforeHit,
|
||||
EffectTrigger.OnCritPreDamage,
|
||||
EffectTrigger.PreDamage,
|
||||
EffectTrigger.OnHit,
|
||||
EffectTrigger.OnMiss,
|
||||
EffectTrigger.AfterAttacked,
|
||||
EffectTrigger.OnDefeat,
|
||||
EffectTrigger.SkillUseEnd,
|
||||
EffectTrigger.OnBeforeCalculateDamage,
|
||||
EffectTrigger.OnDamage,
|
||||
EffectTrigger.Shield,
|
||||
EffectTrigger.PostDamage,
|
||||
EffectTrigger.OnCritPostDamage,
|
||||
EffectTrigger.OnTransform,
|
||||
EffectTrigger.OnTransformEnd,
|
||||
EffectTrigger.BeforeTransform,
|
||||
EffectTrigger.AfterTransform,
|
||||
EffectTrigger.TurnStart,
|
||||
EffectTrigger.TurnEnd,
|
||||
EffectTrigger.OnBeforeAddMark,
|
||||
EffectTrigger.OnAnyMarkAdded,
|
||||
EffectTrigger.OnRemoveMark,
|
||||
EffectTrigger.OnMarkCreated,
|
||||
EffectTrigger.OnMarkDestroy,
|
||||
EffectTrigger.OnMarkDurationEnd,
|
||||
EffectTrigger.OnStackBefore,
|
||||
EffectTrigger.OnStack,
|
||||
EffectTrigger.OnBeforeConsumeStack,
|
||||
EffectTrigger.OnConsumeStack,
|
||||
EffectTrigger.OnBeforeHeal,
|
||||
EffectTrigger.OnHeal,
|
||||
EffectTrigger.BeforeRageGain,
|
||||
EffectTrigger.BeforeRageLoss,
|
||||
EffectTrigger.OnRageGain,
|
||||
EffectTrigger.OnRageLoss,
|
||||
EffectTrigger.OnSwitchIn,
|
||||
EffectTrigger.OnSwitchOut,
|
||||
EffectTrigger.OnOwnerSwitchIn,
|
||||
EffectTrigger.OnOwnerSwitchOut,
|
||||
EffectTrigger.BeforeEffect,
|
||||
EffectTrigger.AfterEffect,
|
||||
}
|
||||
topics := make(map[EnumEffectTrigger]*bus.Topic[*EffectContext])
|
||||
for _, trig := range allTriggers {
|
||||
topics[trig] = bus.NewTopic[*EffectContext]()
|
||||
}
|
||||
return &Battle{Turn: 0, topics: topics}
|
||||
}
|
||||
|
||||
func (b *Battle) GetTopic(trig EnumEffectTrigger) *bus.Topic[*EffectContext] {
|
||||
return b.topics[trig]
|
||||
}
|
||||
|
||||
func (b *Battle) NextTurn(containers []*EffectContainer) {
|
||||
b.Turn++
|
||||
fmt.Printf("=== 回合 %d 开始 ===\n", b.Turn)
|
||||
b.PublishTrigger(EffectTrigger.TurnStart, containers)
|
||||
fmt.Println("=== 玩家操作阶段 ===")
|
||||
b.PublishTrigger(EffectTrigger.TurnEnd, containers)
|
||||
fmt.Printf("=== 回合 %d 结束 ===\n\n", b.Turn)
|
||||
}
|
||||
|
||||
func (b *Battle) PublishTrigger(trigger EnumEffectTrigger, containers []*EffectContainer) {
|
||||
for _, c := range containers {
|
||||
for _, e := range c.Effects {
|
||||
for _, t := range e.Triggers {
|
||||
if t == trigger {
|
||||
ctx := &EffectContext{
|
||||
Parent: c.Parent,
|
||||
Trigger: trigger,
|
||||
Container: c,
|
||||
Effect: e,
|
||||
Available: true,
|
||||
}
|
||||
b.GetTopic(trigger).Pub(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========================
|
||||
// 示例
|
||||
// ========================
|
||||
|
||||
type Player struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
func (p *Player) SourceID() string { return p.ID }
|
||||
40
logic/service/fight/battle/effect/effect_test.go
Normal file
40
logic/service/fight/battle/effect/effect_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package effect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_mainTT(t *testing.T) {
|
||||
battle := NewBattle()
|
||||
player := &Player{ID: "player1"}
|
||||
|
||||
container := NewEffectContainer("container1", []*Effect{
|
||||
{
|
||||
ID: "startEffect",
|
||||
Priority: 10,
|
||||
Triggers: []EnumEffectTrigger{EffectTrigger.TurnStart},
|
||||
Apply: func(ctx *EffectContext, next func()) {
|
||||
fmt.Println("回合开始效果: 增加护盾")
|
||||
next()
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "endEffect",
|
||||
Priority: 5,
|
||||
Triggers: []EnumEffectTrigger{EffectTrigger.TurnEnd},
|
||||
Apply: func(ctx *EffectContext, next func()) {
|
||||
fmt.Println("回合结束效果: 恢复怒气")
|
||||
next()
|
||||
},
|
||||
},
|
||||
}, battle, player)
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
battle.NextTurn([]*EffectContainer{container})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
fmt.Println("测试 BattleMode 枚举:", BattleMode.PVE, BattleMode.PVP)
|
||||
}
|
||||
@@ -6,6 +6,6 @@ import "github.com/tnnmigga/enum"
|
||||
type EnumBattleMode int
|
||||
|
||||
var BattleMode = enum.New[struct {
|
||||
PVE EnumBattleMode // 玩家 vs AI
|
||||
PVP EnumBattleMode // 玩家 vs 玩家
|
||||
PVE EnumBattleMode `enum:"3"`
|
||||
PVP EnumBattleMode `enum:"1"`
|
||||
}]()
|
||||
244
logic/service/fight/md/elo-rating-system.md
Normal file
244
logic/service/fight/md/elo-rating-system.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# ELO评级系统
|
||||
|
||||
## 概述
|
||||
|
||||
为匹配框架引入了ELO评级系统,为每个规则集单独维护ELO评级,提供更精确的玩家技能评估和匹配质量。
|
||||
|
||||
## 核心特性
|
||||
|
||||
### 🎯 规则集分离
|
||||
- 每个规则集(如休闲模式、竞技模式)独立维护ELO评级
|
||||
- 玩家在不同规则集下有不同的ELO分数
|
||||
- 支持无限扩展新的规则集
|
||||
|
||||
### 📊 标准ELO算法
|
||||
- 基于经典ELO评级系统
|
||||
- 期望得分计算:`1 / (1 + 10^((对手ELO - 自己ELO) / 400))`
|
||||
- 新ELO = 旧ELO + K * (实际得分 - 期望得分)
|
||||
- 支持胜利(1分)、失败(0分)、平局(0.5分)
|
||||
|
||||
### ⚙️ 动态K因子
|
||||
- **新手** (< 30场): K = 32 (快速调整)
|
||||
- **普通** (30-100场): K = 24 (中等调整)
|
||||
- **老手** (> 100场): K = 16 (稳定调整)
|
||||
|
||||
### 🛡️ 安全边界
|
||||
- ELO范围:100 - 3000
|
||||
- 初始ELO:1200
|
||||
- 自动记录历史最高ELO
|
||||
|
||||
## 数据库设计
|
||||
|
||||
### player_elo_ratings 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE player_elo_ratings (
|
||||
player_id TEXT NOT NULL, -- 玩家ID
|
||||
rule_set_id TEXT NOT NULL, -- 规则集ID
|
||||
elo_rating INTEGER DEFAULT 1200, -- 当前ELO评级
|
||||
games_played INTEGER DEFAULT 0, -- 游戏场次
|
||||
wins INTEGER DEFAULT 0, -- 胜利次数
|
||||
losses INTEGER DEFAULT 0, -- 失败次数
|
||||
draws INTEGER DEFAULT 0, -- 平局次数
|
||||
highest_elo INTEGER DEFAULT 1200, -- 历史最高ELO
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY (player_id, rule_set_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 核心函数
|
||||
|
||||
- `get_or_create_player_elo()` - 获取或创建ELO记录
|
||||
- `update_player_elo()` - 更新单个玩家ELO
|
||||
- `batch_update_player_elos()` - 批量更新ELO(战斗结束)
|
||||
- `get_elo_leaderboard()` - 获取排行榜
|
||||
|
||||
## API端点
|
||||
|
||||
### 排行榜
|
||||
```
|
||||
GET /api/v1/elo/leaderboard/:ruleSetId?limit=50&offset=0
|
||||
```
|
||||
|
||||
### 玩家ELO信息
|
||||
```
|
||||
GET /api/v1/elo/player/:playerId/:ruleSetId
|
||||
GET /api/v1/elo/player/:playerId # 所有规则集
|
||||
```
|
||||
|
||||
### 统计信息
|
||||
```
|
||||
GET /api/v1/elo/statistics/:ruleSetId
|
||||
```
|
||||
|
||||
### 战斗预测
|
||||
```
|
||||
GET /api/v1/elo/predict/:playerAId/:playerBId/:ruleSetId
|
||||
```
|
||||
|
||||
### 配置信息
|
||||
```
|
||||
GET /api/v1/elo/config
|
||||
GET /api/v1/elo/win-rate/:eloDifference
|
||||
```
|
||||
|
||||
## 系统集成
|
||||
|
||||
### 战斗结束自动更新
|
||||
|
||||
战斗结束时,`battleReportService` 会自动:
|
||||
|
||||
1. 获取两个玩家的当前ELO
|
||||
2. 根据战斗结果计算新ELO
|
||||
3. 原子性批量更新数据库
|
||||
4. 记录详细日志
|
||||
|
||||
```typescript
|
||||
// 在 battleReportService.ts 中
|
||||
if (battleData.ruleSetId && battleResult !== 'abandoned') {
|
||||
await eloService.processBattleEloUpdate(
|
||||
battleData.playerAId,
|
||||
battleData.playerBId,
|
||||
winnerId,
|
||||
battleData.ruleSetId
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 匹配系统集成
|
||||
|
||||
匹配系统已支持规则集分离,ELO系统可以:
|
||||
|
||||
- 基于ELO进行更精确的匹配
|
||||
- 预测战斗结果概率
|
||||
- 提供匹配质量评估
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 数据库迁移
|
||||
|
||||
在Supabase SQL编辑器中执行:
|
||||
|
||||
```sql
|
||||
-- 执行ELO系统迁移
|
||||
\i packages/database/sql/06_add_elo_system.sql
|
||||
```
|
||||
|
||||
### 2. 服务器更新
|
||||
|
||||
ELO系统已集成到现有服务器中,无需额外配置。
|
||||
|
||||
### 3. 测试验证
|
||||
|
||||
```bash
|
||||
# 测试ELO计算逻辑
|
||||
cd packages/server && npx tsx src/test-elo.ts
|
||||
|
||||
# 启动服务器测试API
|
||||
node dist/cli.js server --port 8102
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 获取排行榜
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8102/api/v1/elo/leaderboard/casual_standard_ruleset?limit=10"
|
||||
```
|
||||
|
||||
### 查看玩家ELO
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8102/api/v1/elo/player/player123/casual_standard_ruleset"
|
||||
```
|
||||
|
||||
### 预测战斗结果
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8102/api/v1/elo/predict/player1/player2/competitive_ruleset"
|
||||
```
|
||||
|
||||
## 配置选项
|
||||
|
||||
ELO系统支持运行时配置调整:
|
||||
|
||||
```typescript
|
||||
const eloService = new EloService(repository, calculationService)
|
||||
|
||||
// 更新配置
|
||||
eloService.updateEloConfig({
|
||||
initialElo: 1500,
|
||||
kFactor: {
|
||||
newbie: 40,
|
||||
normal: 20,
|
||||
veteran: 10
|
||||
},
|
||||
minElo: 200,
|
||||
maxElo: 2800
|
||||
})
|
||||
```
|
||||
|
||||
## 监控和日志
|
||||
|
||||
### 日志记录
|
||||
|
||||
- ELO更新详细日志
|
||||
- 计算过程追踪
|
||||
- 错误处理和恢复
|
||||
|
||||
### 性能监控
|
||||
|
||||
- 数据库查询优化
|
||||
- 批量更新性能
|
||||
- API响应时间
|
||||
|
||||
## 未来扩展
|
||||
|
||||
### 可能的增强功能
|
||||
|
||||
1. **季度重置** - 定期重置ELO评级
|
||||
2. **衰减机制** - 长期不活跃玩家ELO衰减
|
||||
3. **匹配优化** - 基于ELO的智能匹配
|
||||
4. **成就系统** - ELO里程碑奖励
|
||||
5. **数据分析** - ELO分布统计和趋势分析
|
||||
|
||||
### 扩展新规则集
|
||||
|
||||
添加新规则集只需:
|
||||
|
||||
1. 在规则系统中定义新规则集
|
||||
2. ELO系统自动支持(无需代码修改)
|
||||
3. 玩家首次游戏时自动创建ELO记录
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **ELO记录不存在**
|
||||
- 系统会自动创建初始记录
|
||||
- 检查规则集ID是否正确
|
||||
|
||||
2. **ELO更新失败**
|
||||
- 检查数据库连接
|
||||
- 查看服务器日志
|
||||
- 验证战斗数据完整性
|
||||
|
||||
3. **API响应错误**
|
||||
- 确认数据库迁移已执行
|
||||
- 检查API路由注册
|
||||
- 验证请求参数格式
|
||||
|
||||
### 调试工具
|
||||
|
||||
```bash
|
||||
# 测试ELO计算
|
||||
npx tsx packages/server/src/test-elo.ts
|
||||
|
||||
# 检查数据库表
|
||||
SELECT * FROM player_elo_ratings LIMIT 10;
|
||||
|
||||
# 查看API状态
|
||||
curl "http://localhost:8102/api/v1/elo/config"
|
||||
```
|
||||
@@ -8,6 +8,7 @@ des 鼠标移上去的提示
|
||||
<!-- 从场景FromMap进入本场景时,玩家将出现在 (PosX, PosY)
|
||||
<Entries>节点下的表示几个进出点玩家出现的坐标
|
||||
<changeMapComp>节点下表示切换场景组件
|
||||
|
||||
<funComp>节点下表示点击,然后走近触发某个动作
|
||||
<autoComp>节点下表示不需要点击,走到碰撞区域就触发的动作
|
||||
-->
|
||||
|
||||
Reference in New Issue
Block a user