package mapPlayer import ( actorRemote "f1-game/internal/actor_remote" "f1-game/internal/code" "f1-game/internal/constant" "f1-game/internal/data" "f1-game/internal/enum" "f1-game/internal/event" "f1-game/internal/extend/math" nameLocal "f1-game/internal/name/local" "f1-game/internal/pb" "f1-game/internal/types" ao "f1-game/nodes/game/player/asset/origin" "f1-game/nodes/map/internal/db" mapFacade "f1-game/nodes/map/internal/facade" "f1-game/nodes/map/player/conscript" cproto "github.com/cherry-game/cherry/net/proto" ) func (p *actorPlayer) initConscript() { p.Local().Register(nameLocal.MapPlayer_ConscriptBegin, p.conscriptBegin) p.Local().Register(nameLocal.MapPlayer_ConscriptCancel, p.conscriptCancel) p.Local().Register(nameLocal.MapPlayer_ConscriptUp, p.conscriptUp) p.Local().Register(nameLocal.MapPlayer_ConscriptUpCancel, p.conscriptUpCancel) p.Local().Register(nameLocal.MapPlayer_ConscriptAuto, p.conscriptAuto) } // 开始征兵 func (p *actorPlayer) conscriptBegin(session *cproto.Session, req *pb.ConscriptRequest) { var ( playerTable = db.GetMapPlayerTable(p.playerID) armID = req.ArmID num = req.Num ) if num <= 0 { p.ResponseCode(session, code.ConscriptNumLack) return } armLevelRow, found := data.ArmLevel.GetByID(armID) if !found { p.ResponseCode(session, code.ConfigNotExist_Conscript) return } // 当前正在士兵升级 if playerTable.Conscripts.IsConscriptUp() { p.ResponseCode(session, code.ConscriptUpgradeHandling) return } // 判断征兵不同士兵 if playerTable.Conscripts.IsNotSameConscript(armID) { p.ResponseCode(session, code.ConscriptHandling) return } // 征兵/升级的等级未解锁 if playerTable.Facilities.CheckAttrsLimit(enum.AttrArmsMaxLevel, armLevelRow.Level) { p.ResponseCode(session, code.ConscriptLevelLimit) return } var ( playerID = playerTable.PlayerID // 获取征兵/升级的兵种ID当前数量 curNum = int32(conscript.Service().GetCurTroopNum(playerID)) total = curNum + num + playerTable.Conscripts.Conscript.ConscriptRemain() ) // 超出最大值 if playerTable.Facilities.CheckAttrsLimit(enum.AttrArmsLimit, total) { p.ResponseCode(session, code.ConscriptNumLimit) return } // 计算征兵/升级消耗 costs := armLevelRow.CalConscriptAssets(int64(num)) _, errCode := mapFacade.Storage.AssetSubs(playerID, costs, ao.ConscriptCost) if code.IsFail(errCode) { p.ResponseCode(session, errCode) return } // 开始征兵/升级 playerTable.Conscripts.StartConscript(armID, num) playerTable.Save2Queue() // 推送给客户端 conscript.Service().Push(playerTable, session) p.ResponseCode(session, code.OK) } // 取消征兵 func (p *actorPlayer) conscriptCancel(session *cproto.Session, req *pb.None) { playerTable := db.GetMapPlayerTable(p.playerID) // 执行取消征兵 errCode := p.doConscriptCancel(playerTable) if code.IsFail(errCode) { p.ResponseCode(session, errCode) return } playerTable.Conscripts.ResetConscript() // 手动取消征兵 才会取消自动征兵功能 playerTable.Conscripts.Conscript.AutoConscript = false playerTable.Save2Queue() conscript.Service().Push(playerTable, session) p.ResponseCode(session, code.OK) } // 执行取消征兵 func (p *actorPlayer) doConscriptCancel(playerTable *db.MapPlayerTable) int32 { // 当前没有任何操作 if playerTable.Conscripts.IsNotConscriptAction() { return code.ConscriptNoAction } // 当前士兵升级中 if playerTable.Conscripts.IsConscriptUp() { return code.ConscriptUpgradeHandling } var ( armID = playerTable.Conscripts.Conscript.ArmID remain = int64(playerTable.Conscripts.Conscript.ConscriptRemain()) ) if remain <= 0 { return code.OK } armLevelRow, found := data.ArmLevel.GetByID(armID) if !found { return code.ConfigNotExist_Conscript } // 按照比例返还征兵材料 returnAssets := armLevelRow.CalConscriptAssets(remain) for _, asset := range returnAssets { num := asset.Num asset.Num = math.Round[float64, int64](float64(num*data.Const.BuildConscriptRefundRatio) / constant.RatioBase) } _, errCode := mapFacade.Storage.AssetAdds(playerTable.PlayerID, returnAssets, ao.ConscriptBack) if code.IsFail(errCode) { return errCode } progress := playerTable.Conscripts.Conscript.Progress if progress > 0 { // 提交事件 p.PostEvent(event.NewConscriptTroopSettle(p.playerID, armID, progress)) // 系统消息 actorRemote.GamePlayer.GamePlayerCallSystemMsg(playerTable.GameNodeID, p.playerID, enum.ChatMsgType_conscript, nil, nil, armID, progress) } // 重置征兵数据 playerTable.Conscripts.ResetConscript() return code.OK } // 士兵升级 func (p *actorPlayer) conscriptUp(session *cproto.Session, req *pb.ConscriptUpRequest) { var ( armID = req.ArmID upArmID = req.UpArmID num = req.Num ) if num <= 0 { p.ResponseCode(session, code.ConscriptUpNumLack) return } armLevelRow, found := data.ArmLevel.GetByID(armID) if !found { p.ResponseCode(session, code.ConfigNotExist_Conscript) return } playerTable := db.GetMapPlayerTable(p.playerID) // 当前正在征兵 if playerTable.Conscripts.IsConscript() { p.ResponseCode(session, code.ConscriptHandling) return } // 判断当前是否相同士兵升级 if playerTable.Conscripts.IsNotSameConscriptUp(armID, upArmID) { p.ResponseCode(session, code.ConscriptUpgradeHandling) return } upArmLevelRow, found := data.ArmLevel.GetByID(upArmID) if !found { p.ResponseCode(session, code.ConfigNotExist_Conscript) return } // 征兵/升级的等级未解锁 if playerTable.Facilities.CheckAttrsLimit(enum.AttrArmsMaxLevel, upArmLevelRow.Level) { p.ResponseCode(session, code.ConscriptLevelLimit) return } var ( // 获取征兵/升级的兵种ID当前数量 curNum = int32(conscript.Service().GetCurTroopNum(p.playerID)) total = curNum + playerTable.Conscripts.ConscriptUp.ConscriptUpRemain() ) // 超出最大值 if playerTable.Facilities.CheckAttrsLimit(enum.AttrArmsLimit, total) { p.ResponseCode(session, code.ConscriptNumLimit) return } // 获取/扣除升级消耗 upCosts := p.calConscriptUpAssets(armLevelRow, upArmLevelRow, int64(num)) upCosts.Add(armID, int64(num)) _, errCode := mapFacade.Storage.AssetSubs(p.playerID, upCosts, ao.ConscriptUpgradeCost) if code.IsFail(errCode) { p.ResponseCode(session, errCode) return } // 开始士兵升级 playerTable.Conscripts.StartConscriptUp(armID, upArmID, num) playerTable.Save2Queue() // 推送给客户端 conscript.Service().Push(playerTable, session) p.ResponseCode(session, code.OK) } // 升级取消 func (p *actorPlayer) conscriptUpCancel(session *cproto.Session, req *pb.None) { playerTable := db.GetMapPlayerTable(p.playerID) if !playerTable.Conscripts.IsConscriptUp() { p.ResponseCode(session, code.ConscriptNotUp) return } // 执行士兵升级取消 errCode := p.doConscriptUpCancel(playerTable) if code.IsFail(errCode) { p.ResponseCode(session, errCode) return } playerTable.Save2Queue() // 推送给客户端 conscript.Service().Push(playerTable, session) p.ResponseCode(session, code.OK) } func (p *actorPlayer) doConscriptUpCancel(playerTable *db.MapPlayerTable) int32 { var ( armID = playerTable.Conscripts.ConscriptUp.ArmID upArmID = playerTable.Conscripts.ConscriptUp.UpArmID remain = int64(playerTable.Conscripts.ConscriptUp.ConscriptUpRemain()) ) if remain <= 0 { return code.OK } armLevelRow, found := data.ArmLevel.GetByID(armID) if !found { return code.ConfigNotExist_Conscript } upArmLevelRow, found := data.ArmLevel.GetByID(upArmID) if !found { return code.ConfigNotExist_Conscript } // 按照比例返还升级材料 returnAssets := p.calConscriptUpAssets(armLevelRow, upArmLevelRow, remain) for _, asset := range returnAssets { num := asset.Num asset.Num = math.Round[float64, int64](float64(num*data.Const.BuildConscriptRefundRatio) / constant.RatioBase) } // 返还升级前士兵按照原数量 returnAssets.Add(armID, remain) _, errCode := mapFacade.Storage.AssetAdds(p.playerID, returnAssets, ao.ConscriptBack) if code.IsFail(errCode) { return errCode } progress := playerTable.Conscripts.ConscriptUp.Progress if progress > 0 { // 提交事件 p.PostEvent(event.NewConscriptTroopSettle(p.playerID, upArmID, progress)) // 系统消息 actorRemote.GamePlayer.GamePlayerCallSystemMsg(playerTable.GameNodeID, p.playerID, enum.ChatMsgType_conscriptUp, nil, nil, upArmID, progress) } // 重置士兵升级数据 playerTable.Conscripts.ResetConscriptUp() return code.OK } // 自动征兵设置 func (p *actorPlayer) conscriptAuto(session *cproto.Session, req *pb.I32) { var ( armID = req.Value playerTable = db.GetMapPlayerTable(p.playerID) autoConscript = !playerTable.Conscripts.Conscript.AutoConscript ) if playerTable.Conscripts.Conscript.ArmID != armID { autoConscript = true } // 执行自动征兵 if autoConscript { if armID <= 0 { p.ResponseCode(session, code.RequestParamsError) return } // 检测是否需要返还征兵材料 errCode := p.checkAutoConscriptReturn(playerTable, armID) if code.IsFail(errCode) { p.ResponseCode(session, errCode) return } // 执行自动征兵逻辑 if ok := conscript.Service().AutoConscript(playerTable, armID); !ok { // 如果因为材料不足而导致自动征兵失败 则设置当前自动征兵的士兵ID 等有材料的时候自动征兵 playerTable.Conscripts.CurState = enum.ConscriptState_Conscript playerTable.Conscripts.Conscript.ArmID = armID } } else { // 当前是征兵状态 且 已完成 清空自动征兵的士兵ID if playerTable.Conscripts.IsConscript() && playerTable.Conscripts.Conscript.IsConscriptFinish() { playerTable.Conscripts.ResetConscript() } } // 设置自动征兵 playerTable.Conscripts.Conscript.AutoConscript = autoConscript playerTable.Save2Queue() // 推送给客户端 conscript.Service().Push(playerTable, session) p.ResponseCode(session, code.OK) } // 检测是否需要返还征兵材料 func (p *actorPlayer) checkAutoConscriptReturn(playerTable *db.MapPlayerTable, armID int32) int32 { if playerTable.Conscripts.IsNotConscriptAction() { return code.OK } // 如果当前是征兵 且征兵士兵ID不相同,则取消原来的兵征兵任务 if playerTable.Conscripts.IsConscript() && playerTable.Conscripts.Conscript.ArmID != armID { return p.doConscriptCancel(playerTable) } // 如果当前是士兵升级逻辑 取消原来的士兵升级任务 if playerTable.Conscripts.IsConscriptUp() { return p.doConscriptUpCancel(playerTable) } return code.OK } func (p *actorPlayer) calConscriptUpAssets(curArmLevelRow *data.ArmLevelRow, upArmLevelRow *data.ArmLevelRow, num int64) types.Assets { var ( assets = curArmLevelRow.CalConscriptAssets(num) upAssets = upArmLevelRow.CalConscriptAssets(num) ) for _, asset := range assets { for _, upAsset := range upAssets { if upAsset.ID == asset.ID { upAsset.Num -= asset.Num } } } finalAssets := types.Assets{} for _, asset := range upAssets { if asset.Num > 0 { finalAssets.Add(asset.ID, asset.Num) } } return finalAssets }