pet_home_server/src/server/game/mod/card/Card.go
2025-06-30 11:06:51 +08:00

593 lines
14 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 card
import (
"fmt"
"server/GoUtil"
cardCfg "server/conf/card"
"server/game/mod/item"
"server/msg"
)
type CardMod struct {
CardList map[int]int // 卡牌列表
ExchangeStar int // 兑换星星
CollectReward map[int]struct{} // 已领取奖励
AllCollect int // 总共收集 0未领取 1已领取
CardLimit bool //卡牌节 限时活动
EndTime int64 //周期结束时间
SeasonFirst bool //赛季首次奖励
AllCard map[int]int //
ExTimes int //置换次数
ReqTimes int //请求次数
GoldTimes int // 金卡次数
ReqFriend map[int]*CardInfo //今日已请求好友
ExCard map[int]*CardInfo // 交换卡牌
Cache Cache // 缓存卡牌
Round int // 轮次
Handbook map[int]int // 图鉴
}
type Cache struct {
Card map[int]int
Master map[int]int
Handbook map[int]int
ExStar int
}
const (
MASTER_CARD_NORMAL = 6
MASTER_CARD_GOLD = 7
)
const (
HANDBOOK_STATUS_IDLE = 1 // 未领取
HANDBOOK_STATUS_GET = 2 // 已领取
)
const (
TYPE_CARD_GIVE = 1 // 请求卡牌
TYPE_CARD_SEND = 2 // 赠送卡牌
TYPE_CARD_EX = 3 // 卡牌交换
)
const (
STATUS_CARD_GIVE_1 = 1 // 请求中
STATUS_CARD_GIVE_2 = 2 // 对方同意,等待领取
STATUS_CARD_GIVE_3 = 3 // 请求已结束
STATUS_CARD_SEND_1 = 1 // 赠送成功 等待领取
STATUS_CARD_EX_1 = 1 // 发起交换
STATUS_CARD_EX_2 = 2 // 选择卡牌交换
STATUS_CARD_EX_3 = 3 // 交换成功,等待领取
)
type CardInfo struct {
Id string
AUid int
BUid int
CardId int
ExId int
Type int
EndTime int64
StartTime int64
Status int
}
func (c *CardMod) InitData() {
// 初始化数据
if c.CardList == nil {
c.CardList = make(map[int]int)
}
if c.CollectReward == nil {
c.CollectReward = make(map[int]struct{})
}
if c.AllCard == nil {
c.AllCard = make(map[int]int)
}
if c.ReqFriend == nil {
c.ReqFriend = make(map[int]*CardInfo)
}
if c.ExCard == nil {
c.ExCard = make(map[int]*CardInfo)
}
if c.Handbook == nil {
c.Handbook = make(map[int]int)
}
if c.Cache.Card == nil {
c.Cache.Card = make(map[int]int)
}
if c.Cache.Master == nil {
c.Cache.Master = make(map[int]int)
}
if c.Cache.Handbook == nil {
c.Cache.Handbook = make(map[int]int)
}
for k := range c.CardList {
if _, ok := c.Handbook[k]; !ok {
c.Handbook[k] = HANDBOOK_STATUS_IDLE
}
}
}
func (c *CardMod) Login(ServerOpenTime int64) []*item.Item {
Now := GoUtil.Now()
Duration := cardCfg.GetCardDuration()
HandbookItemNum := 0
if c.EndTime < Now {
c.CardList = make(map[int]int)
c.ExchangeStar = 0
c.CollectReward = make(map[int]struct{})
c.AllCollect = 0
c.EndTime = 0
c.Round = 0
c.Handbook = make(map[int]int)
for k, v := range c.Handbook {
if v == HANDBOOK_STATUS_GET {
continue
}
Round := cardCfg.GetRoundById(k)
if Round < c.Round {
continue
}
HandbookItemNum += cardCfg.GetStarById(k)
}
}
if c.EndTime == 0 {
c.EndTime = ((Now-ServerOpenTime)/Duration+1)*Duration + ServerOpenTime
}
return []*item.Item{{Id: item.ITEM_ENERGY_ID, Num: HandbookItemNum}}
}
func (c *CardMod) ZeroUpdate(ServerOpenTime int64) []*item.Item {
c.ReqTimes = cardCfg.GetReqTimes()
c.ExTimes = cardCfg.GetExTimes()
c.GoldTimes = 2
return c.Login(ServerOpenTime)
}
// 增加卡牌
func (c *CardMod) AddCard(Id int) {
_, ok := c.CardList[Id]
if ok {
star := cardCfg.GetStarById(Id)
c.ExchangeStar += star
c.Cache.ExStar += star
c.CardList[Id]++
} else {
c.CardList[Id] = 1
}
_, ok = c.Handbook[Id]
if !ok {
c.Handbook[Id] = HANDBOOK_STATUS_IDLE
c.Cache.Handbook[Id] = 1
}
c.Cache.Card[Id]++
}
// 开启卡包
func (c *CardMod) OpenCardPack(Star int) ([]int, error) {
cardId := 0
newCard := make([]int, 0)
cnt := cardCfg.GetPackRewardCnt(Star)
if cnt == 0 {
return newCard, fmt.Errorf("open card pack cfg err")
}
mustHaveStar := cardCfg.GetPackMustHave(Star)
if mustHaveStar != 0 {
cardId = randCard(c.Round, mustHaveStar, 0, newCard)
if cardId == 0 {
return newCard, fmt.Errorf("OpenCardPack card id err")
}
newCard = append(newCard, cardId)
c.AddCard(cardId)
cnt--
}
if c.CardLimit { // 卡牌节获得额外的卡牌 获得卡包原本卡牌数50%向下取整且至少为1张额外卡牌
total := cnt + len(newCard)
Extra := max(1, int(total/2))
cnt += Extra
}
randList := cardCfg.GetRandListByStar(Star)
for i := 0; i < cnt; i++ {
CardStar := GoUtil.RandMap(randList)
switch CardStar {
case 5:
cardId = randCard(c.Round, 4, 1, newCard)
case 6:
cardId = randCard(c.Round, 5, 1, newCard)
default:
cardId = randCard(c.Round, CardStar, 0, newCard)
}
if cardId == 0 {
return newCard, fmt.Errorf("OpenCardPack card id err")
}
newCard = append(newCard, cardId)
c.AddCard(cardId)
}
// 开卡包
return newCard, nil
}
// 协议返回
func (c *CardMod) BackData() *msg.ResCardInfo {
var cardList []*msg.Card
for k, v := range c.CardList {
if v <= 0 {
continue
}
cardList = append(cardList, &msg.Card{Id: int32(k), Count: int32(v)})
}
ReqUid := make([]int64, 0)
for _, v := range c.ReqFriend {
if v.EndTime < GoUtil.Now() {
delete(c.ReqFriend, v.BUid)
continue
}
ReqUid = append(ReqUid, int64(v.BUid))
}
ExUid := make([]int64, 0)
for k, v := range c.ExCard {
if v.EndTime < GoUtil.Now() {
delete(c.ExCard, k)
continue
}
ExUid = append(ExUid, int64(k))
}
return &msg.ResCardInfo{
CardList: cardList,
ExStar: int32(c.ExchangeStar),
Status: int32(c.AllCollect),
CollectId: GoUtil.MapIntToSlice(c.CollectReward),
EndTime: int32(c.EndTime),
ExTimes: int32(c.ExTimes),
ReqTimes: int32(c.ReqTimes),
AllCard: GoUtil.MapIntToInt32(c.AllCard),
ReqUid: ReqUid,
ExUid: ExUid,
Round: int32(c.Round),
Handbook: GoUtil.MapIntToInt32(c.Handbook),
SeasonFirst: c.SeasonFirst,
}
}
// 领取卡牌收集奖励
func (c *CardMod) GetCollectReward(Id int) ([]*item.Item, int, error) {
_, ok := c.CollectReward[Id]
if ok {
return nil, 0, fmt.Errorf("CollectReward already collect")
}
cardList := cardCfg.GetCardListByColor(Id)
for _, v := range cardList {
count, ok := c.CardList[v]
if !ok || count <= 0 {
return nil, 0, fmt.Errorf("card not collect all ,id : %d", Id)
}
}
c.CollectReward[Id] = struct{}{}
Item, Chess := cardCfg.GetCollectReward(Id)
return Item, Chess, nil
}
// 兑换星星奖励
func (c *CardMod) ExStarReward(Id int) ([]*item.Item, error) {
if c.ExchangeStar < Id {
return nil, fmt.Errorf("ExStarReward star not enough")
}
CostStar, itemList := cardCfg.GetExchangeCfg(Id)
if c.ExchangeStar < CostStar {
return nil, fmt.Errorf("ExStarReward star not enough")
}
c.ExchangeStar -= CostStar
c.Cache.ExStar -= CostStar
return itemList, nil
}
// 领取全收集奖励
func (c *CardMod) AllCollectReward() ([]*item.Item, []*item.Item, error) {
if c.AllCollect == 1 {
return nil, nil, fmt.Errorf("AllCollectReward already collect")
}
AllCardId := cardCfg.GetAllCardId(c.Round)
for _, v := range AllCardId {
count, ok := c.CardList[v]
if !ok || count <= 0 {
return nil, nil, fmt.Errorf("card not fully collect")
}
}
c.AllCollect = 0
c.CollectReward = make(map[int]struct{})
ExStar := 0
for k, v := range c.CardList {
star := cardCfg.GetStarById(k)
ExStar += star * (v - 1)
c.CardList[k] = v - 1
}
c.CardList = make(map[int]int)
c.ExchangeStar += ExStar
c.Cache.ExStar += ExStar
Item := cardCfg.GetAllCollectReward()
HandbookItemNum := 0
for k, v := range c.Handbook {
if v == HANDBOOK_STATUS_GET {
continue
}
// Round := cardCfg.GetRoundById(k)
// if Round < c.Round {
// continue
// }
HandbookItemNum += cardCfg.GetStarById(k)
}
c.Round++
c.Handbook = make(map[int]int)
return Item, []*item.Item{{Id: item.ITEM_ENERGY_ID, Num: HandbookItemNum}}, nil
}
func (c *CardMod) ResetCardFestival() {
c.CardLimit = false
}
func (c *CardMod) GetCardFestival() bool {
return c.CardLimit
}
func (c *CardMod) CreateCardFestival() {
c.CardLimit = true
}
func (c *CardMod) GetCardNum(Card int) int {
return c.CardList[Card]
}
func (c *CardMod) SubCard(id int) error {
count, ok := c.CardList[id]
if ok && count > 0 {
c.CardList[id]--
c.Cache.Card[id]--
return nil
}
return fmt.Errorf("SubCard card not enough")
}
func (c *CardMod) RequestCard() error {
if c.ReqTimes <= 0 {
return fmt.Errorf("RequestCard times not enough")
}
c.ReqTimes--
return nil
}
// 增加请求卡牌记录
func (c *CardMod) AddRequestCard(CardInfo *CardInfo) error {
_, ok := c.ReqFriend[CardInfo.BUid]
if ok {
return fmt.Errorf("AddRequestCard already request")
}
c.ReqFriend[CardInfo.BUid] = CardInfo
return nil
}
func (c *CardMod) DelRequestCard(Uid int) (map[int]*CardInfo, error) {
ci, ok := c.ReqFriend[Uid]
if !ok {
return nil, fmt.Errorf("DelRequestCard not find request card")
}
r := make(map[int]*CardInfo)
for k, v := range c.ReqFriend {
if v.Id == ci.Id && v.BUid != ci.BUid {
r[k] = v
continue
}
}
delete(c.ReqFriend, Uid)
return r, nil
}
func (c *CardMod) AddReqTimes(Id string, Time int64) {
n := 0
for _, v := range c.ReqFriend {
if v.Id == Id {
n++
}
}
Zero := GoUtil.ZeroTime(Time)
ZeroTime := GoUtil.ZeroTimestamp()
if n == 0 && Zero == ZeroTime {
c.ReqTimes = min(cardCfg.GetReqTimes(), c.ReqTimes+1)
}
}
func (c *CardMod) AddExTimes(CardInfo *CardInfo) {
Zero := GoUtil.ZeroTime(CardInfo.StartTime)
ZeroTime := GoUtil.ZeroTimestamp()
if Zero == ZeroTime {
c.ExTimes++
c.ExTimes = min(cardCfg.GetExTimes(), c.ExTimes)
}
if cardCfg.CheckCardIsGold(CardInfo.CardId) {
c.GoldTimes--
}
}
// 交换卡牌
func (c *CardMod) ExchangeCard(From, To, CardId int) (*CardInfo, error) {
Now := GoUtil.Now()
Id := GoUtil.CreateCardId(From, To, CardId)
err := c.SubCard(CardId)
if c.ExTimes <= 0 {
return nil, fmt.Errorf("ExchangeCard times not enough")
}
c.ExTimes--
if err != nil {
return nil, err
}
_, ok := c.ExCard[To]
if ok {
return nil, fmt.Errorf("ExchangeCard already exchange")
}
CardInfo := &CardInfo{
Id: Id,
AUid: From,
BUid: To,
CardId: CardId,
Type: TYPE_CARD_EX,
Status: STATUS_CARD_EX_1,
StartTime: Now,
EndTime: Now + 86400,
}
c.ExCard[To] = CardInfo
return CardInfo, nil
}
func (c *CardMod) SendCard(From, To, CardId int) (*CardInfo, error) {
Now := GoUtil.Now()
Id := GoUtil.CreateCardId(From, To, CardId)
err := c.SubCard(CardId)
if c.ExTimes <= 0 {
return nil, fmt.Errorf("SendCard times not enough")
}
c.ExTimes--
if err != nil {
return nil, err
}
CardInfo := &CardInfo{
Id: Id,
AUid: From,
BUid: To,
CardId: CardId,
Type: TYPE_CARD_SEND,
StartTime: Now,
Status: STATUS_CARD_SEND_1,
}
return CardInfo, nil
}
func (c *CardMod) DelExCard(CardInfo *CardInfo) {
delete(c.ExCard, CardInfo.BUid)
}
func (c *CardMod) AddMasterCard(Id int) {
c.Cache.Master[Id]++
c.AllCard[Id]++
}
func (c *CardMod) MasterCardEx(Id, CardId int) error {
if c.AllCard[Id] <= 0 {
return fmt.Errorf("MasterCardEx card not enough")
}
if Id == MASTER_CARD_NORMAL && cardCfg.CheckCardIsGold(CardId) {
return fmt.Errorf("MasterCardEx card type err")
}
c.AllCard[Id]--
c.Cache.Master[Id]--
c.AddCard(CardId)
return nil
}
func (c *CardMod) NotifyCard() *msg.ResNotifyCard {
m := &msg.ResNotifyCard{
Card: GoUtil.MapIntToInt32(c.Cache.Card),
Master: GoUtil.MapIntToInt32(c.Cache.Master),
Handbook: GoUtil.MapIntToInt32(c.Cache.Handbook),
ExStar: int32(c.Cache.ExStar),
}
// log.Debug("NotifyCard %v", c.Cache.Card)
c.Cache = Cache{
Card: make(map[int]int),
Master: make(map[int]int),
Handbook: make(map[int]int),
ExStar: 0,
}
return m
}
func (c *CardMod) NotifyTimes() *msg.ResNotifyCardTimes {
ReqUid := make([]int64, 0)
for k, v := range c.ReqFriend {
if v.EndTime < GoUtil.Now() {
delete(c.ReqFriend, k)
continue
}
ReqUid = append(ReqUid, int64(k))
}
ExUid := make([]int64, 0)
for k, v := range c.ExCard {
if v.EndTime < GoUtil.Now() {
delete(c.ExCard, k)
continue
}
ExUid = append(ExUid, int64(k))
}
m := &msg.ResNotifyCardTimes{
ExTimes: int32(c.ExTimes),
ReqTimes: int32(c.ReqTimes),
ExUid: ExUid,
ReqUid: ReqUid,
GoldTimes: int32(c.GoldTimes),
}
return m
}
func (c *CardMod) ResetGoldCardEx() {
for k, v := range c.ExCard {
if cardCfg.CheckCardIsGold(v.CardId) {
delete(c.ExCard, k)
}
if GoUtil.ZeroTime(v.StartTime) == GoUtil.ZeroTimestamp() {
c.ExTimes++
}
}
}
func (c *CardMod) SubGoldTimes() error {
if c.GoldTimes <= 0 {
return fmt.Errorf("SubGoldTimes times not enough")
}
c.GoldTimes--
return nil
}
func (c *CardMod) AddGoldTimes() {
c.GoldTimes++
c.GoldTimes = min(2, c.GoldTimes)
}
func (c *CardMod) GetHandbookReward(CardId int) ([]*item.Item, error) {
if v, ok := c.Handbook[CardId]; ok {
if v == HANDBOOK_STATUS_GET {
return nil, fmt.Errorf("GetHandbookReward already get")
}
Star := cardCfg.GetStarById(CardId)
c.Handbook[CardId] = HANDBOOK_STATUS_GET
c.Cache.Handbook[CardId] = HANDBOOK_STATUS_GET
return []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, Star)}, nil
}
return nil, fmt.Errorf("GetHandbookReward not find card")
}
func (c *CardMod) RandCard(Star int) int {
return randCard(c.Round, Star, 0, []int{})
}
func (c *CardMod) SeasonFirstReward() ([]*item.Item, error) {
if c.SeasonFirst {
return nil, fmt.Errorf("SeasonFirstReward already get")
}
c.SeasonFirst = true
return cardCfg.GetSeasonFirstReward(), nil
}
func (c *CardMod) GetCardList() []int {
cardList := make([]int, 0)
for k, v := range c.CardList {
if v > 0 {
cardList = append(cardList, k)
}
}
return cardList
}