fix: sync current handlers, repair relic data and restore visible launcher consoles
This commit is contained in:
1 parent
163d4433e6
commit
74f3c4411b
46 files changed
+4599
-1402
No files matched your search
@@ -13,33 +13,25 @@ import (
|
||||
func init() {
|
||||
handle("StartCocoonStage", func(s *Session, req *goproto.StartCocoonStageCsReq, rsp *goproto.StartCocoonStageScRsp) error {
|
||||
Log(fmt.Sprintf("[BATTLE] StartCocoonStage: CocoonId=%d Wave=%d WorldLevel=%d PropEntityId=%d", req.CocoonId, req.Wave, req.WorldLevel, req.PropEntityId))
|
||||
battleInfo := createBattleInfo(s, 0, 0)
|
||||
normalizeCalyxBattleInfo(battleInfo, req.Wave, req.WorldLevel)
|
||||
CURRENT_BATTLE.Store(s.Token, battleInfo)
|
||||
|
||||
challengeCnt := req.Wave
|
||||
if challengeCnt == 0 {
|
||||
challengeCnt = 1
|
||||
}
|
||||
rsp.Retcode = 0
|
||||
rsp.PropEntityId = req.PropEntityId
|
||||
rsp.CocoonId = req.CocoonId
|
||||
rsp.Wave = req.Wave
|
||||
rsp.ChallengeCnt = challengeCnt
|
||||
battleInfo := createBattleInfo(s, 0, 0)
|
||||
CURRENT_BATTLE.Store(s.Token, battleInfo)
|
||||
rsp.BattleInfo = battleInfo
|
||||
return nil
|
||||
})
|
||||
|
||||
// NOTE: 4.6.51 proto names this message StartQuickCocoonStageCsReq/Rsp
|
||||
// The Go schema names this message StartQuickCocoonStageCsReq/Rsp
|
||||
handleNamed("StartQuickCocoonStage", "StartQuickCocoonStageRsp", func(s *Session, req *goproto.StartQuickCocoonStageCsReq, rsp *goproto.StartQuickCocoonStageRsp) error {
|
||||
Log(fmt.Sprintf("[BATTLE] StartQuickCocoonStage: CocoonId=%d Wave=%d WorldLevel=%d", req.CocoonId, req.Wave, req.WorldLevel))
|
||||
battleInfo := createBattleInfo(s, 0, 0)
|
||||
normalizeCalyxBattleInfo(battleInfo, req.Wave, req.WorldLevel)
|
||||
CURRENT_BATTLE.Store(s.Token, battleInfo)
|
||||
|
||||
rsp.Retcode = 0
|
||||
rsp.CocoonId = req.CocoonId
|
||||
rsp.Wave = req.Wave
|
||||
battleInfo := createBattleInfo(s, 0, 0)
|
||||
CURRENT_BATTLE.Store(s.Token, battleInfo)
|
||||
|
||||
rsp.BattleInfo = battleInfo
|
||||
return nil
|
||||
})
|
||||
@@ -47,7 +39,6 @@ func init() {
|
||||
handleNamed("StartQuickFarmElement", "StartQuickFarmElementRsp", func(s *Session, req *goproto.StartQuickFarmElementCsReq, rsp *goproto.StartQuickFarmElementRsp) error {
|
||||
Log(fmt.Sprintf("[BATTLE] StartQuickFarmElement: FarmID=%d WorldLevel=%d", req.PAOFHFLFFHD, req.WorldLevel))
|
||||
battleInfo := createBattleInfo(s, 0, 0)
|
||||
normalizeCalyxBattleInfo(battleInfo, 1, req.WorldLevel)
|
||||
CURRENT_BATTLE.Store(s.Token, battleInfo)
|
||||
|
||||
rsp.Retcode = 0
|
||||
@@ -115,24 +106,24 @@ func init() {
|
||||
//
|
||||
// อาการ: กดโจมตีใน overworld แล้วกล้องหลุดออกจากตัวละคร
|
||||
//
|
||||
// สาเหตุ (จากโค้ด Rust เดิม): handler ตอบ battle_info + monster_battle_info
|
||||
// สาเหตุ (จากโค้ด Rust เดิม): handler ตอบ_info + monster_battle_info
|
||||
// ให้ client เข้าสู่การต่อสู้กับ target ที่ "ผ่าน filter แบบหลวมๆ"
|
||||
// filter เดิม: id > 30000 (monster ในฉาก) || id < 1000 (avatar entity ของผู้เล่น!)
|
||||
// ถ้า targets ว่างและอยู่ใน arena (entry >= 3000000) ยัง "หลอก" target
|
||||
// เป็น 30001 อีกชั้น
|
||||
// พอ client ได้ battle_info กับ "monster" ที่จริงคือ prop/NPC/ตัวผู้เล่นเอง
|
||||
// หรือ monster ที่ไม่มี event_id มันจะเริ่ม battle transition ที่โหลดไม่สำเร็จ
|
||||
// → battle camera ไม่มี target ให้ตาม → กล้องหลุดจากตัวละคร
|
||||
// พอ client ได้_info กับ "monster" ที่จริงคือ prop/NPC/ตัวผู้เล่นเอง
|
||||
// หรือ monster ที่ไม่มี event_id มันจะเริ่ม transition ที่โหลดไม่สำเร็จ
|
||||
// → camera ไม่มี target ให้ตาม → กล้องหลุดจากตัวละคร
|
||||
//
|
||||
// FIX: ยอมรับเฉพาะ entity ที่ server spawn เป็น "monster จริง" ในฉากปัจจุบัน
|
||||
// (เก็บไว้ใน Session.MonsterEntities ตอน load_scene) ถ้าไม่มี monster จริง
|
||||
// ถูกโจมตี → ตอบ retcode 0 + cast_entity_id เฉยๆ ไม่เข้า battle
|
||||
// ถูกโจมตี → ตอบ retcode 0 + cast_entity_id เฉยๆ ไม่เข้า
|
||||
// client จะเล่นแอนิเมชันตีปกติ กล้องค้างกับตัวละคร
|
||||
// ================================================================
|
||||
handle("SceneCastSkill", func(s *Session, req *goproto.SceneCastSkillCsReq, rsp *goproto.SceneCastSkillScRsp) error {
|
||||
rsp.CastEntityId = req.CastEntityId
|
||||
|
||||
// เฉพาะ monster entity จริงเท่านั้นที่ trigger battle
|
||||
// เฉพาะ monster entity จริงเท่านั้นที่ trigger
|
||||
var targets []uint32
|
||||
seen := map[uint32]bool{}
|
||||
addTarget := func(id uint32) {
|
||||
@@ -149,14 +140,14 @@ func init() {
|
||||
}
|
||||
|
||||
if len(targets) == 0 {
|
||||
// ไม่มี monster จริงถูกตี — ไม่เข้า battle (นี่คือ fix หลัก)
|
||||
// ไม่มี monster จริงถูกตี — ไม่เข้า (นี่คือ fix หลัก)
|
||||
SceneDebugLog("SCENE_CAST_SKILL cast_entity=%d caster=%d skill_index=%d -> no real monster target (battle skipped)",
|
||||
req.CastEntityId, req.CasterId, req.SkillIndex)
|
||||
rsp.Retcode = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
SceneDebugLog("SCENE_CAST_SKILL cast_entity=%d caster=%d -> battle with %d monster(s)",
|
||||
SceneDebugLog("SCENE_CAST_SKILL cast_entity=%d caster=%d -> with %d monster(s)",
|
||||
req.CastEntityId, req.CasterId, len(targets))
|
||||
|
||||
battleInfo := createBattleInfo(s, req.CasterId, req.SkillIndex)
|
||||
@@ -179,39 +170,19 @@ func init() {
|
||||
})
|
||||
|
||||
handle("GetCurBattleInfo", func(s *Session, req *goproto.GetCurBattleInfoCsReq, rsp *goproto.GetCurBattleInfoScRsp) error {
|
||||
// Login queries this even when no battle is active. An absent battle
|
||||
// is a successful empty result, not RET_BATTLE_STAGE_NOT_MATCH.
|
||||
rsp.Retcode = 0
|
||||
if info, ok := CURRENT_BATTLE.Load(s.Token); ok {
|
||||
rsp.Retcode = 0
|
||||
rsp.BattleInfo = info
|
||||
return nil
|
||||
}
|
||||
|
||||
rsp.Retcode = 2000 // RET_BATTLE_STAGE_NOT_MATCH
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func normalizeCalyxBattleInfo(battleInfo *goproto.SceneBattleInfo, reqWave uint32, worldLevel uint32) {
|
||||
if worldLevel > 0 {
|
||||
battleInfo.WorldLevel = worldLevel
|
||||
}
|
||||
if reqWave > 0 && int(reqWave) <= len(battleInfo.MonsterWaveList) {
|
||||
battleInfo.MonsterWaveList = battleInfo.MonsterWaveList[:reqWave]
|
||||
} else if len(battleInfo.MonsterWaveList) > 1 {
|
||||
battleInfo.MonsterWaveList = battleInfo.MonsterWaveList[:1]
|
||||
}
|
||||
battleInfo.JAOIOKBBMFC = uint32(len(battleInfo.MonsterWaveList))
|
||||
for _, w := range battleInfo.MonsterWaveList {
|
||||
// NOTE: In client 4.6.53 GameAssembly.dll 0x166b2fdd, client verifies:
|
||||
// (wave.WaveId & ~8) == 1. If wave_id != 1, it jumps to 0x166b3161
|
||||
// and throws NullReferenceException in AdventureModule.CreateBattleServerCheckResult.
|
||||
// Therefore every wave in Calyx / FarmElement MUST have WaveId = 1 and WaveParam = nil.
|
||||
w.WaveId = 1
|
||||
w.WaveParam = nil
|
||||
w.BattleStageId = battleInfo.StageId
|
||||
}
|
||||
}
|
||||
|
||||
// createBattleInfo is the Go port of battle.rs create_battle_info.
|
||||
// createBattleInfo is the Go port of.rs create_battle_info.
|
||||
func createBattleInfo(s *Session, casterID, skillIndex uint32) *goproto.SceneBattleInfo {
|
||||
player := s.JSON()
|
||||
if player == nil {
|
||||
@@ -431,9 +402,6 @@ func createBattleInfo(s *Session, casterID, skillIndex uint32) *goproto.SceneBat
|
||||
// monsters
|
||||
battleInfo.MonsterWaveList = common.ToSceneMonsterWaves(player.BattleConfig.Monsters)
|
||||
battleInfo.JAOIOKBBMFC = uint32(len(battleInfo.MonsterWaveList))
|
||||
for _, wave := range battleInfo.MonsterWaveList {
|
||||
wave.BattleStageId = battleInfo.StageId
|
||||
}
|
||||
|
||||
// global buffs
|
||||
hasCastorice, hasSilverWolf := false, false
|
||||
|
||||
Reference in new issue
Block a user