2025-11-05 18:30:03 +08:00

1126 lines
35 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package model
import (
"math"
"rocommon/util"
"roserver/baseserver/model"
"roserver/baseserver/set"
"roserver/serverproto"
"strings"
)
type AddFromType int32
const (
AddFrom_System AddFromType = iota
AddFrom_Battle
AddFrom_Task
AddFrom_Card_Decompose
AddFrom_Battle_Box //4 寻宝
AddFrom_Quick_Battle //5 快速战斗
AddFrom_Mail //6 邮件
AddFrom_Fashion //7 时装
AddFrom_Shop_Buy //8 杂货店
AddFrom_Arena //9 arena
AddFrom_Package //10 来自礼包
AddFrom_SignUp //11 签到
AddFrom_WorldBoss //12 世界boss rand点奖励
AddFrom_Evil //13 恶魔协会
AddFrom_Tower //14 爬塔奖励
AddFrom_ResetSkill //15 重置技能
AddFrom_CardCollect //16 卡片收集奖励
AddFrom_Pet //17 宠物
AddFrom_GuildBoss //18 公会boss奖励
AddFrom_Expedition //19 远征之门
AddFrom_Activities //20 精彩活动
AddFrom_Invitation //21 invitation
AddFrom_Pay //22 pay
AddFrom_Draw //23 抽取获得
AddFrom_Rune //24 卢恩商会
AddFrom_Shop_Arane //25 荣誉商店
AddFrom_Shop_Dark //26 黑市商店
AddFrom_Shop_Guild //27 公会商店
AddFrom_Shop_Pet //28 宠物商店
AddFrom_HeadFrame //29 头像处理
AddFrom_Guild //30 公会
AddFrom_Competition //31 赛季系统
AddFrom_Card //32 卡片系统
AddFrom_Equip //33 装备系统
AddFrom_Hero //34 伙伴系统
AddFrom_Skill //35 技能系统
AddFrom_Expire //36 过期数据
AddFrom_RushTower //37 爬塔冲榜
AddFrom_RushArena //38 英灵殿冲榜
AddFrom_DaoChang100 //39 百人道场
AddFrom_DrawCard //40 卡片召唤
AddFrom_DrawPet //41 宠物召唤
AddFrom_GiftCode //42 礼包码
AddFrom_QuestionReward //43 问卷调查奖励
AddFrom_RushMap //44 地图冲榜
AddFrom_ReplaceJob //45 职业更换
AddFrom_KeepSake //46 信物(藏品)
AddFrom_GuildBattle //47 公会战
AddFrom_DaoChang100Wheel //48 百人道场转盘
AddFrom_OnlineReward //49 在线时间累计奖励
AddFrom_RedBagShop //50 红包商店
AddFrom_RedBagExchange //51 红包商店兑换
AddFrom_qualityPoint //52 素质点
AddFrom_RushPet //53 爬塔冲榜
AddFrom_PetEquip //54 宠物印记
AddFrom_JobChange //55 转职
AddFrom_Divine //56 占卜
AddFrom_SkillExpConver //57 技能经验兑换
AddFrom_DrawingResolve //58 时装图纸分解
AddFrom_RushSkill //59 技能冲榜
AddFrom_CrossYuanHangTrial //60跨服远航试炼
AddFrom_SkillEquipStarLevel //61 神器升星
AddFrom_SkillEquipSoltLevel //62 神器槽位升级
AddFrom_SkillEquipDecompose //63 神器分解
AddFrom_DrawSkillEquip //64
AddFrom_CrossTopTower //65 跨服巅峰之塔
AddFrom_HeadActivate //66 称号激活消耗
AddFrom_GuildDemon //67 公会魔王
AddFrom_SkillEquipRefroge //68 神器重铸
AddFrom_ActivitySummon //69 活动召唤
AddFrom_ActivitySignIn //70 活动签到
AddFrom_SkillEquipShift //71 神器转移
AddFrom_IdolSeason //72 偶像季
AddFrom_WishBox //73 许愿宝箱解锁
AddFrom_WishBoxSpeed //74 许愿宝箱加速
AddFrom_WishBoxUse //75 许愿使用
AddFrom_PetJuexing //76 宠物觉醒
AddFrom_PetDataExchange //77 宠物传承
AddFrom_MujoyLoginAward //78 妙聚每日登录领奖
AddFrom_MujoyDiceAward //79 秒聚骰子奖励
AddFrom_MujoyBrandAward //80 妙聚幸运翻牌奖励
AddFrom_RuneOnekey //81 飞艇探索一键领奖
AddFrom_ChangeName //82 改名
AddFrom_ActivityFundOnekey //83 基金活动
AddFrom_PetRankAward //84 宠物比拼
AddFrom_DrawLevelupSummon //可升级的抽奖卡池
AddFrom_Fruit
AddFrom_StoryChat
)
type RoleBag struct {
SaveObject
itemList map[uint64]*serverproto.ItemData
maxBagSize int32
itemAction *ItemAction
bCheck bool
}
func newRoleBag(r *Role) *RoleBag {
roleBag := &RoleBag{
SaveObject: SaveObject{
role: r,
},
maxBagSize: 999,
}
roleBag.itemAction = newItemAction(roleBag)
roleBag.itemList = make(map[uint64]*serverproto.ItemData)
return roleBag
}
func (this *RoleBag) Load(msg interface{}) bool {
proRole := msg.(*serverproto.Role)
if proRole.RoleBag == nil {
proRole.RoleBag = &serverproto.RoleBag{}
this.AddItemList(model.GlobalCreateItemList, AddItemST{AddFrom: AddFrom_System, Notify: false})
} else {
for _, itemData := range proRole.RoleBag.ItemList {
this.itemList[itemData.Id] = itemData
}
}
return true
}
func (this *RoleBag) Save() {
this.SetDirty(false)
//util.DebugF("uid=%v RoleBag save...", this.role.GetUUid())
saveMsg := &serverproto.SSBagDataSaveReq{
Bag: &serverproto.RoleBag{},
}
//优化提升效率 growslice
saveMsg.Bag.ItemList = make([]*serverproto.ItemData, 0, 32)
for _, data := range this.itemList {
saveMsg.Bag.ItemList = append(saveMsg.Bag.ItemList, data)
}
this.role.SendDb(saveMsg)
}
func (this *RoleBag) CopyData(bag *serverproto.RoleBag) {
for _, data := range this.itemList {
bag.ItemList = append(bag.ItemList, data)
}
}
func (this *RoleBag) GetRole() *Role {
return this.role
}
func (this *RoleBag) checkValid() {
if this.bCheck {
return
}
this.bCheck = true
for _, itemData := range this.itemList {
if itemData.Num <= 0 {
delete(this.itemList, itemData.Id)
this.SetDirty(true)
continue
}
_, ok := serverproto.ItemCfgLoader[itemData.ConfigId]
if !ok {
util.WarnF("uid=%v RoleBag Load load item error id=%v", this.role.GetUUid(), itemData.ConfigId)
delete(this.itemList, itemData.Id)
this.SetDirty(true)
continue
}
}
}
func (this *RoleBag) emptyPosNum() uint32 {
itemLen := int32(len(this.itemList))
if this.maxBagSize < itemLen {
return 0
} else {
return uint32(this.maxBagSize - itemLen)
}
}
// 获取物品堆叠上限
func (this *RoleBag) canAddCnt(itemCfgId int32, itemPileNum uint32) uint64 {
//itemPileNum := this.getItemPileNum(itemCfgId)
//itemCfg := GetItemCfg(itemCfgId)
var count uint64 = 0
for _, item := range this.itemList {
if item != nil && item.ConfigId == itemCfgId && item.Num < itemPileNum {
left := itemPileNum - item.Num
count += uint64(left)
}
}
currCount := count + uint64(this.emptyPosNum()*itemPileNum)
return currCount
}
// 根据动态ID获取道具
func (this *RoleBag) getItemById(id uint64) *serverproto.ItemData {
item, ok := this.itemList[id]
if ok {
return item
}
return nil
}
func (this *RoleBag) getItemPileNum(itemCfgId int32) uint32 {
cfgData, ok := serverproto.ItemCfgLoader[itemCfgId]
if ok {
return uint32(cfgData.Composition)
} else {
util.InfoF("uid=%v getItemPileNum item data not found id=%v", this.role.GetUUid(), itemCfgId)
return 0
}
}
func (this *RoleBag) getItemNum(itemConfigId int32) uint32 {
var count uint32 = 0
if itemConfigId > 0 {
for _, item := range this.itemList {
if item.ConfigId == itemConfigId {
count += item.Num
}
}
}
return count
}
func (this *RoleBag) addItem(cfgData *serverproto.ItemCfg, count int32, st AddItemST) (bBaseChange bool) {
itemCfgId := cfgData.Id
bBaseChange = false
ignore := st.Ignore
st.ItemCfgId = cfgData.Id
st.ItemCount = count
switch serverproto.ResType(cfgData.ResType) {
case serverproto.ResType_Res_Coin:
fallthrough
case serverproto.ResType_Res_RoleBaseExp:
fallthrough
case serverproto.ResType_Res_RoleJobExp:
fallthrough
case serverproto.ResType_Res_HeroBaseExp:
fallthrough
case serverproto.ResType_Res_Rmb:
fallthrough
case serverproto.ResType_Res_Cruise:
fallthrough
case serverproto.ResType_Res_Sprite:
fallthrough
case serverproto.ResType_Res_Reslove:
fallthrough
case serverproto.ResType_Res_EvilExp:
fallthrough
case serverproto.ResType_Res_PetExp:
fallthrough
case serverproto.ResType_Res_Guild:
fallthrough
case serverproto.ResType_Res_DaoChang100:
fallthrough
case serverproto.ResType_Res_VipExp:
fallthrough
case serverproto.ResType_Res_Guild_Battle:
fallthrough
case serverproto.ResType_Res_PetCoin:
fallthrough
case serverproto.ResType_Res_HightSkillExp:
fallthrough
case serverproto.ResType_Res_PetLevelUP_Exp:
if DoCheck(this.role, cfgData, count) != int32(serverproto.ErrorCode_ERROR_OK) {
util.InfoF("uid=%v AddItem effect not found restype=%v", this.role.GetUUid(), cfgData.ResType)
return
}
DoUse(this.role, cfgData, st, true)
if serverproto.ResType(cfgData.ResType) != serverproto.ResType_Res_VipExp {
bBaseChange = true
}
case serverproto.ResType_Res_Item:
fallthrough
case serverproto.ResType_Res_SkillBook:
fallthrough
case serverproto.ResType_Res_Gift:
fallthrough
case serverproto.ResType_Res_QuickBattle:
fallthrough
case serverproto.ResType_Res_ItemCompose:
fallthrough
case serverproto.ResType_Res_HeadFrame:
fallthrough
case serverproto.ResType_Res_CashTicket:
fallthrough
case serverproto.ResType_Res_Month_Car_Item:
fallthrough
case serverproto.ResType_Res_Rune_Unlock_Award:
fallthrough
case serverproto.ResType_Res_Head_Item:
fallthrough
case serverproto.ResType_Res_WishBox:
fallthrough
case serverproto.ResType_Res_WishBox_Select:
fallthrough
case serverproto.ResType_Res_Gift_Unique:
if this.itemAction.add(itemCfgId, count) {
this.SetDirty(true)
}
case serverproto.ResType_Res_Fashion:
//添加时判断性别
cfgFashionPaper, ok1 := serverproto.FashionPaperCfgLoader[itemCfgId]
if ok1 {
cfgFashion, ok2 := serverproto.FashionCfgLoader[cfgFashionPaper.FashionId]
if ok2 && cfgFashion.FashionSex == this.role.GetRoleBase().GetRoleSex() || cfgFashion.FashionSex == 0 {
if this.itemAction.add(itemCfgId, count) {
//this.itemAction.doAction(notify, false)
this.SetDirty(true)
}
}
}
case serverproto.ResType_Res_Equip:
this.role.AddEquip(cfgData.Id, count, st.Notify, ignore)
case serverproto.ResType_Res_Skill_Equip:
this.role.AddSkillEquip(cfgData.Id, count, st.Notify, ignore)
case serverproto.ResType_Res_Chip:
this.role.GetRoleChip().AddChip(itemCfgId, count, true)
if st.Notify {
this.role.GetRoleChip().ChipChangeNtf([]int32{int32(itemCfgId)})
}
case serverproto.ResType_Res_Card:
this.role.GetRoleCard().AddCard(itemCfgId, count, st.Notify, ignore, true)
case serverproto.ResType_Res_Hero:
if cfgData.AutoUse > 0 {
this.role.GetRoleHero().AddHeroByList(cfgData.ComposeItem)
} else {
if this.itemAction.add(itemCfgId, count) {
//this.itemAction.doAction(notify, ignore)
this.SetDirty(true)
}
}
case serverproto.ResType_Res_Pet:
for idx := 0; idx < int(count); idx++ {
this.role.GetRolePet().AddPet(itemCfgId)
}
case serverproto.ResType_Res_KeepSake:
this.role.GetRoleKeepSake().AddKeepSakeMaterial(cfgData, count)
case serverproto.ResType_Res_DaoChang100_Guild:
//百人道场公会贡献点
ssUpdateMsg := &serverproto.SSDaoChang100GuildRankUpdateNtf{
Uid: this.role.GetUUid(),
GuildId: uint64(this.role.GetRoleGuildId()),
Score: uint32(count),
}
this.role.SendGuild(ssUpdateMsg)
case serverproto.ResType_Res_Explor_Exp:
if rune := this.role.GetRoleRune(); rune != nil {
rune.AddGoldExp(count)
}
case serverproto.ResType_Res_DaoChang100_Score:
this.role.GetRoleCompetition().CompetitionAddScoreDuoBao(count)
case serverproto.ResType_Res_RushMap:
this.role.GetRoleBattle().OnRushMapScoreChange(count, 0)
case serverproto.ResType_Res_Virtual_RMB:
this.role.GMPay(float32(count))
case serverproto.ResType_Res_PetEquip:
this.role.GetRolePet().AddPetEquipList(itemCfgId, count, 1, ignore)
case serverproto.ResType_Res_IdolSeason:
this.role.GetRoleCompetition().UseIdolSeasonItem(itemCfgId, count)
default:
util.WarnF("uid=%v res type no exist!!! restype=%v", this.role.GetUUid(), cfgData.ResType)
}
//稀有道具获得消息提示
//邮件方式获取稀有道具不做提醒
if st.AddFrom == AddFrom_WorldBoss ||
st.AddFrom == AddFrom_DrawCard ||
st.AddFrom == AddFrom_DrawPet ||
st.AddFrom == AddFrom_Package ||
st.AddFrom == AddFrom_Shop_Arane ||
st.AddFrom == AddFrom_Shop_Guild ||
st.AddFrom == AddFrom_DrawSkillEquip ||
st.AddFrom == AddFrom_ActivitySummon {
if _, ok := model.GlobalSystemMsgItemList[cfgData.Id]; ok {
if cfgData.ResType == int32(serverproto.ResType_Res_Card) ||
cfgData.ResType == int32(serverproto.ResType_Res_Pet) ||
cfgData.ResType == int32(serverproto.ResType_Res_Skill_Equip) {
//514老旧相册,世界boss商店购买抽卡
if (st.UseItemCfgId > 0 && st.UseItemCfgId == 514 && st.AddFrom == AddFrom_Package) ||
st.AddFrom == AddFrom_DrawCard ||
st.AddFrom == AddFrom_DrawPet ||
st.AddFrom == AddFrom_WorldBoss ||
st.AddFrom == AddFrom_Shop_Arane ||
st.AddFrom == AddFrom_Shop_Guild ||
st.AddFrom == AddFrom_DrawSkillEquip ||
st.AddFrom == AddFrom_ActivitySummon {
this.GetRole().AddSystemMessage(SystemMessageType_Item,
AddSystemMsg{ParamId: cfgData.Id, ParamCount: int32(count), AddFromType: int32(st.AddFrom), UseItemCfgId: st.UseItemCfgId})
}
} else {
this.GetRole().AddSystemMessage(SystemMessageType_Item,
AddSystemMsg{ParamId: cfgData.Id, ParamCount: int32(count), AddFromType: int32(st.AddFrom), UseItemCfgId: st.UseItemCfgId})
}
}
}
return
}
func (this *RoleBag) AddItem(itemCfgId, count int32, st AddItemST) {
this.checkValid()
if count <= 0 {
return
}
cfgData, ok := serverproto.ItemCfgLoader[itemCfgId]
if !ok {
util.ErrorF("uid=%v AddItem item cfg data not found id=%v", this.role.GetUUid(), itemCfgId)
return
}
//自动使用
if cfgData.AutoUse > 0 {
this.autoUseItem(itemCfgId, uint32(count), true, nil, 0)
return
}
util.InfoF("uid=%v AddItem id=%v count=%v from=%v", this.role.GetUUid(), itemCfgId, count, st.AddFrom)
ignore := false
addFrom := st.AddFrom
if addFrom == AddFrom_Battle ||
addFrom == AddFrom_Task ||
addFrom == AddFrom_Quick_Battle ||
addFrom == AddFrom_SignUp ||
addFrom == AddFrom_Tower ||
addFrom == AddFrom_Mail ||
addFrom == AddFrom_Package ||
addFrom == AddFrom_ResetSkill ||
addFrom == AddFrom_WorldBoss ||
addFrom == AddFrom_GuildBoss ||
addFrom == AddFrom_Expedition ||
addFrom == AddFrom_Shop_Buy ||
addFrom == AddFrom_Draw ||
addFrom == AddFrom_Rune ||
addFrom == AddFrom_Shop_Arane ||
addFrom == AddFrom_Shop_Dark ||
addFrom == AddFrom_Shop_Guild ||
addFrom == AddFrom_Shop_Pet ||
addFrom == AddFrom_RushTower ||
addFrom == AddFrom_RushArena ||
addFrom == AddFrom_Activities ||
addFrom == AddFrom_Pay ||
addFrom == AddFrom_DrawCard ||
addFrom == AddFrom_GiftCode ||
addFrom == AddFrom_RushMap ||
addFrom == AddFrom_KeepSake ||
addFrom == AddFrom_DrawPet ||
addFrom == AddFrom_DaoChang100Wheel ||
addFrom == AddFrom_DaoChang100 ||
addFrom == AddFrom_RushPet ||
addFrom == AddFrom_DrawingResolve ||
addFrom == AddFrom_RushSkill ||
addFrom == AddFrom_RedBagShop ||
addFrom == AddFrom_CrossYuanHangTrial ||
addFrom == AddFrom_PetRankAward ||
addFrom == AddFrom_WishBox {
ignore = true
}
st.Ignore = ignore
bBaseChange := this.addItem(cfgData, count, st)
this.itemAction.doAction(st.Notify, st.Ignore)
if bBaseChange {
this.role.GetRoleBase().BaseChangeNtf()
}
if cfgData.ResType == int32(serverproto.ResType_Res_KeepSake) {
this.role.GetRoleKeepSake().OnKeepSakeChangeNtf()
}
if cfgData.ResType == int32(serverproto.ResType_Res_Head_Item) {
TaskMagCheck(this.role, serverproto.TaskType_Eve_Item_Count, int32(cfgData.Id))
}
}
type AddItemST struct {
ItemCfgId int32
ItemCount int32
AddFrom AddFromType
UseItemCfgId int32 //来自使用物品的ID
Notify bool
Ignore bool
ReasonParam int32 //触发该消耗或者添加操作的对应系统道具参数
ReasonParam2 int32 //触发该消耗或者添加操作的对应系统道具参数2
}
func (this *RoleBag) AddItemList(addItemList map[int32]int32, st AddItemST) {
addFrom := st.AddFrom
notify := st.Notify
this.checkValid()
ignore := false
if addFrom == AddFrom_Battle ||
addFrom == AddFrom_Task ||
addFrom == AddFrom_Quick_Battle ||
addFrom == AddFrom_SignUp ||
addFrom == AddFrom_Tower ||
addFrom == AddFrom_Mail ||
addFrom == AddFrom_Package ||
addFrom == AddFrom_ResetSkill ||
addFrom == AddFrom_WorldBoss ||
addFrom == AddFrom_GuildBoss ||
addFrom == AddFrom_Expedition ||
addFrom == AddFrom_Shop_Buy ||
addFrom == AddFrom_Draw ||
addFrom == AddFrom_Rune ||
addFrom == AddFrom_Shop_Arane ||
addFrom == AddFrom_Shop_Dark ||
addFrom == AddFrom_Shop_Guild ||
addFrom == AddFrom_Shop_Pet ||
addFrom == AddFrom_RushTower ||
addFrom == AddFrom_RushArena ||
addFrom == AddFrom_Activities ||
addFrom == AddFrom_Pay ||
addFrom == AddFrom_DrawCard ||
addFrom == AddFrom_GiftCode ||
addFrom == AddFrom_RushMap ||
addFrom == AddFrom_KeepSake ||
addFrom == AddFrom_DrawPet ||
addFrom == AddFrom_DaoChang100Wheel ||
addFrom == AddFrom_DaoChang100 ||
addFrom == AddFrom_RushPet ||
addFrom == AddFrom_DrawingResolve ||
addFrom == AddFrom_RushSkill ||
addFrom == AddFrom_RedBagShop ||
addFrom == AddFrom_CrossYuanHangTrial ||
addFrom == AddFrom_SkillEquipStarLevel ||
addFrom == AddFrom_SkillEquipSoltLevel ||
addFrom == AddFrom_SkillEquipDecompose ||
addFrom == AddFrom_DrawSkillEquip ||
addFrom == AddFrom_CrossTopTower ||
addFrom == AddFrom_ActivitySummon ||
addFrom == AddFrom_ActivitySignIn ||
addFrom == AddFrom_MujoyLoginAward ||
addFrom == AddFrom_MujoyDiceAward ||
addFrom == AddFrom_ActivityFundOnekey ||
addFrom == AddFrom_PetRankAward ||
addFrom == AddFrom_RuneOnekey ||
addFrom == AddFrom_MujoyBrandAward {
ignore = true
}
st.Ignore = ignore
util.InfoF("uid=%v AddItem itemlist=%v from=%v", this.role.GetUUid(), addItemList, st.AddFrom)
bBaseChange := false
bKeepSakeItem := false
for itemCfgId, count := range addItemList {
cfgData, ok := serverproto.ItemCfgLoader[itemCfgId]
if !ok {
util.ErrorF("uid=%v item cfg data not found id=%v", this.role.GetUUid(), itemCfgId)
continue
}
if cfgData.AutoUse > 0 {
ret := this.autoUseItem(itemCfgId, uint32(count), notify, nil, 0)
if ret == serverproto.ErrorCode_ERROR_OK {
delete(addItemList, itemCfgId)
}
continue
}
if this.addItem(cfgData, count, st) {
bBaseChange = true
}
if cfgData.ResType == int32(serverproto.ResType_Res_KeepSake) {
bKeepSakeItem = true
}
}
this.itemAction.doAction(notify, st.Ignore)
if bBaseChange {
this.role.GetRoleBase().BaseChangeNtf()
}
if bKeepSakeItem { //如果有信物相关变化
this.role.GetRoleKeepSake().OnKeepSakeChangeNtf()
}
for itemCfgId, _ := range addItemList {
cfgData, ok := serverproto.ItemCfgLoader[itemCfgId]
if !ok {
continue
}
if cfgData.ResType == int32(serverproto.ResType_Res_Head_Item) {
TaskMagCheck(this.role, serverproto.TaskType_Eve_Item_Count, int32(itemCfgId))
}
}
this.role.U8ServerLogNtf()
}
func (this *RoleBag) delItem(itemCfgId int32, st AddItemST, notify bool) (bBaseChange bool) {
cfgData, ok := serverproto.ItemCfgLoader[itemCfgId]
if !ok {
util.ErrorF("uid=%v delItem item cfg data not found itemCfgId=%v", this.role.GetUUid(), itemCfgId)
return
}
count := st.ItemCount
bBaseChange = false
switch serverproto.ResType(cfgData.ResType) {
case serverproto.ResType_Res_Coin:
fallthrough
case serverproto.ResType_Res_RoleBaseExp:
fallthrough
case serverproto.ResType_Res_RoleJobExp:
fallthrough
case serverproto.ResType_Res_HeroBaseExp:
fallthrough
case serverproto.ResType_Res_Rmb:
fallthrough
case serverproto.ResType_Res_Cruise:
fallthrough
case serverproto.ResType_Res_Sprite:
fallthrough
case serverproto.ResType_Res_Reslove:
fallthrough
case serverproto.ResType_Res_EvilExp:
fallthrough
case serverproto.ResType_Res_PetExp:
fallthrough
case serverproto.ResType_Res_Guild:
fallthrough
case serverproto.ResType_Res_DaoChang100:
fallthrough
case serverproto.ResType_Res_VipExp:
fallthrough
case serverproto.ResType_Res_Guild_Battle:
fallthrough
case serverproto.ResType_Res_PetCoin:
fallthrough
case serverproto.ResType_Res_HightSkillExp:
fallthrough
case serverproto.ResType_Res_PetLevelUP_Exp:
if DoCheck(this.role, cfgData, count) != int32(serverproto.ErrorCode_ERROR_OK) {
util.ErrorF("uid=%v effect not found itemCfgId=%v", this.role.GetUUid(), itemCfgId)
return
}
DoUse(this.role, cfgData, st, false)
bBaseChange = true
case serverproto.ResType_Res_Item:
fallthrough
case serverproto.ResType_Res_HeadFrame:
fallthrough
case serverproto.ResType_Res_SkillBook:
fallthrough
case serverproto.ResType_Res_Fashion:
fallthrough
case serverproto.ResType_Res_Gift:
fallthrough
case serverproto.ResType_Res_QuickBattle:
fallthrough
case serverproto.ResType_Res_ItemCompose:
fallthrough
case serverproto.ResType_Res_CashTicket:
fallthrough
case serverproto.ResType_Res_Head_Item:
fallthrough
case serverproto.ResType_Res_WishBox_Select:
fallthrough
case serverproto.ResType_Res_WishBox:
fallthrough
case serverproto.ResType_Res_Gift_Unique, serverproto.ResType_Res_Month_Car_Item, serverproto.ResType_Res_Rune_Unlock_Award:
if this.itemAction.del(itemCfgId, count) {
this.SetDirty(true)
}
case serverproto.ResType_Res_Chip:
this.GetRole().roleChip.DelChip(itemCfgId, count)
case serverproto.ResType_Res_Equip:
fallthrough
case serverproto.ResType_Res_Card:
fallthrough
case serverproto.ResType_Res_PetEquip:
util.WarnF("uid=%v PetEquip can't be del ", this.role.GetUUid())
default:
util.WarnF("uid=%v resType no exist!!! restype=%v ", this.role.GetUUid(), cfgData.ResType)
}
return
}
func (this *RoleBag) DelItemList(delItemList map[int32]int32, delFrom AddItemST) {
this.checkValid()
bBaseChange := false
for itemCfgId, count := range delItemList {
if itemCfgId <= 0 {
continue
}
delFrom.ItemCfgId = itemCfgId
delFrom.ItemCount = count
if this.delItem(itemCfgId, delFrom, false) {
bBaseChange = true
}
}
util.InfoF("uid=%v DelItem itemList=%v delFrom=%v", this.role.GetUUid(), delItemList, delFrom)
this.itemAction.doAction(true, false)
if bBaseChange {
this.role.GetRoleBase().BaseChangeNtf()
}
}
func (this *RoleBag) DelItem(configId, count int32, delFrom AddItemST) {
bBaseChange := false
delFrom.ItemCfgId = configId
delFrom.ItemCount = count
if this.delItem(configId, delFrom, false) {
bBaseChange = true
}
util.InfoF("uid=%v DelItem id=%v count=%v delFrom=%v", this.role.GetUUid(), configId, count, delFrom)
this.itemAction.doAction(true, false)
if bBaseChange {
this.role.GetRoleBase().BaseChangeNtf()
}
}
// 该结构只删除背包中的道具(在背包中显示的道具)
func (this *RoleBag) DelItemById(id uint64, count int32, delFrom AddFromType) {
if this.itemAction.delByID(id, count) {
this.SetDirty(true)
this.itemAction.doAction(true, false)
util.InfoF("uid=%v DelItemById id=%v count=%v delFrom=%v", this.role.GetUUid(), id, count, delFrom)
}
}
func (this *RoleBag) UseHeadFrameItem(itemId uint64, itemNum uint32) (serverproto.ErrorCode, []*serverproto.KeyValueType) {
if itemNum <= 0 {
return serverproto.ErrorCode_ERROR_FAIL, nil
}
item := this.getItemById(itemId)
if item == nil || item.Num < itemNum {
return serverproto.ErrorCode_ERROR_RENAME_ITEM_NOT_ENOUGH, nil
}
cfgData, ok := serverproto.ItemCfgLoader[item.ConfigId]
if !ok {
util.InfoF("uid=%v item cfg data not found itemCfgId=%v", this.role.GetUUid(), item.ConfigId)
return serverproto.ErrorCode_ERROR_ITEM_NOT_FOUND, nil
}
frameList := strings.Split(cfgData.ComposeItem[0], ":")
if len(frameList) >= 2 {
frameId, _ := model.Str2Num(frameList[0])
frameTime, _ := model.Str2Num(frameList[1])
//校验头像框
headFrameCfg, headFrameOk := serverproto.HeadFrameCfgLoader[int32(frameId)]
if headFrameOk == false {
return serverproto.ErrorCode_ERROR_ITEM_NOT_FOUND, nil
}
//头像框流程
bRet := this.role.GetRoleBase().AddHeadFrame(int32(frameId), int32(frameTime), int32(itemNum))
this.DelItem(item.ConfigId, int32(itemNum), AddItemST{AddFrom: AddFrom_HeadFrame})
if bRet == serverproto.ErrorCode_ERROR_HEAD_FRAME_EXCHANGE_ITEM {
var retMList = map[int32]int32{}
var retKList []*serverproto.KeyValueType
resList := strings.Split(headFrameCfg.ResolveItem[0], ":")
if len(frameList) >= 2 {
resId, _ := model.Str2Num(resList[0])
resNum, _ := model.Str2Num(resList[1])
retMList[int32(resId)] = int32(resNum) * int32(itemNum)
retKList = append(retKList, &serverproto.KeyValueType{
Key: int32(resId),
Value: int32(resNum) * int32(itemNum),
})
}
this.AddItemList(retMList, AddItemST{AddFrom: AddFrom_Package, Notify: true})
return serverproto.ErrorCode_ERROR_HEAD_FRAME_EXCHANGE_ITEM, retKList
}
return serverproto.ErrorCode_ERROR_OK, nil
}
return serverproto.ErrorCode_ERROR_FAIL, nil
}
func (this *RoleBag) UseItem(id uint64, count uint32, itemIdxList []int32, bForceItemId bool) serverproto.ErrorCode {
item := this.getItemById(id)
if item == nil || item.Num < count {
return serverproto.ErrorCode_ERROR_ITEM_NOT_FOUND
}
util.InfoF("uid=%v UseItem id=%v cfgId=%v count=%v", this.role.GetUUid(), id, item.ConfigId, count)
if bForceItemId {
return this.autoUseItem(item.ConfigId, count, true, itemIdxList, id)
} else {
return this.autoUseItem(item.ConfigId, count, true, itemIdxList, 0)
}
}
func (this *RoleBag) autoUseItem(itemCfgId int32, count uint32, notify bool, itemIdxList []int32, itemId uint64) serverproto.ErrorCode {
this.checkValid()
cfgData, ok := serverproto.ItemCfgLoader[itemCfgId]
if !ok {
util.InfoF("uid=%v item cfg data not found itemCfgId=%v", this.role.GetUUid(), itemCfgId)
return serverproto.ErrorCode_ERROR_ITEM_NOT_FOUND
}
if cfgData.NeedLevel != 0 && cfgData.NeedLevel > this.role.GetRoleLevel() {
return serverproto.ErrorCode_ERROR_USEITEM_ROLE_LEVEL_NOT_ENOUGH
}
if itemId > 0 {
item := this.getItemById(itemId)
//判断是否是达到对应时间可使用道具
if cfgData.ItemTime == Item_Time_Type_TimeUse {
if int64(item.TimeStamp+uint32(cfgData.ItemTimeCd)) > util.GetTimeSeconds() {
return serverproto.ErrorCode_ERROR_ITEM_NOT_IN_USE_TIME
}
}
}
//获取使用消耗
var consumeItemLIst = map[int32]int32{}
for idx := 0; idx < len(cfgData.Costitem); idx++ {
key, val := model.Str2Res(cfgData.Costitem[idx])
if key <= 0 || val <= 0 {
continue
}
if !this.CanDelItem(key, val*int32(count)) {
return serverproto.ErrorCode_ERROR_RES_NOT_ENOUGH
}
consumeItemLIst[key] += val * int32(count)
}
//获取礼包内容
var addItemList = map[int32]int32{}
for i := 0; i < int(count); i++ {
switch serverproto.ResType(cfgData.ResType) {
case serverproto.ResType_Res_Hero:
this.role.GetRoleHero().AddHeroByList(cfgData.ComposeItem)
case serverproto.ResType_Res_Gift:
//掉落处理//根据配置需要按照职业/性别给箱子
job := false
if cfgData.Job == 1 {
job = true
}
//先区分性别
if SEX_FEMALE == this.role.GetRoleBase().GetRoleSex() {
this.openPackage(cfgData.ComposeItem, addItemList, job)
} else {
this.openPackage(cfgData.Resolve, addItemList, job)
}
case serverproto.ResType_Res_ItemCompose:
//先区分性别
if SEX_FEMALE == this.role.GetRoleBase().GetRoleSex() {
this.openPackage(cfgData.ComposeItem, addItemList, false)
} else {
this.openPackage(cfgData.Resolve, addItemList, false)
}
case serverproto.ResType_Res_Head_Item:
for _, data := range cfgData.ComposeItem {
itemList := strings.Split(data, ":")
if len(itemList) < 2 {
continue
}
itemId, _ := model.Str2Num(itemList[0])
cnt, _ := model.Str2Num(itemList[1])
addItemList[int32(itemId)] += int32(cnt)
}
case serverproto.ResType_Res_QuickBattle:
for _, data := range cfgData.ComposeItem {
itemList := strings.Split(data, ":")
if len(itemList) < 2 {
continue
}
itemId, _ := model.Str2Num(itemList[0])
hours, _ := model.Str2Num(itemList[1])
var itemNum int32 = 0
levelCfg, ok := serverproto.LevelCfgLoader[this.role.GetRoleBattle().GetLevelId()]
if !ok {
continue
}
if itemId == int(serverproto.ResType_Res_RoleBaseExp) {
itemNum = levelCfg.BaseExpOl
} else if itemId == int(serverproto.ResType_Res_HeroBaseExp) {
itemNum = levelCfg.ParterOl
} else if itemId == int(serverproto.ResType_Res_Coin) {
itemNum = levelCfg.ZenyOl
} else if itemId == int(serverproto.ResType_Res_Cruise) {
itemNum = levelCfg.CruiseOl
} else {
continue
}
tmpAddNum := uint64(itemNum) * (uint64(hours) / uint64(model.GlobalIncomeTime))
tmpNum := uint64(addItemList[int32(itemId)]) + tmpAddNum
if tmpNum > math.MaxInt32 {
util.ErrorF("uid=%v useItem limit configid=%v count=%v", this.role.GetUUid(), itemCfgId, count)
return serverproto.ErrorCode_ERROR_SERVER_USE_FAILED_LIMIT
}
addItemList[int32(itemId)] += int32(tmpAddNum)
}
case serverproto.ResType_Res_Gift_Unique:
//只能使用一个
if i > 1 || len(itemIdxList) <= 0 {
break
}
hasList := set.New(set.NonThreadSafe)
for idx := 0; idx < len(itemIdxList); idx++ {
if int(itemIdxList[idx]) >= len(cfgData.ComposeItem) || itemIdxList[idx] < 0 {
break
}
if hasList.Has(itemIdxList[idx]) {
continue
}
hasList.Add(itemIdxList[idx])
itemId, ItemNum := model.Str2Res(cfgData.ComposeItem[itemIdxList[idx]])
if itemId > 0 && ItemNum > 0 {
addItemList[itemId] += ItemNum
}
}
case serverproto.ResType_Res_Month_Car_Item:
if len(cfgData.ComposeItem) > 0 {
if id, err := model.Str2Num(cfgData.ComposeItem[0]); err == nil {
this.role.GetRoleRune().AddMonthCardItem(int32(id), 1)
}
}
case serverproto.ResType_Res_Rune_Unlock_Award:
rune := this.role.GetRoleRune()
if rune != nil && rune.runeExplore != nil {
if !RuneShopMag.IsOpen() {
return serverproto.ErrorCode_ERROR_RUNE_NO_OPEN
}
if rune.runeExplore.BUnlock {
return serverproto.ErrorCode_ERROR_RUNE_HIGHTER_UNLOCK
}
this.role.GetRoleRune().RuneUnlock()
}
}
}
//消耗资源并获得礼包内容
switch serverproto.ResType(cfgData.ResType) {
case serverproto.ResType_Res_Hero:
if itemId > 0 {
this.DelItemById(itemId, int32(count), AddFrom_Package)
} else {
this.DelItem(itemCfgId, int32(count), AddItemST{AddFrom: AddFrom_Package})
}
case serverproto.ResType_Res_Month_Car_Item, serverproto.ResType_Res_Rune_Unlock_Award:
if itemId > 0 {
this.DelItemById(itemId, int32(count), AddFrom_Package)
} else {
this.DelItem(itemCfgId, int32(count), AddItemST{AddFrom: AddFrom_Package})
}
return serverproto.ErrorCode_ERROR_OK
case serverproto.ResType_Res_ItemCompose:
this.DelItemList(consumeItemLIst, AddItemST{AddFrom: AddFrom_Package})
this.AddItemList(addItemList, AddItemST{AddFrom: AddFrom_Package, Notify: notify, UseItemCfgId: itemCfgId})
default:
if len(addItemList) > 0 {
ret := this.CanAddItemList(addItemList)
if ret == serverproto.ErrorCode_ERROR_OK {
this.AddItemList(addItemList, AddItemST{AddFrom: AddFrom_Package, Notify: notify, UseItemCfgId: itemCfgId})
//消耗资源
if itemId > 0 {
this.DelItemById(itemId, int32(count), AddFrom_Package)
} else {
consumeItemLIst[itemCfgId] += int32(count)
}
this.DelItemList(consumeItemLIst, AddItemST{AddFrom: AddFrom_Package})
} else {
return ret
}
}
}
ackMsg := &serverproto.SCUseItemAck{
Error: int32(serverproto.ErrorCode_ERROR_OK),
}
if len(addItemList) <= 0 {
ackMsg.Error = int32(serverproto.ErrorCode_ERROR_FAIL)
} else {
for key, value := range addItemList {
ackMsg.ItemList = append(ackMsg.ItemList, &serverproto.KeyValueType{
Key: key,
Value: value,
})
}
}
this.role.ReplayGate(ackMsg, true)
return serverproto.ErrorCode_ERROR_OK
}
// 是否能添加该列表物品(整体添加)
func (this *RoleBag) CanAddItemList(addItemList map[int32]int32) serverproto.ErrorCode {
for key, value := range addItemList {
ret := this.CanAddItem(key, value)
if ret != serverproto.ErrorCode_ERROR_OK {
return ret
}
}
return serverproto.ErrorCode_ERROR_OK
}
func (this *RoleBag) CanAddItem(configId int32, count int32) serverproto.ErrorCode {
if count <= 0 {
return serverproto.ErrorCode_ERROR_FAIL
}
cfgData, ok := serverproto.ItemCfgLoader[configId]
if !ok {
util.InfoF("uid=%v item cfg data not found itemCfgId=%v", this.role.GetUUid(), configId)
return serverproto.ErrorCode_ERROR_ITEM_NOT_FOUND
}
switch serverproto.ResType(cfgData.ResType) {
case serverproto.ResType_Res_Item:
fallthrough
case serverproto.ResType_Res_HeadFrame:
fallthrough
case serverproto.ResType_Res_SkillBook:
fallthrough
case serverproto.ResType_Res_Card:
fallthrough
case serverproto.ResType_Res_Pet:
fallthrough
case serverproto.ResType_Res_QuickBattle:
fallthrough
case serverproto.ResType_Res_Fashion: //只添加图纸
if cfgData.Composition <= 0 {
//if this.role.roleBag.getItemPileNum(configId) <= 0 {
util.InfoF("uid=%v CanAddItem max count can not add or cfg not found itemCfgId=%v", this.role.GetUUid(), configId)
return serverproto.ErrorCode_ERROR_BAG_ITEM_PILE
}
if uint64(count) > this.canAddCnt(configId, uint32(cfgData.Composition)) {
util.InfoF("uid=%v CanAddItem limit count itemCfgId=%v", this.role.GetUUid(), configId)
return serverproto.ErrorCode_ERROR_BAG_FULL
}
}
return serverproto.ErrorCode_ERROR_OK
}
func (this *RoleBag) CanDelItemList(delItemList map[int32]int32) bool {
for key, value := range delItemList {
if !this.CanDelItem(key, value) {
return false
}
}
return true
}
func (this *RoleBag) CanDelItem(configId int32, count int32) bool {
if count <= 0 {
return false
}
if configId > 100 {
if this.role.GetItemNum(configId) < uint32(count) {
return false
}
} else {
if this.role.GetResNum(configId) < uint64(count) {
util.InfoF("uid=%v del item num not enough itemCfgId=%v", this.role.GetUUid(), configId)
return false
}
}
return true
}
// 打开礼包
func (this *RoleBag) openPackage(dropIdList []string, addItemList map[int32]int32, job bool) {
roleJobType := this.role.GetRoleBase().GetRoleJobType()
for idx := 0; idx < len(dropIdList); idx++ {
if !job { //不按照job给箱子
dropId, _ := model.Str2Num(dropIdList[idx])
if dropId <= 0 {
continue
}
this.role.GetRoleBattle().DropProcess(addItemList, int32(dropId))
} else { //按照job给箱子
jobType, dropId := model.Str2Res(dropIdList[idx])
if (dropId <= 0) || (jobType != roleJobType) {
continue
}
this.role.GetRoleBattle().DropProcess(addItemList, int32(dropId))
}
}
}
// GM process
func (this *RoleBag) GMClearBag() {
for _, data := range this.itemList {
cfgData, ok := serverproto.ItemCfgLoader[data.ConfigId]
if !ok {
util.InfoF("uid=%v item cfg data not found itemCfgId=%v", this.role.GetUUid(), data.ConfigId)
break
}
switch serverproto.ResType(cfgData.ResType) {
case serverproto.ResType_Res_SkillBook:
case serverproto.ResType_Res_Gift:
case serverproto.ResType_Res_QuickBattle:
case serverproto.ResType_Res_HeadFrame:
fallthrough
case serverproto.ResType_Res_Item:
this.itemAction.del(data.ConfigId, int32(data.Num))
this.SetDirty(true)
}
}
this.itemAction.doAction(true, false)
}