package model import ( "rocommon/util" "roserver/baseserver/model" "roserver/baseserver/set" "roserver/serverproto" ) type EmHeadState int32 const ( Head_Not_Reach1 EmHeadState = iota // 未达成 Head_Not_Activate // 未激活 Head_Wear // 佩戴中 Head_Unload // 卸下中 ) func newRoleHead(r *Role) *RoleHead { roleCommon := &RoleHead{ SaveObject: SaveObject{ role: r, }, headData: map[int32]*serverproto.HeadData{}, taskTypeMap: map[serverproto.TaskType]set.Interface{}, headTime: map[int32]*serverproto.HeadData{}, } roleCommon.curHead = -1 return roleCommon } type RoleHead struct { SaveObject curHead int32 // 不要直接取该值 使用GetHeadIdIng() taskTypeMap map[serverproto.TaskType]set.Interface // 任务检索 (方便检索使用) headTime map[int32]*serverproto.HeadData // 计时称号 headData map[int32]*serverproto.HeadData // 称号数据 } // 加载数据 func (this *RoleHead) Load(msg interface{}) bool { proRole := msg.(*serverproto.Role) head := proRole.RoleHead if head == nil { return false } for _, data := range head.Heads { if data.EndTime > 0 { this.headTime[data.HeadId] = data } this.headData[data.HeadId] = data } //util.InfoF("uid=%v head Load .. list=%v", this.role.GetUUid(), this.headData) return true } // 保存数据 func (this *RoleHead) Save() { this.SetDirty(false) saveMsg := &serverproto.SSHeadDataSaveReq{ Head: &serverproto.RoleHead{}, } for _, data := range this.headData { saveMsg.Head.Heads = append(saveMsg.Head.Heads, data) } this.role.SendDb(saveMsg) //util.InfoF("uid=%v RoleHead save... list=%v", this.role.GetUUid(), saveMsg.Head.Heads) } func (this *RoleHead) DailyReset(notify bool) { state := int32(Head_Not_Reach1) changeHeads := []int32{} for _, db := range model.DbHeadData { if !db.BRestTask { continue } head := this.GetHeadByHeadId(db.HeadId) if head == nil { continue } if head.State > state { continue } this.DelHeadById(db.HeadId) changeHeads = append(changeHeads, db.HeadId) } this.SetDirty(true) this.sendHeadNtf(changeHeads[:]...) } func (this *RoleHead) InitTask() { this.taskTypeMap = map[serverproto.TaskType]set.Interface{} for _, db := range model.DbHeadData { for tType, _ := range db.Condition { taskType := serverproto.TaskType(tType) taskList, ok := this.taskTypeMap[taskType] if !ok { taskList = set.New(set.NonThreadSafe) this.taskTypeMap[taskType] = taskList } data1, ok1 := this.headData[db.HeadId] if !ok1 { data1 = &serverproto.HeadData{HeadId: db.HeadId, TaskData: &serverproto.TaskData{TaskId: uint32(db.HeadId)}} this.headData[db.HeadId] = data1 TaskConditionCheck(this.role, data1.TaskData, serverproto.TaskType_NONE, db.Condition, 0, false) if checkSubConditionState(int32(taskType), data1.TaskData) { data1.State = int32(Head_Not_Activate) data1.TaskData.Reset() } } taskList.Add(data1) } } this.SetDirty(true) } func (this *RoleHead) OnlineProcess() { if len(this.taskTypeMap) <= 0 { this.InitTask() } this.flushAttr() } // 处理任务事件 func (this *RoleHead) TaskCheck(taskType serverproto.TaskType, count int32) { if len(this.taskTypeMap) <= 0 { this.InitTask() } taskList, ok := this.taskTypeMap[taskType] if !ok || taskList.IsEmpty() { return } msg := &serverproto.SCHeadUpdateNtf{} for _, task := range taskList.List() { head := task.(*serverproto.HeadData) if head.State > int32(Head_Not_Reach1) { continue } db := model.DbHeadData[head.HeadId] if db == nil { continue } ret := TaskConditionCheck(this.role, head.TaskData, taskType, db.Condition, count, false) if !ret { continue } if checkSubConditionState(int32(taskType), head.TaskData) { head.State = int32(Head_Not_Activate) head.TaskData.Reset() } msg.Head = append(msg.Head, head) this.SetDirty(true) } if len(msg.Head) > 0 { this.role.ReplayGate(msg, true) } } // 获得当前佩戴的称号ID func (this RoleHead) GetHeadIdIng() int32 { if this.curHead < 0 { this.flushCurHead() } return this.curHead } func (this RoleHead) GetHeadByHeadId(headId int32) *serverproto.HeadData { head, _ := this.headData[headId] return head } func (this *RoleHead) DelHeadById(headId int32) { head, ok := this.headData[headId] if ok { head.TaskData.Reset() } _, ok1 := this.headTime[headId] if ok1 { delete(this.headTime, headId) } util.InfoF("uid=%v DelHeadById %v", this.role.GetUUid(), headId) this.SetDirty(true) } // 外部使用 func (this *RoleHead) SetHeadState(headId int32, state EmHeadState) { head, ok := this.headData[headId] if !ok { util.ErrorF("uid=%v SetHeadState error, %v, %v", this.role.GetUUid(), headId, this.headData) return } // 暂时限制两个状态 if state > Head_Not_Activate { return } head.State = int32(state) this.sendHeadNtf(headId) this.SetDirty(true) } // 激活 func (this *RoleHead) HeadActivate(headId int32) (ret serverproto.ErrorCode) { head := this.GetHeadByHeadId(headId) if head == nil { return serverproto.ErrorCode_ERROR_HEAD_NOT } if head.State != int32(Head_Not_Activate) { return serverproto.ErrorCode_ERROR_HEAD_ACTIVATE } db, ok := model.DbHeadData[headId] if !ok { util.ErrorF("uid=%v HeadActivate error, db not find Head Id %v", this.role.GetUUid(), headId) return serverproto.ErrorCode_ERROR_FAIL } if len(db.ActivateItem) > 0 { if !this.role.roleBag.CanDelItemList(db.ActivateItem) { return serverproto.ErrorCode_ERROR_RES_NOT_ENOUGH } this.role.DelItemList(db.ActivateItem, AddItemST{AddFrom: AddFrom_HeadActivate}) } head.State = int32(Head_Unload) if db.ContinueTime > 0 { head.EndTime = util.GetTimeSeconds() + int64(db.ContinueTime*60*60) this.headTime[db.HeadId] = head } this.flushAttr() this.sendHeadNtf(headId) this.SetDirty(true) util.InfoF("uid=%v HeadActivate %v", this.role.GetUUid(), headId) return serverproto.ErrorCode_ERROR_OK } // 佩戴 func (this *RoleHead) HeadWear(headId int32) (ret serverproto.ErrorCode) { ret = serverproto.ErrorCode_ERROR_FAIL head := this.GetHeadByHeadId(headId) if head == nil { ret = serverproto.ErrorCode_ERROR_HEAD_NOT return } if head.State <= int32(Head_Wear) { ret = serverproto.ErrorCode_ERROR_HEAD_NO_ACTIVATE return } lastHead := this.GetHeadIdIng() curHead := this.GetHeadByHeadId(lastHead) if curHead != nil { curHead.State = int32(Head_Unload) } head.State = int32(Head_Wear) ret = serverproto.ErrorCode_ERROR_OK this.sendHeadNtf(headId, lastHead) this.flushCurHead() this.SetDirty(true) util.InfoF("uid=%v HeadWear %v", this.role.GetUUid(), head) return } // 卸下 func (this *RoleHead) HeadUnload(headId int32) (ret serverproto.ErrorCode) { ret = serverproto.ErrorCode_ERROR_FAIL head := this.GetHeadByHeadId(headId) if head == nil { ret = serverproto.ErrorCode_ERROR_HEAD_NOT return } if head.State != int32(Head_Wear) { ret = serverproto.ErrorCode_ERROR_HEAD_NO_WEAR return } head.State = int32(Head_Unload) ret = serverproto.ErrorCode_ERROR_OK this.sendHeadNtf(headId) this.flushCurHead() this.SetDirty(true) util.InfoF("uid=%v HeadUnload %v", this.role.GetUUid(), head) return } // 时间到期 func (this *RoleHead) TimeOver(headId int32) (ret bool) { head := this.GetHeadByHeadId(headId) if head == nil { return } curTime := util.GetTimeSeconds() if head.EndTime == 0 { return } if head.EndTime > curTime { return } head.State = int32(Head_Not_Reach1) this.DelHeadById(headId) // 处理到期后重新检查任务 db, ok := model.DbHeadData[headId] if ok { for tType, _ := range db.Condition { ret := TaskConditionCheck(this.role, head.TaskData, serverproto.TaskType_NONE, db.Condition, 0, false) if !ret { continue } if checkSubConditionState(int32(tType), head.TaskData) { head.State = int32(Head_Not_Activate) head.TaskData.Reset() } } } this.sendHeadNtf(headId) this.flushCurHead() this.flushAttr() this.SetDirty(true) util.InfoF("uid=%v TimeOver %v", this.role.GetUUid(), head) return true } func (this RoleHead) sendHeadNtf(headIds ...int32) { msg := &serverproto.SCHeadUpdateNtf{} for _, id := range headIds { head := this.GetHeadByHeadId(id) if head == nil { continue } msg.Head = append(msg.Head, head) } this.role.ReplayGate(msg, true) } func (this RoleHead) SendAllHeadData() { ids := []int32{} for id, _ := range this.headData { ids = append(ids, id) } this.sendHeadNtf(ids...) } func (this *RoleHead) Update(ms uint64) { sec := int64(ms / 1000) for _, data := range this.headTime { if data.EndTime > sec { continue } this.TimeOver(data.HeadId) } } func (this *RoleHead) flushCurHead() { this.curHead = 0 for _, head := range this.headData { if head.State != int32(Head_Wear) { continue } this.curHead = head.HeadId break } } func (this *RoleHead) flushAttr() { this.role.roleBattleAttr.AttrChange(AttrChangeST{ ChangeType: Attr_Change_Head, ChangeHeroData: this.role.GetRoleHero().GetMainHero(), }) }