537 lines
12 KiB
Go
537 lines
12 KiB
Go
package fishing
|
||
|
||
import (
|
||
"math/rand"
|
||
"mongo.games.com/game/gamesrv/base"
|
||
"mongo.games.com/game/srvdata"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// FishArray 鱼阵
|
||
type FishArray struct {
|
||
Type uint32 //鱼阵类型
|
||
Speed uint32 //鱼阵速度
|
||
Duration uint32 //持续时间
|
||
Fishs []*Fish //鱼阵中鱼
|
||
|
||
//Actions []*FishArrayAction //鱼阵动作
|
||
}
|
||
|
||
// AppearFish 出鱼
|
||
type AppearFish struct {
|
||
id uint64 //出鱼编号
|
||
aid uint32 //鱼阵编号
|
||
//mutex sync.Mutex //编号同步
|
||
start bool //是否出鱼
|
||
pause int64 //暂停时间
|
||
resumeTimer *time.Timer //恢复定时器
|
||
SceneEx *FishingSceneData
|
||
appearFishs map[int32]*AppearFishConfig //出鱼策略
|
||
fishPath map[int32]*FishPath //出鱼路径配置
|
||
mutex sync.Mutex //编号同步
|
||
}
|
||
|
||
type FishPath struct {
|
||
PathId int32
|
||
AppearTime int32
|
||
DisappearTime int32
|
||
}
|
||
|
||
type AppearFishConfig struct {
|
||
fishId int32 //对应fish表中的fishType
|
||
name string //鱼的名字
|
||
exp int32 //经验值
|
||
multiple []int32 //倍数
|
||
prob float64 //死亡概率 目前不用 看后期设计 每个场次单独控制 还是整体控制
|
||
baseRates float64 //基础概率 目前不用
|
||
path []int32 //出鱼路径
|
||
fishNum []int32 //出鱼数量
|
||
interval int32 //出鱼间隔
|
||
|
||
}
|
||
|
||
// Start 开始
|
||
func (a *AppearFish) Start() {
|
||
fishlogger.Trace("newFish 开始出鱼!!!!!!!!!!!!")
|
||
a.aid = FishArrayOne //鱼阵起始标记
|
||
a.start = true
|
||
//最短间隔
|
||
minInterval := int32(100000)
|
||
for _, v := range base.FishOutEx.FishOutPool {
|
||
if a.SceneEx.GetDBGameFree().GetSceneType() == v.SceneType && v.Interval < minInterval {
|
||
minInterval = v.Interval
|
||
}
|
||
}
|
||
|
||
//间隔差值 开始出鱼时候出鱼比较慢 让玩家早点看到屏幕鱼
|
||
var diffInterval int32
|
||
if minInterval > 1000 {
|
||
diffInterval = minInterval - 1000
|
||
}
|
||
|
||
//遍历出鱼
|
||
for _, v := range base.FishOutEx.FishOutPool {
|
||
if a.SceneEx.GetDBGameFree().GetSceneType() == v.SceneType {
|
||
tmp := v
|
||
//定时出鱼
|
||
time.AfterFunc(time.Duration(tmp.Interval-diffInterval)*time.Millisecond, func() {
|
||
a.do(tmp)
|
||
})
|
||
}
|
||
}
|
||
/* //定时鱼阵
|
||
time.AfterFunc(time.Duration(FishArrayInterval)*time.Millisecond, func() {
|
||
a.doArray()
|
||
})*/
|
||
|
||
//定时切换场景
|
||
time.AfterFunc(FishArrayInterval, func() {
|
||
a.cleanData()
|
||
})
|
||
}
|
||
|
||
// Stop 停止
|
||
func (a *AppearFish) Stop() {
|
||
a.start = false
|
||
}
|
||
|
||
// Pause 暂停
|
||
func (a *AppearFish) Pause(t int64) {
|
||
//暂停时间
|
||
a.pause = time.Now().Unix()
|
||
a.pause += (t / 1000)
|
||
|
||
//定时暂停
|
||
if a.resumeTimer != nil {
|
||
a.resumeTimer.Stop()
|
||
}
|
||
a.resumeTimer = time.AfterFunc(time.Duration(t)*time.Millisecond, func() {
|
||
a.resume()
|
||
})
|
||
}
|
||
|
||
// resume 恢复
|
||
func (a *AppearFish) resume() {
|
||
a.pause = 0
|
||
fishlogger.Trace("暂停结束,恢复出鱼!")
|
||
}
|
||
|
||
// do 执行
|
||
func (a *AppearFish) do(afc *base.AppearFish) {
|
||
if !a.start {
|
||
return
|
||
}
|
||
startTime := time.Now().UnixNano() / int64(time.Millisecond)
|
||
//定时出鱼
|
||
if a.pause != 0 {
|
||
//不能出就不出不延迟至鱼阵结束
|
||
time.AfterFunc(time.Duration(afc.Interval)*time.Millisecond, func() {
|
||
a.do(afc)
|
||
})
|
||
|
||
return
|
||
}
|
||
|
||
//出鱼数量
|
||
quantity := afc.FishNum[0]
|
||
if afc.FishNum[0] != afc.FishNum[1] {
|
||
//随机出鱼数量
|
||
quantity += rand.Int31n(int32(afc.FishNum[1] - afc.FishNum[0] + 1))
|
||
}
|
||
//创建出鱼切片
|
||
fishs := make([]*Fish, 0, quantity)
|
||
|
||
for i := 0; i < int(quantity); i++ {
|
||
//遍历鱼类
|
||
v := afc.FishId
|
||
|
||
//获取鱼的配置
|
||
//conf := a.fishConfig[afc.fishId]
|
||
conf := base.FishTemplateEx.FishPool[afc.FishId]
|
||
if conf == nil {
|
||
fishlogger.Errorf("出鱼 没有找到鱼的配置!!!!fishId = %v", afc.FishId)
|
||
continue
|
||
}
|
||
|
||
//出鱼路径 出多条一样的鱼 路径尽量不重复
|
||
pathTime := time.Now().UnixNano() / int64(time.Millisecond)
|
||
path := afc.Path[0]
|
||
var num = 0
|
||
for {
|
||
num++
|
||
if afc.Path[0] != afc.Path[1] {
|
||
path += rand.Int31n(int32(afc.Path[1] - afc.Path[0] + 1))
|
||
}
|
||
|
||
if a.PathUsable(path, fishs) && a.SceneEx.PathUsable(path) {
|
||
break
|
||
}
|
||
|
||
path = afc.Path[0]
|
||
}
|
||
fishlogger.Tracef("寻找路径耗时:%v,循环了多少次:%v", time.Now().UnixNano()/int64(time.Millisecond)-pathTime, num)
|
||
//创建出鱼
|
||
fish := new(Fish)
|
||
|
||
//设置属性
|
||
fish.TemplateID = v
|
||
fish.Path = path
|
||
fish.Exp = conf.EXP
|
||
//fish.SetrAppea(afc.FishAppearType)
|
||
|
||
//计算倍数 待确认怎么随机
|
||
//策划让直接用鱼谱里的GOLD值
|
||
multiple := conf.Gold[0]
|
||
if conf.Gold[0] != conf.Gold[1] {
|
||
multiple += rand.Int31n(conf.Gold[1] - conf.Gold[0] + 1)
|
||
}
|
||
|
||
//设置属性
|
||
fish.DropCoin = multiple
|
||
//这个参数是用于财神鱼 要不要待定
|
||
fish.MaxDropCoin = conf.Gold[1]
|
||
fish.Speed = conf.Speed
|
||
fish.Rate = conf.Rate
|
||
fish.Name = conf.Name
|
||
//设置出鱼编号
|
||
fish.FishID = int32(a.GetFishID())
|
||
fish.Event = afc.Event
|
||
//不指定能打死自己的玩家
|
||
//fish.SetPlayer(InvalidPlayer)
|
||
fishlogger.Infof("newfish 出鱼 fish = %v", fish)
|
||
//加入切片
|
||
fishs = append(fishs, fish)
|
||
}
|
||
//桌子增加鱼
|
||
a.SceneEx.AddFish(fishs, 0)
|
||
fishlogger.Trace("出鱼耗时:", time.Now().UnixNano()/int64(time.Millisecond)-startTime)
|
||
//定时出鱼
|
||
time.AfterFunc(time.Duration(afc.Interval)*time.Millisecond, func() {
|
||
a.do(afc)
|
||
})
|
||
//通知客户端出鱼
|
||
a.SceneEx.NotifyAppearFish(fishs)
|
||
|
||
}
|
||
|
||
func (a *AppearFish) doPreArray() {
|
||
if !a.start {
|
||
return
|
||
}
|
||
//通知客户端 鱼潮来临
|
||
//a.pfacb()
|
||
}
|
||
|
||
// 鱼阵 doArray 执行
|
||
func (a *AppearFish) doArray() {
|
||
/*
|
||
if !a.start {
|
||
return
|
||
}
|
||
|
||
//定时鱼阵
|
||
if a.pause != 0 {
|
||
time.AfterFunc(time.Duration(a.GetPauseTime())*time.Second, func() {
|
||
a.doArray()
|
||
})
|
||
|
||
return
|
||
}
|
||
|
||
//最大持续时间
|
||
var maxDuration uint32
|
||
|
||
//创建鱼阵切片
|
||
var fishArrays []FishArray
|
||
|
||
//子鱼阵编号
|
||
ids := CMIns().FishArrayConf[a.aid-1]
|
||
a.aid = a.aid%FishArraySeven + 1
|
||
|
||
//遍历子鱼阵
|
||
for _, v := range ids {
|
||
//创建鱼阵
|
||
var fishArray FishArray
|
||
|
||
//获取鱼阵配置
|
||
fishArrayConfig := CMIns().GetFishArrayConfig(v)
|
||
|
||
//遍历鱼阵组
|
||
for _, i := range fishArrayConfig.FishArrayGroups {
|
||
//获取鱼类配置
|
||
conf := CMIns().GetFishConfig(i.FishType)
|
||
if conf == nil {
|
||
continue
|
||
}
|
||
|
||
//遍历鱼阵鱼
|
||
for _, j := range i.FishArrayFishs {
|
||
//创建出鱼
|
||
fish := new(Fish)
|
||
|
||
//计算倍数
|
||
multiple := conf.FishMinMultiple
|
||
if conf.FishMinMultiple != conf.FishMaxMultiple {
|
||
multiple += uint32(rand.Int31n(int32(conf.FishMaxMultiple - conf.FishMinMultiple + 1)))
|
||
}
|
||
|
||
//设置属性
|
||
fish.SetType(i.FishType)
|
||
fish.SetMultiple(multiple)
|
||
fish.SetProbability(conf.FishProbability)
|
||
fish.SetLotteryProbability(conf.LotteryProbability)
|
||
fish.SetName(conf.FishName)
|
||
fish.SetAngle(j.FishAngle)
|
||
fish.SetX(j.FishX)
|
||
fish.SetY(j.FishY)
|
||
|
||
//设置出鱼编号
|
||
fish.SetID(a.GetFishID())
|
||
|
||
//不指定能打死自己的玩家
|
||
fish.SetPlayer(InvalidPlayer)
|
||
|
||
//加入切片
|
||
fishArray.Fishs = append(fishArray.Fishs, fish)
|
||
}
|
||
}
|
||
|
||
//设置鱼阵属性
|
||
fishArray.Type = fishArrayConfig.FishArrayType
|
||
fishArray.Speed = fishArrayConfig.FishArraySpeed
|
||
fishArray.Duration = fishArrayConfig.FishArrayDuration
|
||
fishArray.Actions = fishArrayConfig.FishArrayActions
|
||
|
||
//最高持续时间
|
||
if maxDuration < fishArrayConfig.FishArrayDuration {
|
||
maxDuration = fishArrayConfig.FishArrayDuration
|
||
}
|
||
|
||
//加入鱼阵切片
|
||
fishArrays = append(fishArrays, fishArray)
|
||
}
|
||
|
||
//清空鱼
|
||
a.table.ClearFish()
|
||
|
||
//暂停出鱼
|
||
a.Pause(int64(maxDuration + 5000))
|
||
|
||
//增加鱼阵
|
||
a.table.AddFishArray(fishArrays)
|
||
|
||
//定时鱼阵
|
||
time.AfterFunc(time.Duration(CMIns().FishArrayInterval)*time.Millisecond, func() {
|
||
a.doArray()
|
||
})
|
||
//time.AfterFunc(time.Duration(CMIns().FishArrayInterval-15)*time.Millisecond, func() {
|
||
// a.doPreArray()
|
||
//})
|
||
|
||
//设置标识
|
||
a.table.SetFishArray(true)
|
||
|
||
//鱼阵回调 //通知客户端
|
||
a.facb(0, fishArrays)
|
||
*/
|
||
|
||
}
|
||
|
||
/*// DeadFishArray 死鱼鱼阵
|
||
func (a *AppearFish) DeadFishArray(tp uint32, fid uint64) {
|
||
//获取配置
|
||
conf := CMIns().GetFishConfig(tp)
|
||
if conf == nil {
|
||
return
|
||
}
|
||
|
||
//校验鱼类
|
||
if conf.DeadFish == 0 {
|
||
return
|
||
}
|
||
|
||
//确定鱼类
|
||
fishType := conf.DeadFish
|
||
redFishType := conf.DeadRedFish
|
||
|
||
//获取鱼类配置
|
||
fishconfig := CMIns().GetFishConfig(fishType)
|
||
if fishconfig == nil {
|
||
return
|
||
}
|
||
|
||
//创建鱼阵切片
|
||
var fishArrays []FishArray
|
||
|
||
//随机红鱼位置
|
||
index := int(rand.Int31n(int32(NumberPreCircle)))
|
||
|
||
//获取红鱼配置
|
||
redFishConfig := CMIns().GetFishConfig(redFishType)
|
||
|
||
//发散三圈
|
||
for i := 0; i < CircleNumber; i++ {
|
||
//创建鱼阵
|
||
var fishArray FishArray
|
||
for j := 0; j < NumberPreCircle; j++ {
|
||
//创建出鱼
|
||
fish := new(Fish)
|
||
|
||
//红鱼属性
|
||
if i == 2 && j == index && redFishConfig != nil {
|
||
//计算倍数
|
||
multiple := redFishConfig.FishMinMultiple
|
||
if redFishConfig.FishMinMultiple != redFishConfig.FishMaxMultiple {
|
||
multiple += uint32(rand.Int31n(int32(redFishConfig.FishMaxMultiple - redFishConfig.FishMinMultiple + 1)))
|
||
}
|
||
|
||
//设置属性
|
||
fish.SetType(redFishType)
|
||
fish.SetMultiple(multiple)
|
||
fish.SetProbability(redFishConfig.FishProbability)
|
||
fish.SetLotteryProbability(redFishConfig.LotteryProbability)
|
||
fish.SetName(redFishConfig.FishName)
|
||
} else {
|
||
//计算倍数
|
||
multiple := fishconfig.FishMinMultiple
|
||
if fishconfig.FishMinMultiple != fishconfig.FishMaxMultiple {
|
||
multiple += uint32(rand.Int31n(int32(fishconfig.FishMaxMultiple - fishconfig.FishMinMultiple + 1)))
|
||
}
|
||
|
||
//设置属性
|
||
fish.SetType(fishType)
|
||
fish.SetMultiple(multiple)
|
||
fish.SetProbability(fishconfig.FishProbability)
|
||
fish.SetLotteryProbability(fishconfig.LotteryProbability)
|
||
fish.SetName(fishconfig.FishName)
|
||
}
|
||
|
||
fish.SetAngle((float32(360) / float32(NumberPreCircle)) * float32(j))
|
||
|
||
//设置出鱼编号
|
||
fish.SetID(a.GetFishID())
|
||
|
||
//不指定能打死自己的玩家
|
||
fish.SetPlayer(InvalidPlayer)
|
||
|
||
//加入切片
|
||
fishArray.Fishs = append(fishArray.Fishs, fish)
|
||
}
|
||
|
||
//设置鱼阵属性
|
||
fishArray.Type = FishArrayDisperse
|
||
fishArray.Speed = CMIns().FishArrays[17+i].FishArraySpeed
|
||
fishArray.Duration = CMIns().FishArrays[17+i].FishArrayDuration
|
||
//fishArray.Actions = CMIns().FishArrays[17+i].FishArrayActions
|
||
|
||
//加快死鱼鱼阵出圈速度
|
||
fishArrayAction := &FishArrayAction{
|
||
Path: CMIns().FishArrays[17+i].FishArrayActions[0].Path,
|
||
Time: CMIns().FishArrays[17+i].FishArrayActions[0].Time / 2,
|
||
}
|
||
|
||
fishArray.Actions = append(fishArray.Actions, fishArrayAction)
|
||
fishArray.Actions = append(fishArray.Actions, CMIns().FishArrays[17+i].FishArrayActions[1])
|
||
|
||
//加入鱼阵切片
|
||
fishArrays = append(fishArrays, fishArray)
|
||
}
|
||
|
||
//增加鱼阵
|
||
a.table.AddFishArray(fishArrays)
|
||
|
||
//通知客户端鱼阵消息
|
||
a.facb(fid, fishArrays)
|
||
}
|
||
*/
|
||
//====================
|
||
//simple interface
|
||
//====================
|
||
|
||
// GetID 出鱼编号
|
||
func (a *AppearFish) GetID() uint64 {
|
||
return a.id
|
||
}
|
||
|
||
// GetAID 鱼阵编号
|
||
func (a *AppearFish) GetAID() uint32 {
|
||
return a.aid
|
||
}
|
||
|
||
// IsStart 是否开始
|
||
func (a *AppearFish) IsStart() bool {
|
||
return a.start
|
||
}
|
||
|
||
// IsPause 是否暂停
|
||
func (a *AppearFish) IsPause() bool {
|
||
return a.pause != 0
|
||
}
|
||
|
||
// GetFishID 获取出鱼编号
|
||
func (a *AppearFish) GetFishID() uint64 {
|
||
a.mutex.Lock()
|
||
defer a.mutex.Unlock()
|
||
|
||
a.id++
|
||
return a.id
|
||
}
|
||
|
||
// GetPauseTime 获取暂停时间
|
||
func (a *AppearFish) GetPauseTime() int64 {
|
||
surplus := a.pause - time.Now().Unix()
|
||
if surplus <= 0 {
|
||
surplus = 1
|
||
}
|
||
|
||
return surplus
|
||
}
|
||
|
||
// PathUsable 路径可用
|
||
func (a *AppearFish) PathUsable(path int32, fishs []*Fish) bool {
|
||
for _, v := range fishs {
|
||
if v.Path == path {
|
||
return false
|
||
}
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// 鱼潮策略初始化
|
||
func (a *AppearFish) InitFishArray() {
|
||
//后续再做
|
||
}
|
||
|
||
// 初始化鱼的路径
|
||
func (a *AppearFish) InitFishPath() {
|
||
a.fishPath = make(map[int32]*FishPath)
|
||
for _, v := range srvdata.PBDB_FishPathMgr.Datas.Arr {
|
||
a.fishPath[v.Id] = &FishPath{
|
||
PathId: v.Id,
|
||
AppearTime: v.AppearTime,
|
||
DisappearTime: v.DisappearTime,
|
||
}
|
||
}
|
||
}
|
||
|
||
// 清理数据
|
||
func (a *AppearFish) cleanData() {
|
||
//重置出鱼编号
|
||
a.id = 0
|
||
//重置场景里的鱼
|
||
a.SceneEx.fish_list = make(map[int32]*Fish) // 鱼标识 存活的鱼
|
||
//重置逻辑帧
|
||
a.SceneEx.TimePoint = 0
|
||
fishlogger.Trace("定时切换场景,清理数据!!!!!!!!")
|
||
//通知客户端切换场景
|
||
a.SceneEx.NotifyChangeScene()
|
||
//定时切换场景
|
||
time.AfterFunc(FishArrayInterval, func() {
|
||
if a.start {
|
||
a.cleanData()
|
||
}
|
||
})
|
||
}
|