package gamelogic
import (
"bet24.com/servers/common"
"bet24.com/servers/games/fish/bullet"
_ "bet24.com/servers/games/fish/config"
"bet24.com/servers/games/fish/fish"
"bet24.com/servers/games/fish/fishcommon"
item "bet24.com/servers/micros/item_inventory/proto"
"bet24.com/servers/user"
"bet24.com/utils"
"encoding/json"
"fmt"
"math/rand"
)
func (ts *tablesink) OnGameMessage(userIndex int32, cmd, data string) bool {
usr := ts.table.GetPlayer(userIndex)
if usr == nil {
ts.table.LogWithTableId("tablesink.OnGameMessage,usr[%d] not exist", userIndex)
return false
}
chairId := usr.GetUserChairId()
if !fishcommon.IsValidChair(chairId) {
ts.table.LogWithTableId("tablesink.OnGameMessage invalid chair %d", chairId)
return false
}
defer utils.TimeCost(fmt.Sprintf("tablesink.OnGameMessage[%s]", cmd))()
switch cmd {
case fishcommon.ADD_BULLET:
ts.addBullet(usr, cmd, data, chairId)
case fishcommon.CATCH_FISH:
ts.catchFish(usr, cmd, data, chairId)
case fishcommon.SET_BULLET:
ts.setBullet(usr, cmd, data)
case fishcommon.SET_CANNON:
ts.setCannon(usr, cmd, data)
case fishcommon.USE_ITEM:
ts.useItem(usr, cmd, data)
case fishcommon.GAME_SCENE:
//ts.table.NotifySceneChanged(chairId)
gameScene := ts.getChairScene()
ts.table.SendGameData(userIndex, fishcommon.GAME_SCENE, gameScene)
// 如果鱼群来了
if ts.groupState {
ts.sendGroup(userIndex, false)
}
case fishcommon.SPECIAL_CATCH:
ts.specialCatch(usr, cmd, data)
case fishcommon.SPECIAL_CATCH_END:
ts.specialCatchEnd(usr, cmd, data)
case fishcommon.SPECIAL_SHOOT:
ts.specialShoot(usr, cmd, data)
case fishcommon.UPGRADE_BULLET:
ts.upgradeBullet(usr, cmd, data)
default:
ts.table.LogWithTableId("tablesink.HandleCmd usr(%d),unhandled cmd(%v:%v) ", usr.GetUserId(), cmd, data)
return false
}
return false
}
func (ts *tablesink) addBullet(usr *user.UserInfo, cmd, data string, chairID int) {
var add fishcommon.AddBullet
err := json.Unmarshal([]byte(data), &add)
if err != nil {
ts.table.LogWithTableId("tablesink.addBullet failed %v", data)
return
}
blt := bullet.GetBullet(add.BulletID)
if blt == nil {
ts.table.LogWithTableId("tablesink.addBullet invalid bulletID %d", add.BulletID)
return
}
// 检查金币是否足够
//if !usr.ModifyGold(-bullet.Odds) {
if !ts.checkGold(usr, blt.Odds, chairID) {
ts.table.LogWithTableId("tablesink.addBullet not enough gold")
ts.sendBulletFailed(usr, add.ClientID, "not enough gold", add.BulletID)
return
}
b := ts.bulletmgr.addBullet(usr.GetUserId(), add.BulletID, add.Angle, add.FishKey, chairID, blt.Odds)
b.ClientID = add.ClientID
ts.broadcastBullet(b)
}
func (ts *tablesink) checkGold(usr *user.UserInfo, bulletOdds int, chairID int) bool {
// 总金币
gold := usr.GetUserGold()
flyingBullet := 0 //ts.bulletmgr.getFlyingBullet(usr.GetUserId())
if flyingBullet+bulletOdds > gold {
ts.table.LogWithTableId("tablesink.checkGold flyingBullet(%d) + bulletOdds(%d) > gold(%d)", flyingBullet, bulletOdds, gold)
return false
}
return true
}
func (ts *tablesink) sendBulletFailed(usr *user.UserInfo, clientID int, msg string, bulledID int) {
data := fmt.Sprintf(`{"ClientID":%d,"Msg":"%v","BulletID":%d}`, clientID, msg, bulledID)
ts.table.SendGameData(usr.GetUserIndex(), fishcommon.BULLET_FAILED, data)
}
func (ts *tablesink) sendBullet(userIndex int32, bullet *bullet.Bullet) {
msg := fishcommon.ADD_BULLET
data, _ := json.Marshal(bullet)
msgData := string(data)
ts.table.SendGameData(userIndex, msg, msgData)
}
func (ts *tablesink) broadcastBullet(bullet *bullet.Bullet) {
ts.sendBullet(-1, bullet)
}
func (ts *tablesink) broadcastData(msg, data string) {
ts.table.SendGameData(-1, msg, data)
}
func (ts *tablesink) sendFish(userIndex int32, fish *fish.Fish) {
msg := fishcommon.ADD_FISH
data, _ := json.Marshal(fish)
ts.table.SendGameData(userIndex, msg, string(data))
}
func (ts *tablesink) broadcastFish(fish *fish.Fish) {
ts.sendFish(-1, fish)
}
func (ts *tablesink) getRoomUser(userId int) *fishuser {
for _, v := range ts.Users {
if v == nil {
continue
}
if v.userId == userId {
return v
}
}
return nil
}
func (ts *tablesink) onCatchFish(fi *fish.FishInfo, earn int, userName string) {
if fi.BonusFish == 0 {
return
}
if earn <= 0 {
return
}
//msg := fmt.Sprintf("[%s]在[%s]捕获了[%s],获得了金币[%d]", userName, config.Room.RoomDesc, fi.Name, earn)
//coreservice.SendBroadcast(-1, fishcommon.GAMEID, 0, msg, "")
}
func (ts *tablesink) catchFish(usr *user.UserInfo, cmd, data string, chairID int) {
var catch fishcommon.CatchFish
fishUser := ts.getRoomUser(usr.GetUserId())
if fishUser == nil {
ts.table.LogWithTableId("tablesink.catchFish failed fishUser[%d,%d] not found", usr.GetUserId(), chairID)
return
}
err := json.Unmarshal([]byte(data), &catch)
if err != nil {
ts.table.LogWithTableId("tablesink.catchFish failed %v", data)
return
}
// 查询下bullet和fish
bullet := ts.bulletmgr.getBullet(catch.BulletKey)
if bullet == nil || bullet.UserID != usr.GetUserId() {
ts.table.LogWithTableId("tablesink.catchFish failed bullet not found")
ts.sendCatchFailed(usr, catch, 0, false)
return
}
f := ts.fishmgr.getFish(catch.FishKey)
if f == nil || f.IsDead() {
ts.table.LogWithTableId("tablesink.catchFish failed fish not found or dead %d", catch.FishKey)
//ts.fishmgr.dump()
ts.sendCatchFailed(usr, catch, bullet.BulletID, false)
return
}
fi := fish.GetFishInfo(f.FishID)
if fi == nil {
ts.table.LogWithTableId("catshFish fishID[%d] invalid", f.FishID)
return
}
ok := ts.writeUserGold(usr, fishUser, -bullet.GetOdds())
if !ok {
ts.table.LogWithTableId("tablesink.catchFish failed insufficient balance")
//ts.fishmgr.dump()
ts.sendCatchFailed(usr, catch, bullet.BulletID, false)
return
}
fishUser.setWaterPoolValue(-bullet.GetOdds(), bullet.GetOdds())
// 添加奖池
if ts.prizePool != nil {
ts.sendPoolValue()
}
var ret fishcommon.CatchFishRet
ret.CatchFish = catch
ret.BulletID = bullet.BulletID
ret.UserId = usr.GetUserId()
ret.IsCatch = f.IsCatch(fishUser.getUserOdds(), ts.systemOdds, ts.roomInfo.OddsExtra)
if ret.IsCatch {
f.Status = fish.Fish_Dead
ret.Coin = bullet.GetOdds() * f.GetOdds()
ts.onCatchFish(fi, ret.Coin, usr.GetUserNickName())
// 是否产生道具
ret.ItemId, ret.ItemCount = ts.fishDrop.getDropItem(f.FishID)
if ret.ItemCount > 0 {
var items []item.ItemPack
items = append(items, item.ItemPack{ItemId: ret.ItemId, Count: ret.ItemCount})
item.AddItems(usr.GetUserId(), items, "捕鱼掉落", common.LOGTYPE_FISH_DROP)
}
// 转盘鱼
ret.PrizeWheelItemId, ret.PrizeWheelItemCount = f.GetPrize()
if ret.PrizeWheelItemCount > 0 {
var items []item.ItemPack
items = append(items, item.ItemPack{ItemId: ret.PrizeWheelItemId, Count: ret.PrizeWheelItemCount})
item.AddItems(usr.GetUserId(), items, "捕鱼转盘", common.LOGTYPE_FISH_DROP)
}
if fi.SpecialType > 0 {
ts.table.LogWithTableId("catchFish 击中特效鱼 %v", fi)
// 如果是slot
if fi.SpecialEffect == item.SpecialEffect_Slot {
ret.SlotMultiple = fi.Param1 + rand.Intn(fi.Param2-fi.Param1)
ret.Coin += bullet.GetOdds() * ret.SlotMultiple
ts.table.LogWithTableId("catchFish 击中Slot鱼 产生倍数 %d", ret.SlotMultiple)
} else {
ts.Users[chairID].addSpecial(f.FishKey, bullet.GetOdds(), fi.SpecialEffect, fi.SpecialType, fi.Param1, fi.Param2)
}
} else {
ts.table.LogWithTableId("catchFish 击中普通鱼 %v", fi)
}
ts.broadcastCatch(ret, false)
// 是否产生奖池
if ts.prizePool != nil && fi.BonusFish > 0 {
var draw fishcommon.PrizePoolDraw_resp
draw.UserId = usr.GetUserId()
draw.Bingo, draw.Point, draw.Pool = ts.prizePool.Draw(ret.UserId, bullet.GetOdds())
if draw.Bingo {
// 写分
ts.writeUserGold(usr, fishUser, draw.Point)
fishUser.setWaterPoolValue(draw.Point, 0)
}
ts.broadcastPoolDraw(draw)
ts.sendPoolEnergy(ret.UserId)
}
} else {
ts.sendCatch(usr.GetUserIndex(), ret, false)
}
// ts.table.LogWithTableId("catchFish UserID[%d],BulletOdds[%d],Win[%d],FishID[%d]", ret.UserId, bullet.GetOdds(), ret.Coin, catch.FishKey)
// 写分
ts.writeUserGold(usr, fishUser, ret.Coin)
fishUser.setWaterPoolValue(ret.Coin, 0)
// 加入纪录
ts.recordmgr.addUserRecord(ret.UserId, f.FishID, bullet.GetOdds(), ret.Coin)
// 删除子弹
ts.bulletmgr.removeBullet(catch.BulletKey)
}
func (ts *tablesink) sendConfig(userIndex int32) {
ts.table.SendGameData(userIndex, fishcommon.CONFIG_BULLET, bullet.GetConfig())
ts.table.SendGameData(userIndex, fishcommon.CONFIG_FISH, fish.GetFishConfig())
}
func (ts *tablesink) broadcastCatch(catch fishcommon.CatchFishRet, isSpecial bool) {
ts.sendCatch(-1, catch, isSpecial)
}
func (ts *tablesink) sendCatch(userIndex int32, catch fishcommon.CatchFishRet, isSpecial bool) {
msg := fishcommon.CATCH_FISH
if isSpecial {
msg = fishcommon.SPECIAL_CATCH
}
data, _ := json.Marshal(catch)
msgData := string(data)
ts.table.SendGameData(userIndex, msg, msgData)
}
func (ts *tablesink) sendCatchFailed(usr *user.UserInfo, catch fishcommon.CatchFish, bulletID int, isSpecial bool) {
msg := fishcommon.CATCH_FAILED
if isSpecial {
msg = fishcommon.SPECIAL_CATCH
}
var f fishcommon.CatchFishFailed
f.CatchFish = catch
f.BulletID = bulletID
data, _ := json.Marshal(f)
msgData := string(data)
ts.table.SendGameData(usr.GetUserIndex(), msg, msgData)
}
func (ts *tablesink) setBullet(usr *user.UserInfo, cmd, data string) {
var bulletID fishcommon.SetBullet
err := json.Unmarshal([]byte(data), &bulletID)
if err != nil {
ts.table.LogWithTableId("tablesink.setBullet failed %v", data)
return
}
fishUser := ts.getRoomUser(usr.GetUserId())
if fishUser == nil {
return
}
if fishUser.setBullet(bulletID.BulletID) {
// 广播玩家信息
ts.broadCastUserInfo(usr)
}
}
func (ts *tablesink) setCannon(usr *user.UserInfo, cmd, data string) {
var cannon fishcommon.SetCannon
err := json.Unmarshal([]byte(data), &cannon)
if err != nil {
ts.table.LogWithTableId("tablesink.setCannon failed %v", data)
return
}
fishUser := ts.getRoomUser(usr.GetUserId())
if fishUser == nil {
return
}
if fishUser.setCannon(cannon.Cannon, true) {
// 广播玩家信息
ts.broadCastUserInfo(usr)
} else {
ts.table.SendGameData(usr.GetUserIndex(), cmd, "setCannon failed")
}
}
func (ts *tablesink) useItem(usr *user.UserInfo, cmd, data string) {
var itm fishcommon.UseItem
err := json.Unmarshal([]byte(data), &itm)
if err != nil {
ts.table.LogWithTableId("tablesink.useItem failed %v", data)
return
}
roomUser := ts.getRoomUser(usr.GetUserId())
if roomUser == nil {
ts.table.LogWithTableId("tablesink.useItem roomUser not found %d", usr.GetUserId())
return
}
bl := bullet.GetBullet(roomUser.getBulletId())
bulletOdds := ts.roomInfo.BulletMin
if bl != nil {
bulletOdds = bl.Odds
}
itm.UserId = usr.GetUserId()
succeeded, _ := item.Consume(itm.UserId, itm.ItemId, 0, 1, 0)
if !succeeded {
// user类已经广播过失败的消息了
return
}
//coreservice.DoTaskAction(itm.UserId, task.TaskAction_user_item, 1)
// 广播玩家信息
ts.broadCastUseItem(itm)
extra := item.GetItemEffect(itm.ItemId) // 特殊道具后面处理
effectType := extra.SpecialType
specialEffect := extra.SpecialEffect
if specialEffect > 0 {
// 如果是冰冻效果
if specialEffect == item.SpecialEffect_Frozen {
ts.addEffecting(specialEffect, extra.Param1)
// 延长所有鱼的生命
ts.fishmgr.addExtraLife(extra.Param1)
} else {
// 如果是激光道具
roomUser.addSpecial(itm.ItemId, bulletOdds, specialEffect, effectType, extra.Param1, extra.Param2)
}
}
}
func (ts *tablesink) specialCatch(usr *user.UserInfo, cmd, data string) {
var sc fishcommon.SpecialCatch
err := json.Unmarshal([]byte(data), &sc)
if err != nil {
ts.table.LogWithTableId("tablesink.specialCatch failed %v", data)
return
}
roomUser := ts.getRoomUser(usr.GetUserId())
if roomUser == nil {
ts.table.LogWithTableId("tablesink.specialCatch roomUser not found %d", usr.GetUserId())
return
}
for _, v := range sc.TargetFishKeys {
catch := fishcommon.CatchFish{BulletKey: 0, FishKey: v}
f := ts.fishmgr.getFish(v)
if f == nil || f.IsDead() {
ts.table.LogWithTableId("tablesink.specialCatch failed fish not found or dead %d", v)
ts.sendCatchFailed(usr, catch, 0, true)
continue
}
fi := fish.GetFishInfo(f.FishID)
if fi == nil {
ts.table.LogWithTableId("catshFish fishID[%d] invalid", f.FishID)
continue
}
bulletOdds, power := roomUser.useSpecial(sc.OriginFishKey)
if power == 0 {
ts.table.LogWithTableId("specialCatch no power")
// roomUser.removeSpecial(sc.OriginFishKey)
return
}
// 计算是否捕获
var ret fishcommon.CatchFishRet
ret.CatchFish = catch
ret.BulletID = 0
ret.UserId = usr.GetUserId()
isCatch := false
for i := 0; i < power; i++ {
isCatch = f.IsCatch(roomUser.getUserOdds(), ts.systemOdds, ts.roomInfo.OddsExtra)
if isCatch {
break
}
}
ret.IsCatch = isCatch
if !ret.IsCatch {
ts.sendCatch(usr.GetUserIndex(), ret, true)
continue
}
f.Status = fish.Fish_Dead
ret.Coin = bulletOdds * f.GetOdds()
ts.onCatchFish(fi, ret.Coin, usr.GetUserNickName())
// 是否产生道具
ret.ItemId, ret.ItemCount = ts.fishDrop.getDropItem(f.FishID)
if ret.ItemCount > 0 {
var items []item.ItemPack
items = append(items, item.ItemPack{ItemId: ret.ItemId, Count: ret.ItemCount})
item.AddItems(usr.GetUserId(), items, "捕鱼掉落", common.LOGTYPE_FISH_DROP)
}
// 转盘鱼
ret.PrizeWheelItemId, ret.PrizeWheelItemCount = f.GetPrize()
if ret.PrizeWheelItemCount > 0 {
var items []item.ItemPack
items = append(items, item.ItemPack{ItemId: ret.PrizeWheelItemId, Count: ret.PrizeWheelItemCount})
item.AddItems(usr.GetUserId(), items, "捕鱼转盘", common.LOGTYPE_FISH_DROP)
}
roomUser.specialUsed(sc.OriginFishKey, ret.Coin)
if fi.SpecialType > 0 {
// 如果是slot
if fi.SpecialEffect == item.SpecialEffect_Slot {
ret.SlotMultiple = fi.Param1 + rand.Intn(fi.Param2-fi.Param1)
ret.Coin = bulletOdds * ret.SlotMultiple
} else {
roomUser.addSpecial(f.FishKey, bulletOdds, fi.SpecialEffect, fi.SpecialType, fi.Param1, fi.Param2)
}
}
ts.broadcastCatch(ret, true)
ts.table.LogWithTableId("specialCatch UserID[%d],BulletOdds[%d],Win[%d],FishID[%d]", ret.UserId, bulletOdds, ret.Coin, catch.FishKey)
// 写分
ts.writeUserGold(usr, roomUser, ret.Coin)
roomUser.setWaterPoolValue(ret.Coin, 0)
// 加入纪录
ts.recordmgr.getUserRecord(ret.UserId).addRecord(f.FishID, 0, ret.Coin)
}
}
func (ts *tablesink) specialShoot(usr *user.UserInfo, cmd, data string) {
ts.broadcastData(cmd, data)
}
func (ts *tablesink) specialCatchEnd(usr *user.UserInfo, cmd, data string) {
var sc fishcommon.SpecialCatchEnd
err := json.Unmarshal([]byte(data), &sc)
if err != nil {
ts.table.LogWithTableId("tablesink.specialCatchEnd failed %v", data)
return
}
sc.UserId = usr.GetUserId()
roomUser := ts.getRoomUser(usr.GetUserId())
if roomUser == nil {
ts.table.LogWithTableId("tablesink.specialCatchEnd roomUser not found %d", usr.GetUserId())
return
}
sc.TotalEarn = roomUser.removeSpecial(sc.OriginFishKey)
d, _ := json.Marshal(sc)
ts.broadcastData(cmd, string(d))
}
func (ts *tablesink) upgradeBullet(usr *user.UserInfo, cmd, data string) {
roomUser := ts.getRoomUser(usr.GetUserId())
if roomUser == nil {
ts.table.LogWithTableId("tablesink.upgradeBullet roomUser not found %d", usr.GetUserId())
return
}
var ret fishcommon.UpgradeBullet_resp
curBulletId := roomUser.getMaxBulletId()
// 如果已经是最高等级了
if curBulletId == ts.roomInfo.BulletMax {
ts.table.LogWithTableId("tablesink.upgradeBullet 已经是最高等级了")
ret.Succeeded = false
ret.ErrorMsg = "升级失败,已经是本房间最高等级"
d, _ := json.Marshal(ret)
ts.table.SendGameData(usr.GetUserIndex(), cmd, string(d))
return
}
count := bullet.GetUpgradeCount(curBulletId)
if count == 0 {
ts.table.LogWithTableId("tablesink.upgradeBullet failed count == 0")
ret.Succeeded = false
ret.ErrorMsg = "升级失败"
d, _ := json.Marshal(ret)
ts.table.SendGameData(usr.GetUserIndex(), cmd, string(d))
return
}
// 此处暂时写死
/*
原本需要扣除精华来升级子弹
itemId := common.ESSENCE_ITEMID
ok, _ := user.UseItem(itemId, 0, count)
if !ok {
ret.Succeeded = false
ret.ErrorMsg = "升级失败,精华不足!"
d, _ := json.Marshal(ret)
go user.WriteMsg(cmd, string(d))
return
}
*/
ret.Succeeded = true
d, _ := json.Marshal(ret)
ts.table.SendGameData(usr.GetUserIndex(), cmd, string(d))
roomUser.setMaxBulletId(curBulletId + 1)
ts.broadCastUserInfo(usr)
}
func (ts *tablesink) sendPoolValue() {
ts.broadcastPoolValue = true
}
func (ts *tablesink) broadcastPool() {
if true {
return
}
if ts.prizePool == nil {
return
}
data := fmt.Sprintf("%d", ts.prizePool.GetPoolValue())
ts.broadcastData(fishcommon.POOL_VALUE, data)
}
func (ts *tablesink) broadcastPoolDraw(draw fishcommon.PrizePoolDraw_resp) {
data, _ := json.Marshal(draw)
ts.broadcastData(fishcommon.POOL_DRAW, string(data))
}
func (ts *tablesink) writeUserGold(usr *user.UserInfo, fUser *fishuser, amount int) bool {
//ok, _ := ts.table.WriteUserMoney(userId, amount, tax, status, scoreType, ts.roomInfo.RoomName)
// 这里不实际写分,只修改变量
gold := usr.GetUserGold()
if gold+amount < 0 {
return false
}
usr.SetUserGold(gold + amount)
fUser.addScore(amount)
return true
}
func (ts *tablesink) doWriteUserGold(fUser *fishuser) {
consume, earn := fUser.getConsumeAndEarnAndClear()
//ts.table.LogWithTableId("doWriteUserGold UserId[%d] consume[%d] earn[%d]", fUser.userId, consume, earn)
if consume < 0 {
ts.table.WriteUserMoney(fUser.userId, consume, 0, 0, 1, ts.roomInfo.RoomName)
}
if earn > 0 {
ts.table.WriteUserMoney(fUser.userId, earn, 0, 0, 2, ts.roomInfo.RoomName)
}
}
func (ts *tablesink) onTimerWriteScore() {
ts.table.SetTimer(fishcommon.TIMER_WRITESCORE, fishcommon.TIME_WRITESCORE)
for _, v := range ts.Users {
if v != nil {
go ts.doWriteUserGold(v)
}
}
}