pet_home_server/src/server/game/mod/limitedTimeEvent/LimitedTimeEvent.go
2025-09-19 12:09:39 +08:00

558 lines
14 KiB
Go

package limitedTimeEvent
import (
"fmt"
"math"
"server/GoUtil"
limitedTimeEventCfg "server/conf/limitedTimeEvent"
mergeDataCfg "server/conf/mergeData"
"server/game/mod/item"
"server/msg"
)
const (
EVENT_TYPE_HIGH_ROLLER = 1 // high roller
EVENT_TYPE_SUPER_EMIT = 2 // 超级发射器
EVENT_TYPE_METEOR_SHOW = 3 // 流星雨
EVENT_TYPE_CHEST_RAIN = 4 // 宝箱雨
EVENT_TYPE_SUPER_ORDER = 5 // 超级订单
EVENT_TYPE_SENCE_DASH = 6 // 场景冲刺
EVENT_TYPE_CARD_FESTIVAL = 7 // 卡牌节
EVENT_TYPE_GOLDCARD_EX = 8 // 金卡交换
EVENT_TYPE_PET_THIEF = 9 // 宠物小偷
EVENT_TYPE_FAST_PRODUCE = 10 // 连击快手
EVENT_TYPE_CAT_CYCLONE = 11 // 猫咪飓风
EVENT_TYPE_MONEY_CAT = 12 // 招财猫
EVENT_TYPE_LUCKY_CAT = 13 // 幸运猫
EVENT_TYPE_CAT_TRICK = 14 // 猫咪戏法
EVENT_TYPE_PAYBACK_DAY = 15 // 回收日
EVENT_TYPE_LITTLE_APPRENTICE = 16 // 小学徒
)
const (
EVENT_NOTIFY_TYPE_ADD = 0
EVENT_NOTIFY_TYPE_DEL = 1
)
type LimitedTimeEventMod struct {
EventList map[int]*LTEInfo
Triggered map[int]struct{}
Progress int
ProgressReward map[int]int
LastSelect int
Lv int // 玩家等级 零点更新
ProgressMax int
LastOption []int
BonusNum int
First bool
FirstReward bool
}
type LTEInfo struct {
StartT int64 // 开始时间
Remian int64 // 剩余时间
Info map[string]interface{} // 事件信息
D interface{}
}
type MoneyCat struct {
Id int
EndTime int64
Mul float64
}
type LuckyCat struct {
Earnings int
MaxEarings int
}
type CatTrick struct {
List []CatTrickInfo
Energy int
}
type CatTrickInfo struct {
Id int
Type int
}
type PaybackDay struct {
count int
}
func (l *LimitedTimeEventMod) InitData(Lv int) {
if l.EventList == nil {
l.EventList = make(map[int]*LTEInfo)
}
if l.Triggered == nil {
l.Triggered = make(map[int]struct{})
}
if l.ProgressReward == nil {
// 初始化进度奖励
l.ProgressReward = make(map[int]int)
}
if l.ProgressMax == 0 {
l.Lv = Lv
l.ProgressMax = limitedTimeEventCfg.GetProgressMax(Lv, l.BonusNum)
}
if !l.First {
l.First = true
EventId := limitedTimeEventCfg.GetFirstEvent()
l.ProgressMax = 0
l.ProgressReward = map[int]int{
1: EventId,
}
l.LastOption = []int{EventId}
}
if !l.FirstReward {
l.ProgressMax = 0
}
if len(l.ProgressReward) == 0 {
SelectNum := limitedTimeEventCfg.GetProgressSelectNum(Lv)
BonusLv := limitedTimeEventCfg.GetBonusLv(Lv)
RandMap := limitedTimeEventCfg.GetProgressRewardRand(BonusLv)
n := 0
r := make([]int, 0)
LastOption := l.LastOption
for n < 10 {
n++
r = GoUtil.RandMapNum(RandMap, SelectNum)
Id := 1
for _, v := range r {
l.ProgressReward[Id] = v
Id++
}
if !GoUtil.SliceEqual(LastOption, r) {
break
}
}
l.LastOption = r
}
}
func (l *LimitedTimeEventMod) ZeroUpdate(Lv int) {
if !l.FirstReward {
return
}
l.Lv = Lv
l.BonusNum = 0
l.ProgressMax = limitedTimeEventCfg.GetProgressMax(Lv, l.BonusNum)
}
// 判断限时事件是否存在
func (l *LimitedTimeEventMod) CheckExist(EventId int) bool {
info, ok := l.EventList[EventId]
if !ok {
return false
}
return GoUtil.Now() <= info.StartT+info.Remian
}
// 触发限时事件
func (l *LimitedTimeEventMod) Trigger(Lv int) (int, []int, []int) {
if Lv < 4 {
return 0, nil, nil
}
TriggerEvent := limitedTimeEventCfg.GetLimitedTimeEventCfg()
TimeoutEvent := make([]int, 0)
AddEvent := make([]int, 0)
Now := GoUtil.Now()
for _, v := range TriggerEvent {
if _, ok := l.Triggered[v.Id]; ok { //不重复触发
continue
}
if info, ok := l.EventList[v.EventId]; ok {
info.Remian += int64(v.Duration)
} else {
LTEInfo := &LTEInfo{
StartT: Now,
Remian: int64(v.Duration),
}
initEventInfo(LTEInfo, v.EventId)
l.EventList[v.EventId] = LTEInfo
AddEvent = append(AddEvent, v.EventId)
}
l.Triggered[v.Id] = struct{}{}
}
Remain := 0
//删除过期事件
for k, v := range l.EventList {
EndTime := v.StartT + v.Remian
if k == EVENT_TYPE_CAT_TRICK {
EndTime += 5 * 60 // 猫咪戏法事件显示时间为5分钟
}
if EndTime <= Now {
delete(l.EventList, k)
TimeoutEvent = append(TimeoutEvent, k)
continue
}
NowRemain := (v.StartT + v.Remian) - Now
Remain = GoUtil.IfTrue(Remain > 0, min(Remain, int(NowRemain)), int(NowRemain)).(int)
}
return Remain, TimeoutEvent, AddEvent
}
// 增加限时事件
func (l *LimitedTimeEventMod) AddEvent(EventId, Duration int) int64 {
v, ok := l.EventList[EventId]
if ok && v.StartT+v.Remian > GoUtil.Now() {
// 事件未过期
v.Remian += int64(Duration)
addEventInfo(v, EventId, Duration)
} else {
Event := &LTEInfo{
Remian: int64(Duration),
StartT: GoUtil.Now(),
}
initEventInfo(Event, EventId)
l.EventList[EventId] = Event
}
return l.EventList[EventId].Remian + l.EventList[EventId].StartT
}
// 每周刷新
func (l *LimitedTimeEventMod) WeekUpdate() {
l.Triggered = make(map[int]struct{})
}
func (l *LimitedTimeEventMod) GetMoneyCatReward(ChessList []int) []*item.Item {
L := l.EventList[EVENT_TYPE_MONEY_CAT]
if L == nil {
return nil
}
Star := mergeDataCfg.GetMergeStar(ChessList)
d := L.D.(*MoneyCat)
mul := d.Mul
MaxId := limitedTimeEventCfg.GetMoneyCatMax()
NextId := min(d.Id+1, MaxId)
NextMul, Cd := limitedTimeEventCfg.GetMoneyCat(NextId)
d.Id = NextId
d.Mul = NextMul
d.EndTime = GoUtil.Now() + int64(Cd)
Star = int(math.Ceil(float64(Star) * (mul - 1)))
return []*item.Item{{Id: item.ITEM_STAR_ID, Num: Star}}
}
func (l *LimitedTimeEventMod) BackData() *msg.ResLimitEvent {
Res := &msg.ResLimitEvent{}
EventList := make(map[int32]*msg.LimitEvent)
for k, v := range l.EventList {
EventList[int32(k)] = getLimitEventMsg(k, v)
}
Res.LimitEventList = EventList
return Res
}
func (l *LimitedTimeEventMod) ProgressBackData() *msg.ResLimitEventProgress {
r := make(map[int32]int32)
for k, v := range l.ProgressReward {
Type := limitedTimeEventCfg.GetProgressRewardType(v)
r[int32(k)] = int32(Type)
}
return &msg.ResLimitEventProgress{
Progress: int32(l.Progress),
ProgressReward: r,
ProgressMax: int32(l.ProgressMax),
}
}
// 获取流星雨奖励
func (l *LimitedTimeEventMod) GetMeteorReward(MergeList []int) []*item.Item {
MaxLv := 0
Star := 0
for _, v := range MergeList {
ChessLv := mergeDataCfg.GetLvById(v)
Star += mergeDataCfg.GetStarById(v)
if ChessLv > MaxLv {
MaxLv = ChessLv
}
}
Add := limitedTimeEventCfg.GetMeteorAdd(MaxLv)
NewStar := int(float64(Star) * (float64(Add) / 100))
NewStar = max(NewStar, 1)
return []*item.Item{{Id: item.ITEM_STAR_ID, Num: NewStar}}
}
// 获取宝箱雨奖励
func (l *LimitedTimeEventMod) GetChestReward(MergeList []int) []*item.Item {
Star := 0
for _, v := range MergeList {
Star += mergeDataCfg.GetStarById(v)
}
return limitedTimeEventCfg.GetChestReward(Star)
}
// 获取场景冲刺奖励
func (l *LimitedTimeEventMod) GetSceneDashReward() (int, []*item.Item) {
ProbList := limitedTimeEventCfg.GetSenceJackpotProb()
Id := GoUtil.RandMap(ProbList)
Items := limitedTimeEventCfg.GetSenceJackpotReward(Id)
if len(Items) > 1 {
// 多个奖励时,随机选择一个
Items = []*item.Item{GoUtil.RandItem(Items)}
}
return Id, Items
}
// 获取连击快手奖励
func (l *LimitedTimeEventMod) GetFastProduceReward(Energy int) ([]*item.Item, int64, int, error) {
Event, ok := l.EventList[EVENT_TYPE_FAST_PRODUCE]
if !ok {
return nil, 0, 0, fmt.Errorf("FastProduce event not exist")
}
Now := GoUtil.Now()
if Now < GoUtil.Int64(Event.Info["NextPlay"]) {
return nil, 0, 0, fmt.Errorf("FastProduce CD")
}
Times := GoUtil.Int(Event.Info["Times"])
Times++
Event.Info["Times"] = Times
MaxTimes := limitedTimeEventCfg.GetFastProduceMaxTimes()
Times = min(Times, MaxTimes)
CD := limitedTimeEventCfg.GetFastCD()
Event.Info["NextPlay"] = GoUtil.Now() + int64(CD) // CD5分钟
return limitedTimeEventCfg.GetFastProduceReward(Times, Energy), GoUtil.Now() + int64(CD), Event.Info["Times"].(int), nil
}
func (l *LimitedTimeEventMod) ResetFastProduceCD() {
Event, ok := l.EventList[EVENT_TYPE_FAST_PRODUCE]
if !ok {
return
}
Event.Info["NextPlay"] = 0
}
func (l *LimitedTimeEventMod) GetFastProduceInfo() (int64, int) {
Event, ok := l.EventList[EVENT_TYPE_FAST_PRODUCE]
if !ok {
return 0, 0
}
return GoUtil.Int64(Event.Info["NextPlay"]), GoUtil.Int(Event.Info["Times"])
}
// 增加进度
func (l *LimitedTimeEventMod) AddProgress(Lv int) {
UnlockLv := limitedTimeEventCfg.GetUnlockLv()
if Lv < UnlockLv {
return
}
l.Progress++
}
// 选择进度奖励
func (l *LimitedTimeEventMod) SelectProgressReward(Id, Lv, Energy int) ([]*item.Item, int, int, map[int]int, error) {
RewardId, ok := l.ProgressReward[Id]
RewardList := l.ProgressReward
if !ok {
return nil, 0, 0, nil, fmt.Errorf("RewardId not exist")
}
Item := limitedTimeEventCfg.GetProgressReward(RewardId)
OrderNum := l.ProgressMax
l.LastSelect = RewardId
l.ProgressReward = make(map[int]int)
l.Progress = 0
l.BonusNum++
l.ProgressMax = limitedTimeEventCfg.GetProgressMax(l.Lv, l.BonusNum)
// 重新生成进度奖励
SelectNum := limitedTimeEventCfg.GetProgressSelectNum(Lv)
BonusLv := limitedTimeEventCfg.GetBonusLv(Lv)
RandMap := limitedTimeEventCfg.GetProgressRewardRand(BonusLv)
// 体力小于200 high roller事件不进池子
if Energy < limitedTimeEventCfg.GetHighRollerNeedEnergy() {
delete(RandMap, limitedTimeEventCfg.GetJackpotIdByType(EVENT_TYPE_HIGH_ROLLER))
}
n := 0
r := make([]int, 0)
LastOption := l.LastOption
for n < 10 {
n++
r = GoUtil.RandMapNum(RandMap, SelectNum)
Id := 1
for _, v := range r {
l.ProgressReward[Id] = v
Id++
}
if !GoUtil.SliceEqual(LastOption, r) {
break
}
}
l.LastOption = r
l.FirstReward = true
return Item, limitedTimeEventCfg.GetProgressRewardType(RewardId), OrderNum, RewardList, nil
}
func (l *LimitedTimeEventMod) RemoveSuperOrder() bool {
if _, ok := l.EventList[EVENT_TYPE_SUPER_ORDER]; ok {
delete(l.EventList, EVENT_TYPE_SUPER_ORDER)
return true
}
return false
}
func (l *LimitedTimeEventMod) LuckyCat(ChessId int) error {
L := l.EventList[EVENT_TYPE_LUCKY_CAT]
if L == nil {
return fmt.Errorf("LuckyCat event not exist")
}
MaxEarning := limitedTimeEventCfg.GetLuckyCatMaxEarning(int(L.Remian))
d := L.D.(*LuckyCat)
Lv := mergeDataCfg.GetLvById(ChessId)
Earn := math.Pow(2, float64(Lv-1))
d.Earnings += int(Earn)
if d.Earnings >= MaxEarning {
delete(l.EventList, EVENT_TYPE_LUCKY_CAT)
}
return nil
}
func (l *LimitedTimeEventMod) AddCatTrickEnergy(Energy int) {
if l.EventList[EVENT_TYPE_CAT_TRICK] == nil {
return
}
Event := l.EventList[EVENT_TYPE_CAT_TRICK]
if Event.Remian+Event.StartT <= GoUtil.Now() {
return
}
// 事件未过期
d := Event.D.(*CatTrick)
d.Energy += Energy
}
func (l *LimitedTimeEventMod) SubPaybackDay() error {
if l.EventList[EVENT_TYPE_PAYBACK_DAY] == nil {
return fmt.Errorf("PaybackDay event not exist")
}
d := l.EventList[EVENT_TYPE_PAYBACK_DAY].D.(*PaybackDay)
if d.count <= 0 {
return fmt.Errorf("PaybackDay count is 0")
}
d.count--
if d.count <= 0 {
delete(l.EventList, EVENT_TYPE_PAYBACK_DAY)
}
return nil
}
func (l *LimitedTimeEventMod) GetCatTrickReward() ([]*item.Item, error) {
if l.EventList[EVENT_TYPE_CAT_TRICK] == nil {
return nil, fmt.Errorf("CatTrick event not exist")
}
d := l.EventList[EVENT_TYPE_CAT_TRICK].D.(*CatTrick)
if d.Energy < 100 {
return nil, fmt.Errorf("CatTrick energy not enough")
}
d.Energy -= 100
return []*item.Item{
{Id: item.ITEM_DIAMOND_ID, Num: 1},
}, nil
}
// #region 事件信息初始化
func initEventInfo(E *LTEInfo, EventType int) {
switch EventType {
case EVENT_TYPE_FAST_PRODUCE:
E.Info = map[string]interface{}{
"Times": 0,
"NextPlay": 0,
}
case EVENT_TYPE_MONEY_CAT:
E.D = &MoneyCat{
Id: 1,
EndTime: 0,
Mul: 1.1,
}
case EVENT_TYPE_LUCKY_CAT:
MaxEarning := limitedTimeEventCfg.GetLuckyCatMaxEarning(int(E.Remian))
E.D = &LuckyCat{
Earnings: 0,
MaxEarings: MaxEarning,
}
case EVENT_TYPE_PAYBACK_DAY:
E.D = &PaybackDay{
count: limitedTimeEventCfg.GetPaybackDay(),
}
case EVENT_TYPE_CAT_TRICK:
Type := limitedTimeEventCfg.GetCatTrickType(int(E.Remian))
E.D = &CatTrick{
List: []CatTrickInfo{
{
Id: 1,
Type: Type,
},
},
}
}
}
func addEventInfo(E *LTEInfo, EventType, Duration int) {
switch EventType {
case EVENT_TYPE_CAT_TRICK:
d := E.D.(*CatTrick)
d.List = append(d.List, CatTrickInfo{
Id: len(d.List) + 1,
Type: limitedTimeEventCfg.GetCatTrickType(Duration),
})
case EVENT_TYPE_LUCKY_CAT:
MaxEarning := limitedTimeEventCfg.GetLuckyCatMaxEarning(Duration)
d := E.D.(*LuckyCat)
d.MaxEarings += MaxEarning
case EVENT_TYPE_PAYBACK_DAY:
d := E.D.(*PaybackDay)
d.count += limitedTimeEventCfg.GetPaybackDay()
}
}
func getLimitEventMsg(t int, e *LTEInfo) *msg.LimitEvent {
Cd := 0
Mul := 0.0
Param := make(map[string]int32, 0)
ShowTime := int32(e.StartT + e.Remian)
EndTime := int32(e.StartT + e.Remian)
switch t {
case EVENT_TYPE_FAST_PRODUCE:
NextPlay := GoUtil.Int64(e.Info["NextPlay"])
Cd = int(max(NextPlay-GoUtil.Now(), 0))
case EVENT_TYPE_MONEY_CAT:
d := e.D.(*MoneyCat)
Cd = int(d.EndTime)
Mul = d.Mul
case EVENT_TYPE_LUCKY_CAT:
d := e.D.(*LuckyCat)
Param[msg.LimitEventParam_LUCKY_CAT_EARNINGS.String()] = int32(d.MaxEarings)
case EVENT_TYPE_CAT_TRICK:
d := e.D.(*CatTrick)
Energy := d.Energy
Param[msg.LimitEventParam_CAT_TRICK_ENERGY.String()] = int32(Energy)
info := d.List[0]
Param[msg.LimitEventParam_CAT_TRICK_TYPE.String()] = int32(info.Type)
Diamon1, Energy1 := limitedTimeEventCfg.GetCatTrickDiamond(info.Type)
if d.Energy >= Diamon1*Energy1 {
// 进度条已满
EndTime += 5 * 60 // 5分钟
}
case EVENT_TYPE_PAYBACK_DAY:
d := e.D.(*PaybackDay)
Param[msg.LimitEventParam_PAYBACK_DAY_COUNT.String()] = int32(d.count)
}
return &msg.LimitEvent{
EndTime: EndTime,
ShowTime: ShowTime,
Cd: int32(Cd),
Mul: float32(Mul),
StartTime: int32(e.StartT),
Param: Param,
}
}