副本,关卡,战斗,奖励
This commit is contained in:
parent
f4db5a7d3b
commit
2ce71b7a2c
@ -21,5 +21,5 @@ func CheckChannel(channel uint32) bool {
|
||||
}
|
||||
|
||||
func CheckAttrType(attrType int) bool {
|
||||
return pb.AttrType(attrType) > pb.AttrType_AttrTypeNone && pb.AttrType(attrType) < pb.AttrType_Nums
|
||||
return pb.AttrType(attrType) > pb.AttrType_AttrTypeNone && pb.AttrType(attrType) < pb.AttrType_AttrNums
|
||||
}
|
||||
|
@ -8,15 +8,33 @@ import "mod_item.proto";
|
||||
// 战斗模块消息定义
|
||||
// 如果定义的消息内没有字段或者消息被注释掉了,说明该请求不需要参数,发送消息时仅发送包头即可,包体可为空, 返回的消息亦是如此。
|
||||
|
||||
//战斗单位
|
||||
// MsgId.ModBattleEnter = 4001;
|
||||
//进入战斗请求
|
||||
message BattleEnterReq {
|
||||
uint32 SceneId = 1; //场景ID
|
||||
}
|
||||
|
||||
//战斗Buff
|
||||
message BattleBuff {
|
||||
uint32 Skill = 1; //Buff技能
|
||||
uint32 Layers = 2; //Buff层数
|
||||
}
|
||||
|
||||
//战斗数值
|
||||
message BattleValue {
|
||||
int64 Value = 1; //数值集合,负数是伤害,正数回血
|
||||
uint64 Hp = 2; //受数值影响后的当前血量
|
||||
uint32 Status = 3; //0.正常, 1.暴击, 2.闪避,3.无敌,4.格挡,5.吸收, 6.反弹, 7.免疫
|
||||
}
|
||||
|
||||
//战斗目标
|
||||
message BattleTarget {
|
||||
uint32 Type = 1; //目标类型, 1.英雄(自己人),2.怪物(敌人)
|
||||
uint64 Id = 2; //目标ID
|
||||
uint32 Position = 2; //目标位置索引1-6
|
||||
uint64 HpMax = 3; //最大血量
|
||||
uint32 Rage = 4; //当前怒气
|
||||
repeated uint32 Status = 5; //目标状态(待定,如眩晕、击飞等)
|
||||
repeated uint64 Value = 6; //数值集合,可以是伤害,回血等
|
||||
repeated uint64 Hp = 7; //元素个数与上面的数值元素个数一致,元素值为受每个数值影响后的当前血量
|
||||
repeated BattleBuff BuffList = 5; //目标DeBuff状态ID(待定,如眩晕、击飞等)
|
||||
repeated BattleValue ValueList = 6; //数值集合,负数是伤害,正数回血
|
||||
}
|
||||
|
||||
//战斗动作
|
||||
@ -33,10 +51,10 @@ message BattleRound {
|
||||
repeated BattleAction ActionList = 2; //动作列表
|
||||
}
|
||||
|
||||
//战斗单位
|
||||
message BattleUnit {
|
||||
uint64 UnitId = 1;
|
||||
uint64 UnitId = 1; //自己是英雄唯一ID,敌人是怪物表ID,敌对玩家是英雄表ID
|
||||
uint32 SuitId = 2; //时装ID
|
||||
//
|
||||
}
|
||||
|
||||
// MsgId.ModBattleEnter = 4001;
|
||||
|
@ -12,13 +12,6 @@ message SceneEnterAck {
|
||||
uint32 SceneId = 1;//场景ID
|
||||
}
|
||||
|
||||
// MsgId.ModLevelEnter: 3001
|
||||
// 进入关卡返回
|
||||
message LevelEnterAck {
|
||||
uint32 CopyType = 1; //副本类型
|
||||
uint32 LevelId = 2; //关卡ID
|
||||
}
|
||||
|
||||
// CopyStatus 副本状态
|
||||
message CopyStatus {
|
||||
uint32 CopyType = 1; // 副本类型,场景表中的副本类型
|
||||
@ -46,6 +39,14 @@ message LevelEnterReq {
|
||||
uint32 LevelId = 2; //关卡ID
|
||||
}
|
||||
|
||||
// MsgId.ModLevelEnter = 3004;
|
||||
// 进入关卡返回
|
||||
//message LevelEnterAck {
|
||||
// uint32 CopyType = 1; //副本类型
|
||||
// uint32 LevelId = 2; //关卡ID
|
||||
// uint32 SceneId = 3; //场景ID
|
||||
//}
|
||||
|
||||
// MsgId.ModLevelSweep = 3005;
|
||||
// 进入扫荡请求
|
||||
message LevelSweepReq {
|
||||
|
@ -120,6 +120,13 @@ message LineupHeroPositionReq {
|
||||
repeated uint32 PositionList = 3; // 阵容英雄列表中前,6个英雄新布阵位置,布阵位置的顺序和阵容英雄列表是不一样的,布阵位置调整不影响英雄在阵容列表中的顺序。
|
||||
}
|
||||
|
||||
// MsgId.ModRoleLineupHeroPosition = 2008;
|
||||
// 阵容英雄布阵位置变更返回
|
||||
message LineupHeroPositionAck {
|
||||
uint64 LineupUid = 1;
|
||||
repeated uint32 PositionList = 3; // 阵容英雄列表中前,6个英雄新布阵位置,布阵位置的顺序和阵容英雄列表是不一样的,布阵位置调整不影响英雄在阵容列表中的顺序。
|
||||
}
|
||||
|
||||
// MsgId.ModRoleLineupHeroEquip = 2009;
|
||||
// 阵容英雄装备变更请求
|
||||
message LineupHeroEquipReq {
|
||||
|
141
servers/game/data/drop.go
Normal file
141
servers/game/data/drop.go
Normal file
@ -0,0 +1,141 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
json "github.com/json-iterator/go"
|
||||
"github.com/oylshe1314/framework/util"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Drop struct {
|
||||
Id int `json:"id"`
|
||||
DropId int `json:"drop_id"`
|
||||
BoxId int `json:"box_id"`
|
||||
BoxRate int `json:"box_rate"`
|
||||
MinNum int `json:"min_num"`
|
||||
MaxNum int `json:"max_num"`
|
||||
ItemId int `json:"item_id"`
|
||||
ItemNum int `json:"item_num"`
|
||||
ItemRate int `json:"item_rate"`
|
||||
}
|
||||
|
||||
type dropItem struct {
|
||||
drop *Drop
|
||||
}
|
||||
|
||||
type dropBox struct {
|
||||
boxId int
|
||||
rate int
|
||||
min int
|
||||
max int
|
||||
rates int
|
||||
items []*dropItem
|
||||
}
|
||||
|
||||
type dropStore struct {
|
||||
dropId int
|
||||
boxes map[int]*dropBox
|
||||
}
|
||||
|
||||
type DropTable struct {
|
||||
l []*Drop
|
||||
m map[int]*dropStore
|
||||
}
|
||||
|
||||
func (this *DropTable) load(buf []byte) error {
|
||||
var err = json.Unmarshal(buf, &this.l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.m = make(map[int]*dropStore)
|
||||
for _, drop := range this.l {
|
||||
var item = &dropItem{drop}
|
||||
|
||||
var store = this.m[item.drop.DropId]
|
||||
if store == nil {
|
||||
store = &dropStore{
|
||||
dropId: drop.DropId,
|
||||
boxes: map[int]*dropBox{
|
||||
item.drop.BoxId: {
|
||||
boxId: item.drop.BoxId,
|
||||
rate: item.drop.BoxRate,
|
||||
min: item.drop.MinNum,
|
||||
max: item.drop.MaxNum,
|
||||
rates: item.drop.ItemRate,
|
||||
items: []*dropItem{item},
|
||||
},
|
||||
},
|
||||
}
|
||||
this.m[drop.DropId] = store
|
||||
} else {
|
||||
var box = store.boxes[item.drop.BoxId]
|
||||
if box == nil {
|
||||
box = &dropBox{
|
||||
boxId: item.drop.BoxId,
|
||||
rate: item.drop.BoxRate,
|
||||
min: item.drop.MinNum,
|
||||
max: item.drop.MaxNum,
|
||||
rates: item.drop.ItemRate,
|
||||
items: []*dropItem{item},
|
||||
}
|
||||
store.boxes[item.drop.BoxId] = box
|
||||
} else {
|
||||
box.rates += item.drop.ItemRate
|
||||
box.items = append(box.items, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, store := range this.m {
|
||||
for _, box := range store.boxes {
|
||||
sort.Slice(box.items, func(i, j int) bool {
|
||||
return box.items[i].drop.Id < box.items[j].drop.Id
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Drop 掉落算法
|
||||
func (this *DropTable) Drop(dropId int, times int) [][2]int {
|
||||
if dropId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if times <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var store = this.m[dropId]
|
||||
if store == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var rd = util.NewRand()
|
||||
var result [][2]int
|
||||
for range times {
|
||||
for _, box := range store.boxes {
|
||||
if len(box.items) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if rd.Float64()*10000.0 > float64(box.rate) {
|
||||
continue
|
||||
}
|
||||
|
||||
var dropNum = box.min
|
||||
if box.max > dropNum {
|
||||
dropNum += rd.IntN(box.max - box.min)
|
||||
}
|
||||
var rates = float64(box.rates)
|
||||
var factor = rd.Float64() * rates
|
||||
for _, item := range box.items {
|
||||
rates -= float64(item.drop.ItemRate)
|
||||
if factor >= rates {
|
||||
result = append(result, [2]int{item.drop.ItemId, item.drop.ItemNum * dropNum})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
@ -4,7 +4,10 @@ import json "github.com/json-iterator/go"
|
||||
|
||||
type Monster struct {
|
||||
Id int `json:"id"`
|
||||
Gender int `json:"gender"`
|
||||
Country int `json:"country"`
|
||||
Level int `json:"level"`
|
||||
Speed int `json:"speed"`
|
||||
AttackSkills []int `json:"attack_skills"`
|
||||
PassiveSkills []int `json:"passive_skills"`
|
||||
AttrValue1 int `json:"attr_value1"`
|
||||
|
@ -21,8 +21,8 @@ type Scene struct {
|
||||
Monster6 int `json:"monster6"`
|
||||
EnterTimes int `json:"enter_times"`
|
||||
RestTimes int `json:"rest_times"`
|
||||
PassExpRate int `json:"pass_exp_rate"`
|
||||
PassCoinRate int `json:"pass_coin_rate"`
|
||||
ExpMultiple int `json:"exp_multiple"`
|
||||
CoinMultiple int `json:"coin_multiple"`
|
||||
FirstDrop int `json:"first_drop"`
|
||||
PassDrop int `json:"pass_drop"`
|
||||
Star1Type int `json:"star1_type"`
|
||||
|
@ -5,6 +5,7 @@ import json "github.com/json-iterator/go"
|
||||
type Skill struct {
|
||||
Id int `json:"id"`
|
||||
SkillType int `json:"skill_type"`
|
||||
RageConsume int `json:"rage_consume"`
|
||||
SkillBuff []int `json:"skill_buff"`
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,21 @@ import json "github.com/json-iterator/go"
|
||||
|
||||
type SkillBuff struct {
|
||||
Id int `json:"id"`
|
||||
SkillBuffType int `json:"SkillBuff_type"`
|
||||
SkillBuffBuff []int `json:"SkillBuff_buff"`
|
||||
TargetType int `json:"target_type"`
|
||||
TargetArgs []int `json:"target_args"`
|
||||
RangeType int `json:"range_type"`
|
||||
RangeNum int `json:"range_num"`
|
||||
PriorityType []int `json:"priority_type"`
|
||||
PriorityArgs []int `json:"priority_args"`
|
||||
BuffType int `json:"buff_type"`
|
||||
BuffArgs []int `json:"buff_args"`
|
||||
DurationType int `json:"durationType"`
|
||||
Duration int `json:"duration"`
|
||||
EffectId string `json:"effectId"`
|
||||
CanMerge bool `json:"can_merge"`
|
||||
CanCover bool `json:"can_cover"`
|
||||
CanStack bool `json:"can_stack"`
|
||||
CanClean bool `json:"can_clean"`
|
||||
}
|
||||
|
||||
type SkillBuffTable struct {
|
||||
|
@ -19,6 +19,7 @@ type Tables struct {
|
||||
|
||||
Copy CopyTable
|
||||
CopyMain CopyMainTable
|
||||
Drop DropTable
|
||||
Equip EquipTable
|
||||
EquipLevel EquipLevelTable
|
||||
EquipRefine EquipRefineTable
|
||||
|
@ -9,14 +9,14 @@ import (
|
||||
)
|
||||
|
||||
func (this *PlayerHandler) checkLevelConsume(sceneTable *data.Scene, player *logic.Player, times uint32) proto.TipError {
|
||||
var consume = map[uint32]uint32{}
|
||||
var consumeItems = map[uint32]uint32{}
|
||||
for i := range sceneTable.ConsumeItems {
|
||||
consume[uint32(sceneTable.ConsumeItems[i])] += uint32(sceneTable.ConsumeNums[i]) * times
|
||||
consumeItems[uint32(sceneTable.ConsumeItems[i])] += uint32(sceneTable.ConsumeNums[i]) * times
|
||||
}
|
||||
for i := range sceneTable.SuConsumeItems {
|
||||
consume[uint32(sceneTable.SuConsumeItems[i])] += uint32(sceneTable.SuConsumeNums[i]) * times
|
||||
consumeItems[uint32(sceneTable.SuConsumeItems[i])] += uint32(sceneTable.SuConsumeNums[i]) * times
|
||||
}
|
||||
for itemId, itemNum := range consume {
|
||||
for itemId, itemNum := range consumeItems {
|
||||
if ok, tip := player.CheckItem(itemId, itemNum); !ok {
|
||||
return tip
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"ecs/proto/pb"
|
||||
"ecs/servers/game/data"
|
||||
"github.com/oylshe1314/framework/util"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func (this *Player) EnterBattle(sceneTable *data.Scene) {
|
||||
@ -32,25 +33,66 @@ func (this *Player) copyBattle(sceneTable *data.Scene) {
|
||||
this.PassedCopy(sceneTable, ack.Score)
|
||||
}
|
||||
|
||||
_ = this.Send(uint16(pb.ModId_ModuleBattle), uint16(pb.MsgId_ModBattleEnter), ack)
|
||||
_ = this.Send(pb.ModId_ModuleBattle, pb.MsgId_ModBattleEnter, ack)
|
||||
}
|
||||
|
||||
type _BattleBuff struct {
|
||||
id uint32
|
||||
targetType uint32
|
||||
targetArgs []uint32
|
||||
rangeType uint32
|
||||
rangeNum uint32
|
||||
priorityType []uint32
|
||||
priorityArgs []uint32
|
||||
buffType uint32
|
||||
buffArgs []int64
|
||||
durationType uint32
|
||||
duration uint32
|
||||
canMerge bool
|
||||
canCover bool
|
||||
canStack bool
|
||||
canClean bool
|
||||
}
|
||||
|
||||
type _BattleSkill struct {
|
||||
id uint32
|
||||
tipe uint32
|
||||
rage uint32
|
||||
buffs []*_BattleBuff
|
||||
}
|
||||
|
||||
type _BattleUnit struct {
|
||||
id uint64
|
||||
position uint32
|
||||
gender uint32
|
||||
country uint32
|
||||
hp uint64
|
||||
rage uint32
|
||||
speed uint32
|
||||
baseSpeed uint32
|
||||
posSpeed uint32
|
||||
amuletSpeed uint32
|
||||
harnessSpeed uint32
|
||||
|
||||
attrs Attrs
|
||||
|
||||
role *_BattleRole
|
||||
|
||||
buffs []*_BattleBuff
|
||||
deBuffs []*_BattleBuff
|
||||
|
||||
attackSkills []*_BattleSkill
|
||||
passiveSkills []*_BattleSkill
|
||||
}
|
||||
|
||||
type _BattleRole struct {
|
||||
attacker bool
|
||||
addSpeed uint32
|
||||
capacity uint64
|
||||
unitList []*_BattleUnit
|
||||
//sellList []*_BattleUnit
|
||||
}
|
||||
|
||||
func (this *Player) virtualBattle(sceneTable *data.Scene) (ack *pb.BattleEnterAck, tip proto.TipError) {
|
||||
var lineup = util.MapFindValue(this.Lineup, func(lineup *PlayerLineup) bool {
|
||||
return lineup.Active
|
||||
@ -59,110 +101,177 @@ func (this *Player) virtualBattle(sceneTable *data.Scene) (ack *pb.BattleEnterAc
|
||||
return nil, proto.TipLineupNotFound
|
||||
}
|
||||
|
||||
var heroes = make([]*_BattleUnit, 6)
|
||||
for i := range 6 {
|
||||
if lineup.Heroes[i] != nil {
|
||||
if hero := this.Hero[lineup.Heroes[i].HeroUid]; hero != nil {
|
||||
heroes[lineup.Heroes[i].Position-1] = &_BattleUnit{
|
||||
id: lineup.Heroes[i].HeroUid,
|
||||
attrs: hero.Attrs(),
|
||||
}
|
||||
}
|
||||
}
|
||||
var me = &_BattleRole{attacker: true}
|
||||
me.capacity, me.unitList, tip = this.loadHeroes(me, lineup)
|
||||
if tip != nil {
|
||||
_ = this.TipNotice(tip)
|
||||
return
|
||||
}
|
||||
|
||||
var enemies []*_BattleUnit
|
||||
//sort.Slice(me.unitList, func(i, j int) bool {
|
||||
// return me.unitList[i].pos < me.unitList[j].pos
|
||||
//})
|
||||
|
||||
var he = &_BattleRole{attacker: false}
|
||||
if pb.CopyType(sceneTable.CopyType) == pb.CopyType_CopyArena {
|
||||
|
||||
} else {
|
||||
enemies, tip = this.loadMonsters([]int{sceneTable.Monster1, sceneTable.Monster2, sceneTable.Monster3, sceneTable.Monster4, sceneTable.Monster5, sceneTable.Monster6})
|
||||
he.capacity, he.unitList, tip = this.loadMonsters(he, []int{sceneTable.Monster1, sceneTable.Monster2, sceneTable.Monster3, sceneTable.Monster4, sceneTable.Monster5, sceneTable.Monster6})
|
||||
if tip != nil {
|
||||
_ = this.TipNotice(tip)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//sort.Slice(he.unitList, func(i, j int) bool {
|
||||
// return he.unitList[i].pos < he.unitList[j].pos
|
||||
//})
|
||||
|
||||
ack = &pb.BattleEnterAck{
|
||||
SceneId: uint32(sceneTable.Id),
|
||||
RewardList: nil,
|
||||
}
|
||||
|
||||
ack.Heroes = make([]*pb.BattleUnit, 6)
|
||||
ack.Enemies = make([]*pb.BattleUnit, 6)
|
||||
for i := range 6 {
|
||||
if heroes[i] != nil {
|
||||
ack.Heroes[i] = &pb.BattleUnit{UnitId: heroes[i].id}
|
||||
for i := range me.unitList {
|
||||
if me.unitList[i] != nil {
|
||||
ack.Heroes[i] = &pb.BattleUnit{
|
||||
UnitId: me.unitList[i].id,
|
||||
}
|
||||
if enemies[i] != nil {
|
||||
ack.Enemies[i] = &pb.BattleUnit{UnitId: enemies[i].id}
|
||||
}
|
||||
}
|
||||
|
||||
ack.Succeed, ack.Score, ack.RoundList = this.calcBattle(heroes, enemies)
|
||||
ack.Enemies = make([]*pb.BattleUnit, 6)
|
||||
for i := range he.unitList {
|
||||
if he.unitList[i] != nil {
|
||||
ack.Enemies[i] = &pb.BattleUnit{
|
||||
UnitId: he.unitList[i].id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(me.unitList) == 0 {
|
||||
ack.Succeed = false
|
||||
ack.Score = 0
|
||||
} else if len(he.unitList) == 0 {
|
||||
ack.Succeed = true
|
||||
ack.Score = 3
|
||||
} else {
|
||||
var calculator = &_BattleCalculator{
|
||||
rd: util.NewRand(),
|
||||
me: me,
|
||||
he: he,
|
||||
}
|
||||
ack.Succeed, ack.RoundList = calculator.calcBattle(sceneTable.BattleRound, me, he)
|
||||
ack.BattleRounds = uint32(len(ack.RoundList))
|
||||
|
||||
if ack.Succeed {
|
||||
//TODO calc stars
|
||||
ack.Score = 2
|
||||
if me.unitList[0].hp > 0 {
|
||||
ack.Score = 3
|
||||
}
|
||||
|
||||
this.addExp(this.RoleLevel*uint32(sceneTable.ExpMultiple), LogTypeItemObtainByCopy)
|
||||
this.addMoney(pb.MoneyType_Coin, this.RoleLevel*uint32(sceneTable.CoinMultiple), LogTypeItemObtainByCopy)
|
||||
|
||||
//TODO calc reward
|
||||
var rewardItems = map[uint32]uint32{}
|
||||
if this.GetCopyPassed(pb.CopyType(sceneTable.CopyType), uint32(sceneTable.CopyId)) == 0 {
|
||||
var dropResult = this.manager.tables.Drop.Drop(sceneTable.FirstDrop, 1)
|
||||
for _, items := range dropResult {
|
||||
rewardItems[uint32(items[0])] += uint32(items[1])
|
||||
ack.RewardList = append(ack.RewardList, &pb.Item{
|
||||
ItemId: uint32(items[0]),
|
||||
ItemNum: uint32(items[1]),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var dropResult = this.manager.tables.Drop.Drop(sceneTable.PassDrop, 1)
|
||||
for _, items := range dropResult {
|
||||
rewardItems[uint32(items[0])] += uint32(items[1])
|
||||
ack.RewardList = append(ack.RewardList, &pb.Item{
|
||||
ItemId: uint32(items[0]),
|
||||
ItemNum: uint32(items[1]),
|
||||
})
|
||||
}
|
||||
|
||||
this.AddItems(rewardItems, LogTypeItemObtainByCopy)
|
||||
}
|
||||
}
|
||||
|
||||
return ack, nil
|
||||
}
|
||||
|
||||
func (this *Player) calcBattle(heroes, enemies []*_BattleUnit) (bool, int32, []*pb.BattleRound) {
|
||||
return true, 3, []*pb.BattleRound{
|
||||
{
|
||||
BattleRound: 1,
|
||||
ActionList: []*pb.BattleAction{
|
||||
{
|
||||
Caster: &pb.BattleTarget{
|
||||
Type: 1,
|
||||
Id: heroes[0].id,
|
||||
HpMax: heroes[0].attrs[pb.AttrType_Hp],
|
||||
Rage: 0,
|
||||
Status: nil,
|
||||
Value: nil,
|
||||
Hp: nil,
|
||||
},
|
||||
Type: 0,
|
||||
SkillId: 100021,
|
||||
TargetList: []*pb.BattleTarget{
|
||||
{
|
||||
Type: 2,
|
||||
Id: enemies[0].id,
|
||||
HpMax: enemies[0].attrs[pb.AttrType_Hp],
|
||||
Rage: 0,
|
||||
Status: nil,
|
||||
Value: []uint64{heroes[0].attrs[pb.AttrType_Attack]},
|
||||
Hp: []uint64{enemies[0].attrs[pb.AttrType_Hp] - heroes[0].attrs[pb.AttrType_Attack]},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Caster: &pb.BattleTarget{
|
||||
Type: 2,
|
||||
Id: enemies[1].id,
|
||||
HpMax: enemies[1].attrs[pb.AttrType_Hp],
|
||||
Rage: 0,
|
||||
Status: nil,
|
||||
Value: nil,
|
||||
Hp: nil,
|
||||
},
|
||||
Type: 0,
|
||||
SkillId: 100191,
|
||||
TargetList: []*pb.BattleTarget{
|
||||
{
|
||||
Type: 1,
|
||||
Id: heroes[0].id,
|
||||
HpMax: heroes[0].attrs[pb.AttrType_Hp],
|
||||
Rage: 0,
|
||||
Status: nil,
|
||||
Value: []uint64{enemies[1].attrs[pb.AttrType_Attack]},
|
||||
Hp: []uint64{heroes[0].attrs[pb.AttrType_Hp] - enemies[1].attrs[pb.AttrType_Attack]},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
func (this *Player) calcAttrsCapacity(attrs Attrs) uint64 {
|
||||
return uint64((float64(attrs[pb.AttrType_Attack]) * 2) +
|
||||
(float64(attrs[pb.AttrType_Hp]) * 0.2) +
|
||||
(float64(attrs[pb.AttrType_PhysicalDefense]) * 6) +
|
||||
(float64(attrs[pb.AttrType_MagicDefense]) * 6) +
|
||||
(float64(attrs[pb.AttrType_DamageRatio]) * 12) +
|
||||
(float64(attrs[pb.AttrType_DamageRelief]) * 12) +
|
||||
(float64(attrs[pb.AttrType_CriticalRate]) * 12) +
|
||||
(float64(attrs[pb.AttrType_CriticalResistance]) * 12) +
|
||||
(float64(attrs[pb.AttrType_CriticalDamage]) * 12) +
|
||||
(float64(attrs[pb.AttrType_CriticalDamageRelief]) * 12) +
|
||||
(float64(attrs[pb.AttrType_HitRate]) * 12) +
|
||||
(float64(attrs[pb.AttrType_DodgeRate]) * 12) +
|
||||
(float64(attrs[pb.AttrType_TreatRatio]) * 12) +
|
||||
(float64(attrs[pb.AttrType_ByTreatedRate]) * 12) +
|
||||
(float64(attrs[pb.AttrType_FinalDamageRatio]) * 12))
|
||||
}
|
||||
|
||||
func (this *Player) loadMonsters(monsterIds []int) (unitList []*_BattleUnit, tip proto.TipError) {
|
||||
unitList = make([]*_BattleUnit, len(monsterIds))
|
||||
func (this *Player) loadHeroes(role *_BattleRole, lineup *PlayerLineup) (capacity uint64, unitList []*_BattleUnit, tip proto.TipError) {
|
||||
unitList = make([]*_BattleUnit, 6)
|
||||
|
||||
var heroIndex = 0
|
||||
for i := range 6 {
|
||||
if lineup.Heroes[i] != nil {
|
||||
if hero := this.Hero[lineup.Heroes[i].HeroUid]; hero != nil {
|
||||
capacity += lineup.Heroes[i].Capacity
|
||||
var unit = &_BattleUnit{
|
||||
id: lineup.Heroes[i].HeroUid,
|
||||
position: lineup.Heroes[i].Position,
|
||||
attrs: hero.Attrs(),
|
||||
role: role,
|
||||
}
|
||||
|
||||
var heroTable = this.manager.tables.Hero.Find1(int(hero.Id))
|
||||
if heroTable == nil {
|
||||
return 0, nil, proto.TipDataTablesError
|
||||
}
|
||||
|
||||
unit.gender = uint32(heroTable.Sex)
|
||||
unit.country = uint32(heroTable.Country)
|
||||
|
||||
unit.attackSkills, tip = this.loadSkills(heroTable.Skill)
|
||||
if tip != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sort.Slice(unit.attackSkills, func(i, j int) bool {
|
||||
return unit.attackSkills[i].tipe > unit.attackSkills[j].tipe
|
||||
})
|
||||
|
||||
unit.hp = unit.attrs[pb.AttrType_Hp]
|
||||
unit.rage = 4
|
||||
unit.baseSpeed = 100
|
||||
unit.posSpeed = uint32(20 - 4*heroIndex)
|
||||
unit.amuletSpeed = 0 //TODO calc speed
|
||||
unit.harnessSpeed = 0 //TODO calc speed
|
||||
|
||||
//TODO load hero passive skills, from equip, break, soul
|
||||
|
||||
unitList[lineup.Heroes[i].Position-1] = unit
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Player) loadMonsters(role *_BattleRole, monsterIds []int) (capacity uint64, unitList []*_BattleUnit, tip proto.TipError) {
|
||||
unitList = make([]*_BattleUnit, 6)
|
||||
var monsterIndex uint64 = 0
|
||||
for i, monsterId := range monsterIds {
|
||||
if monsterId == 0 {
|
||||
continue
|
||||
@ -170,16 +279,26 @@ func (this *Player) loadMonsters(monsterIds []int) (unitList []*_BattleUnit, tip
|
||||
|
||||
var monsterTable = this.manager.tables.Monster.Find(int(monsterId))
|
||||
if monsterTable == nil {
|
||||
return nil, proto.TipDataTablesError
|
||||
return 0, nil, proto.TipDataTablesError
|
||||
}
|
||||
|
||||
var unit = &_BattleUnit{id: uint64(monsterTable.Id)}
|
||||
var unit = &_BattleUnit{
|
||||
id: uint64(monsterTable.Id),
|
||||
position: uint32(i + 1),
|
||||
gender: uint32(monsterTable.Gender),
|
||||
country: uint32(monsterTable.Country),
|
||||
role: role,
|
||||
}
|
||||
|
||||
unit.attackSkills, tip = this.loadSkills(monsterTable.AttackSkills)
|
||||
if tip != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sort.Slice(unit.attackSkills, func(i, j int) bool {
|
||||
return unit.attackSkills[i].tipe > unit.attackSkills[j].tipe
|
||||
})
|
||||
|
||||
unit.passiveSkills, tip = this.loadSkills(monsterTable.PassiveSkills)
|
||||
if tip != nil {
|
||||
return
|
||||
@ -187,24 +306,34 @@ func (this *Player) loadMonsters(monsterIds []int) (unitList []*_BattleUnit, tip
|
||||
|
||||
unit.attrs[pb.AttrType_Attack] = uint64(monsterTable.AttrValue1)
|
||||
unit.attrs[pb.AttrType_Hp] = uint64(monsterTable.AttrValue2)
|
||||
unit.attrs[pb.AttrType_AttrPhysicalDefense] = uint64(monsterTable.AttrValue3)
|
||||
unit.attrs[pb.AttrType_AttrMagicDefense] = uint64(monsterTable.AttrValue4)
|
||||
unit.attrs[pb.AttrType_AttrAttackRatio] = uint64(monsterTable.AttrValue5)
|
||||
unit.attrs[pb.AttrType_AttrHpRatio] = uint64(monsterTable.AttrValue6)
|
||||
unit.attrs[pb.AttrType_AttrPhysicalDefenseRatio] = uint64(monsterTable.AttrValue7)
|
||||
unit.attrs[pb.AttrType_AttrMagicDefenseRatio] = uint64(monsterTable.AttrValue8)
|
||||
unit.attrs[pb.AttrType_AttrDamageRatio] = uint64(monsterTable.AttrValue9)
|
||||
unit.attrs[pb.AttrType_AttrDamageRelief] = uint64(monsterTable.AttrValue10)
|
||||
unit.attrs[pb.AttrType_AttrCriticalRatio] = uint64(monsterTable.AttrValue11)
|
||||
unit.attrs[pb.AttrType_AttrCriticalResistance] = uint64(monsterTable.AttrValue12)
|
||||
unit.attrs[pb.AttrType_AttrCriticalDamage] = uint64(monsterTable.AttrValue13)
|
||||
unit.attrs[pb.AttrType_AttrCriticalDamageRelief] = uint64(monsterTable.AttrValue14)
|
||||
unit.attrs[pb.AttrType_AttrHitRate] = uint64(monsterTable.AttrValue15)
|
||||
unit.attrs[pb.AttrType_AttrDodgeRate] = uint64(monsterTable.AttrValue16)
|
||||
unit.attrs[pb.AttrType_AttrTreatRatio] = uint64(monsterTable.AttrValue17)
|
||||
unit.attrs[pb.AttrType_AttrByTreatedRatio] = uint64(monsterTable.AttrValue18)
|
||||
unit.attrs[pb.AttrType_AttrFinalDamageRatio] = uint64(monsterTable.AttrValue19)
|
||||
unit.attrs[pb.AttrType_AttrFinalDamageRelief] = uint64(monsterTable.AttrValue20)
|
||||
unit.attrs[pb.AttrType_PhysicalDefense] = uint64(monsterTable.AttrValue3)
|
||||
unit.attrs[pb.AttrType_MagicDefense] = uint64(monsterTable.AttrValue4)
|
||||
unit.attrs[pb.AttrType_AttackRatio] = uint64(monsterTable.AttrValue5)
|
||||
unit.attrs[pb.AttrType_HpRatio] = uint64(monsterTable.AttrValue6)
|
||||
unit.attrs[pb.AttrType_PhysicalDefenseRatio] = uint64(monsterTable.AttrValue7)
|
||||
unit.attrs[pb.AttrType_MagicDefenseRatio] = uint64(monsterTable.AttrValue8)
|
||||
unit.attrs[pb.AttrType_DamageRatio] = uint64(monsterTable.AttrValue9)
|
||||
unit.attrs[pb.AttrType_DamageRelief] = uint64(monsterTable.AttrValue10)
|
||||
unit.attrs[pb.AttrType_CriticalRate] = uint64(monsterTable.AttrValue11)
|
||||
unit.attrs[pb.AttrType_CriticalResistance] = uint64(monsterTable.AttrValue12)
|
||||
unit.attrs[pb.AttrType_CriticalDamage] = uint64(monsterTable.AttrValue13)
|
||||
unit.attrs[pb.AttrType_CriticalDamageRelief] = uint64(monsterTable.AttrValue14)
|
||||
unit.attrs[pb.AttrType_HitRate] = uint64(monsterTable.AttrValue15)
|
||||
unit.attrs[pb.AttrType_DodgeRate] = uint64(monsterTable.AttrValue16)
|
||||
unit.attrs[pb.AttrType_TreatRatio] = uint64(monsterTable.AttrValue17)
|
||||
unit.attrs[pb.AttrType_ByTreatedRate] = uint64(monsterTable.AttrValue18)
|
||||
unit.attrs[pb.AttrType_FinalDamageRatio] = uint64(monsterTable.AttrValue19)
|
||||
unit.attrs[pb.AttrType_FinalDamageRelief] = uint64(monsterTable.AttrValue20)
|
||||
monsterIndex += 1
|
||||
|
||||
unit.hp = unit.attrs[pb.AttrType_Hp]
|
||||
unit.rage = 4
|
||||
unit.baseSpeed = 0
|
||||
unit.posSpeed = uint32(20 - 4*monsterIndex)
|
||||
unit.amuletSpeed = 0 //TODO calc speed
|
||||
unit.harnessSpeed = 0 //TODO calc speed
|
||||
|
||||
capacity += this.calcAttrsCapacity(unit.attrs)
|
||||
|
||||
unitList[i] = unit
|
||||
}
|
||||
@ -212,7 +341,7 @@ func (this *Player) loadMonsters(monsterIds []int) (unitList []*_BattleUnit, tip
|
||||
}
|
||||
|
||||
func (this *Player) loadSkills(skillIds []int) (skillList []*_BattleSkill, tip proto.TipError) {
|
||||
skillList = make([]*_BattleSkill, len(skillIds))
|
||||
skillList = make([]*_BattleSkill, 0, len(skillIds))
|
||||
for _, skillId := range skillIds {
|
||||
var skillTable = this.manager.tables.Skill.Find(skillId)
|
||||
if skillTable == nil {
|
||||
@ -221,29 +350,47 @@ func (this *Player) loadSkills(skillIds []int) (skillList []*_BattleSkill, tip p
|
||||
|
||||
var skill = &_BattleSkill{
|
||||
id: uint32(skillId),
|
||||
tipe: uint32(skillTable.SkillType),
|
||||
rage: uint32(skillTable.RageConsume),
|
||||
}
|
||||
|
||||
skill.buffs, tip = this.loadSkillsBuff(skillTable.SkillBuff)
|
||||
if tip != nil {
|
||||
return
|
||||
}
|
||||
|
||||
skillList = append(skillList, skill)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Player) loadSkillsBuff(buffIds []int) (buffList []*_BattleBuff, tip proto.TipError) {
|
||||
buffList = make([]*_BattleBuff, len(buffIds))
|
||||
for i, skillId := range buffIds {
|
||||
var buff = this.manager.tables.SkillBuff.Find(skillId)
|
||||
if buff == nil {
|
||||
buffList = make([]*_BattleBuff, 0, len(buffIds))
|
||||
for _, buffId := range buffIds {
|
||||
var buffTable = this.manager.tables.SkillBuff.Find(buffId)
|
||||
if buffTable == nil {
|
||||
return nil, proto.TipDataTablesError
|
||||
}
|
||||
|
||||
var battleBuff = &_BattleBuff{
|
||||
id: uint32(skillId),
|
||||
var buff = &_BattleBuff{
|
||||
id: uint32(buffId),
|
||||
targetType: uint32(buffTable.TargetType),
|
||||
targetArgs: util.NumbersConvert2(buffTable.TargetArgs, uint32(0)),
|
||||
rangeType: uint32(buffTable.RangeType),
|
||||
rangeNum: uint32(buffTable.RangeNum),
|
||||
priorityType: util.NumbersConvert2(buffTable.PriorityType, uint32(0)),
|
||||
priorityArgs: util.NumbersConvert2(buffTable.PriorityArgs, uint32(0)),
|
||||
buffType: uint32(buffTable.BuffType),
|
||||
buffArgs: util.NumbersConvert2(buffTable.BuffArgs, int64(0)),
|
||||
durationType: uint32(buffTable.DurationType),
|
||||
duration: uint32(buffTable.Duration),
|
||||
canMerge: buffTable.CanMerge,
|
||||
canCover: buffTable.CanCover,
|
||||
canStack: buffTable.CanStack,
|
||||
canClean: buffTable.CanClean,
|
||||
}
|
||||
|
||||
buffList[i] = battleBuff
|
||||
buffList = append(buffList, buff)
|
||||
}
|
||||
return buffList, nil
|
||||
}
|
||||
|
490
servers/game/logic/player_battle_calculator.go
Normal file
490
servers/game/logic/player_battle_calculator.go
Normal file
@ -0,0 +1,490 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"ecs/proto/pb"
|
||||
"github.com/oylshe1314/framework/util"
|
||||
"math/rand/v2"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type _BattleCalculator struct {
|
||||
rd *rand.Rand
|
||||
|
||||
me *_BattleRole
|
||||
he *_BattleRole
|
||||
}
|
||||
|
||||
func (tnis *_BattleCalculator) calcNextCaster(lastIndex int, unitList []*_BattleUnit) (dead bool, newIndex int, caster *_BattleUnit) {
|
||||
dead = true
|
||||
var posIndex = 0
|
||||
for i, unit := range unitList {
|
||||
if i == lastIndex || unit == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if unit.hp > 0 {
|
||||
dead = false
|
||||
posIndex += 1
|
||||
unit.posSpeed = uint32(20 - (4 * posIndex))
|
||||
unit.speed = unit.baseSpeed + unit.posSpeed + unit.amuletSpeed + unit.harnessSpeed
|
||||
|
||||
if lastIndex < 0 || unit.speed <= unitList[lastIndex].speed {
|
||||
if caster == nil || unit.speed > caster.speed {
|
||||
caster = unit
|
||||
newIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcBattle(rounds int, me, he *_BattleRole) (succeed bool, roundList []*pb.BattleRound) {
|
||||
var roles = [2]*_BattleRole{me, he}
|
||||
|
||||
var ri = 0
|
||||
if he.capacity > me.capacity {
|
||||
ri = 1
|
||||
}
|
||||
|
||||
var dead bool
|
||||
var index = [2]int{-1, -1}
|
||||
var caster, aCaster, bCaster *_BattleUnit
|
||||
for i, unit := range roles[ri].unitList {
|
||||
if unit != nil {
|
||||
unit.speed = unit.baseSpeed + unit.posSpeed + unit.amuletSpeed + unit.harnessSpeed
|
||||
if aCaster == nil || unit.speed > aCaster.speed {
|
||||
aCaster = unit
|
||||
index[ri] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
caster = aCaster
|
||||
for round := range rounds {
|
||||
var battleRound = &pb.BattleRound{BattleRound: uint32(round) + 1}
|
||||
|
||||
dead = false
|
||||
for {
|
||||
var ai, bi = ri, (ri + 1) % 2
|
||||
var battleAction = &pb.BattleAction{}
|
||||
|
||||
battleRound.ActionList = append(battleRound.ActionList, battleAction)
|
||||
|
||||
battleAction.Caster, battleAction.SkillId, battleAction.TargetList = this.calcSkill(caster, roles[ai], roles[bi])
|
||||
|
||||
dead, index[bi], bCaster = this.calcNextCaster(index[bi], roles[bi].unitList)
|
||||
if dead {
|
||||
succeed = bi != 0
|
||||
break
|
||||
}
|
||||
|
||||
dead, index[ai], aCaster = this.calcNextCaster(index[ai], roles[ai].unitList)
|
||||
if dead {
|
||||
succeed = ai != 0
|
||||
break
|
||||
}
|
||||
|
||||
if bCaster == nil {
|
||||
if aCaster == nil {
|
||||
index[ai] = -1
|
||||
index[bi] = -1
|
||||
break
|
||||
} else {
|
||||
caster = aCaster
|
||||
}
|
||||
} else {
|
||||
if aCaster == nil {
|
||||
caster = bCaster
|
||||
ri = bi
|
||||
} else {
|
||||
if aCaster.speed > bCaster.speed {
|
||||
caster = aCaster
|
||||
} else {
|
||||
caster = bCaster
|
||||
ri = bi
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
roundList = append(roundList, battleRound)
|
||||
if dead {
|
||||
break
|
||||
}
|
||||
}
|
||||
return succeed, roundList
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcSkill(unit *_BattleUnit, a, b *_BattleRole) (caster *pb.BattleTarget, skillId uint32, targetList []*pb.BattleTarget) {
|
||||
for _, skill := range unit.attackSkills {
|
||||
if unit.rage < skill.rage {
|
||||
continue
|
||||
}
|
||||
|
||||
switch skill.tipe {
|
||||
case skillTypeAttack:
|
||||
skillId = skill.id
|
||||
caster, targetList = this.calcBuff(unit, skill, a, b)
|
||||
unit.rage += 2
|
||||
case skillTypeActive:
|
||||
skillId = skill.id
|
||||
unit.rage -= skill.rage
|
||||
caster, targetList = this.calcBuff(unit, skill, a, b)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcBuff(unit *_BattleUnit, skill *_BattleSkill, a, b *_BattleRole) (caster *pb.BattleTarget, targetList []*pb.BattleTarget) {
|
||||
caster = &pb.BattleTarget{Type: uint32(util.If(unit.role.attacker, 1, 2)), Position: unit.position}
|
||||
|
||||
caster.HpMax = unit.attrs[pb.AttrType_Hp]
|
||||
caster.Rage = unit.rage
|
||||
|
||||
var targetMap = map[uint32]*pb.BattleTarget{}
|
||||
for _, buff := range skill.buffs {
|
||||
if buff.buffType == buffTypeNone || len(buff.buffArgs) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
//switch buff.targetType {
|
||||
//case targetTypeSelf:
|
||||
// targets = []*_BattleUnit{unit}
|
||||
//case targetTypeTeammate:
|
||||
//case targetTypeEnemy:
|
||||
//case targetTypeTeammateGender:
|
||||
// if len(buff.targetArgs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, teammate := range a.unitList {
|
||||
// if teammate != nil {
|
||||
// if slices.Contains(buff.targetArgs, teammate.gender) {
|
||||
// targets = append(targets, teammate)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//case targetTypeEnemyGender:
|
||||
// if len(buff.targetArgs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, enemy := range b.unitList {
|
||||
// if enemy != nil {
|
||||
// if slices.Contains(buff.targetArgs, enemy.gender) {
|
||||
// targets = append(targets, enemy)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//case targetTypeTeammateCountry:
|
||||
// if len(buff.targetArgs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, teammate := range a.unitList {
|
||||
// if teammate != nil {
|
||||
// if slices.Contains(buff.targetArgs, teammate.country) {
|
||||
// targets = append(targets, teammate)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//case targetTypeEnemyCountry:
|
||||
// if len(buff.targetArgs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, enemy := range b.unitList {
|
||||
// if enemy != nil {
|
||||
// if slices.Contains(buff.targetArgs, enemy.country) {
|
||||
// targets = append(targets, enemy)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//case targetTypeTeammateStatus:
|
||||
// if len(buff.targetArgs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, teammate := range a.unitList {
|
||||
// if teammate != nil {
|
||||
// if slices.ContainsFunc(buff.targetArgs, func(targetArg uint32) bool {
|
||||
// return slices.ContainsFunc(teammate.deBuffs, func(buff *_BattleBuff) bool {
|
||||
// return buff.id == targetArg
|
||||
// })
|
||||
// }) {
|
||||
// targets = append(targets, teammate)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//case targetTypeEnemyStatus:
|
||||
// if len(buff.targetArgs) == 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, enemy := range b.unitList {
|
||||
// if enemy != nil {
|
||||
// if slices.ContainsFunc(buff.targetArgs, func(targetArg uint32) bool {
|
||||
// return slices.ContainsFunc(enemy.deBuffs, func(buff *_BattleBuff) bool {
|
||||
// return buff.id == targetArg
|
||||
// })
|
||||
// }) {
|
||||
// targets = append(targets, enemy)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//case targetTypeAttackRate:
|
||||
//}
|
||||
|
||||
var targets []*_BattleUnit
|
||||
switch buff.buffType {
|
||||
case buffTypePhysicalDamage:
|
||||
if buff.targetType != targetTypeEnemy {
|
||||
continue
|
||||
}
|
||||
targets = this.calcAttackTarget(b.unitList, buff.priorityType, buff.priorityArgs, buff.rangeType, buff.rangeNum)
|
||||
for _, target := range targets {
|
||||
var damage = this.calcDamage(buff, unit, target)
|
||||
this.calcHp(target, damage, targetMap)
|
||||
}
|
||||
case buffTypeMagicDamage:
|
||||
if buff.targetType != targetTypeEnemy {
|
||||
continue
|
||||
}
|
||||
targets = this.calcAttackTarget(b.unitList, buff.priorityType, buff.priorityArgs, buff.rangeType, buff.rangeNum)
|
||||
for _, target := range targets {
|
||||
var damage = this.calcDamage(buff, unit, target)
|
||||
this.calcHp(target, damage, targetMap)
|
||||
}
|
||||
case buffTypeStatusAbnormal:
|
||||
case buffTypeChangeAttr:
|
||||
case buffTypeRevive:
|
||||
case buffTypeDamageReturn:
|
||||
case buffTypeBisect:
|
||||
case buffTypeShield:
|
||||
case buffTypeChangeHp:
|
||||
case buffTypeSteal:
|
||||
case buffTypeAddRage:
|
||||
case buffTypeImmune:
|
||||
case buffTypeUndead:
|
||||
case buffTypeDamageShare:
|
||||
case buffTypeEffectAbnormal:
|
||||
}
|
||||
}
|
||||
for _, target := range targetMap {
|
||||
targetList = append(targetList, target)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcHp(unit *_BattleUnit, damage int64, targetMap map[uint32]*pb.BattleTarget) {
|
||||
var newHp = int64(unit.hp) + damage
|
||||
if newHp < 0 {
|
||||
newHp = 0
|
||||
}
|
||||
unit.hp = uint64(newHp)
|
||||
|
||||
var target = targetMap[unit.position]
|
||||
if target == nil {
|
||||
target = &pb.BattleTarget{
|
||||
Type: uint32(util.If(unit.role.attacker, 1, 2)),
|
||||
Position: unit.position,
|
||||
HpMax: unit.attrs[pb.AttrType_Hp],
|
||||
Rage: unit.rage,
|
||||
BuffList: nil,
|
||||
ValueList: nil,
|
||||
}
|
||||
targetMap[target.Position] = target
|
||||
}
|
||||
|
||||
target.ValueList = append(target.ValueList, &pb.BattleValue{
|
||||
Value: damage,
|
||||
Hp: unit.hp,
|
||||
})
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcAttackTarget(unitList []*_BattleUnit, priorityType, priorityArgs []uint32, rangeType, rangeNum uint32) []*_BattleUnit {
|
||||
var targets []*_BattleUnit
|
||||
if len(priorityType) == 0 {
|
||||
for ui := range unitList {
|
||||
if unitList[ui] != nil && unitList[ui].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
return util.RandomSelect(this.rd, targets, util.If(rangeType == rangeTypeSingle, 1, util.If(rangeNum > 0, int(rangeNum), len(targets))))
|
||||
}
|
||||
|
||||
for i := range priorityType {
|
||||
if len(priorityArgs) <= i {
|
||||
continue
|
||||
}
|
||||
switch priorityType[i] {
|
||||
case priorityTypeNone:
|
||||
if len(priorityType) == 0 {
|
||||
for ui := range unitList {
|
||||
if unitList[ui] != nil && unitList[ui].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
return util.RandomSelect(this.rd, targets, util.If(rangeType == rangeTypeSingle, 1, util.If(rangeNum > 0, int(rangeNum), len(targets))))
|
||||
}
|
||||
case priorityTypePosition:
|
||||
switch priorityArgs[i] {
|
||||
case priorityArgFront:
|
||||
for ui := range []int{0, 1, 2} {
|
||||
if unitList[ui] != nil && unitList[i].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
if len(targets) == 0 {
|
||||
continue
|
||||
}
|
||||
case priorityArgBack:
|
||||
for ui := range []int{3, 4, 5} {
|
||||
if unitList[ui] != nil && unitList[i].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
if len(targets) == 0 {
|
||||
continue
|
||||
}
|
||||
case priorityArgColumn:
|
||||
var columns [][]*_BattleUnit
|
||||
for _, ui := range []int{0, 1, 2} {
|
||||
var column []*_BattleUnit
|
||||
if unitList[ui] != nil && unitList[i].hp > 0 {
|
||||
column = append(column, unitList[ui])
|
||||
}
|
||||
if unitList[ui+3] != nil && unitList[i].hp > 0 {
|
||||
column = append(column, unitList[ui+3])
|
||||
}
|
||||
if len(column) > 0 {
|
||||
columns = append(columns, column)
|
||||
}
|
||||
}
|
||||
for _, column := range util.RandomSelect(this.rd, columns, int(rangeNum)) {
|
||||
for ui := range column {
|
||||
targets = append(targets, column[ui])
|
||||
}
|
||||
}
|
||||
return targets
|
||||
}
|
||||
case priorityTypeHp:
|
||||
for ui := range unitList {
|
||||
if unitList[ui] != nil && unitList[i].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
sort.Slice(targets, func(i, j int) bool {
|
||||
if priorityArgs[i] == priorityArgMin {
|
||||
return targets[i].hp < targets[j].hp
|
||||
} else {
|
||||
return targets[i].hp > targets[j].hp
|
||||
}
|
||||
})
|
||||
break
|
||||
case priorityTypeGender:
|
||||
for ui := range unitList {
|
||||
if unitList[ui] == nil || unitList[ui].hp == 0 || unitList[ui].gender != priorityArgs[i] {
|
||||
continue
|
||||
}
|
||||
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
if len(targets) == 0 {
|
||||
continue
|
||||
}
|
||||
case priorityTypeRage:
|
||||
for ui := range unitList {
|
||||
if unitList[ui] != nil && unitList[i].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
sort.Slice(targets, func(i, j int) bool {
|
||||
if priorityArgs[i] == priorityArgMin {
|
||||
return targets[i].rage < targets[j].rage
|
||||
} else {
|
||||
return targets[i].rage > targets[j].rage
|
||||
}
|
||||
})
|
||||
break
|
||||
case priorityTypeAttack:
|
||||
for ui := range unitList {
|
||||
if unitList[ui] != nil && unitList[i].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
sort.Slice(targets, func(i, j int) bool {
|
||||
if priorityArgs[i] == priorityArgMin {
|
||||
return float64(unitList[i].attrs[pb.AttrType_Attack])*(1.0+float64(unitList[i].attrs[pb.AttrType_AttackRatio])*ratioIn) < float64(unitList[j].attrs[pb.AttrType_Attack])*(1.0+float64(unitList[j].attrs[pb.AttrType_AttackRatio])*ratioIn)
|
||||
} else {
|
||||
return float64(unitList[i].attrs[pb.AttrType_Attack])*(1.0+float64(unitList[i].attrs[pb.AttrType_AttackRatio])*ratioIn) > float64(unitList[j].attrs[pb.AttrType_Attack])*(1.0+float64(unitList[j].attrs[pb.AttrType_AttackRatio])*ratioIn)
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(targets) == 0 {
|
||||
for ui := range unitList {
|
||||
if unitList[ui] != nil && unitList[ui].hp > 0 {
|
||||
targets = append(targets, unitList[ui])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if rangeType == rangeTypeSingle {
|
||||
return targets[:1]
|
||||
} else {
|
||||
if uint32(len(targets)) <= rangeNum {
|
||||
return targets
|
||||
} else {
|
||||
return targets[:rangeNum]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcDamage(buff *_BattleBuff, unit *_BattleUnit, target *_BattleUnit) int64 {
|
||||
var defense float64
|
||||
switch buff.buffType {
|
||||
case buffTypePhysicalDamage:
|
||||
defense = float64(target.attrs[pb.AttrType_PhysicalDefense]) * (1.0 + float64(target.attrs[pb.AttrType_PhysicalDefenseRatio])*ratioIn)
|
||||
case buffTypeMagicDamage:
|
||||
defense = float64(target.attrs[pb.AttrType_MagicDefense]) * (1.0 + float64(target.attrs[pb.AttrType_MagicDefenseRatio])*ratioIn)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
|
||||
if len(buff.buffArgs) < 2 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var attack = float64(unit.attrs[pb.AttrType_Attack]) * (1.0 + float64(unit.attrs[pb.AttrType_AttackRatio])*ratioIn)
|
||||
|
||||
var damage float64
|
||||
if buff.buffArgs[0] == 1 {
|
||||
damage = float64(buff.buffArgs[1])
|
||||
} else {
|
||||
damage = attack * (float64(buff.buffArgs[1]) * ratioIn)
|
||||
}
|
||||
|
||||
var damageRatio = 1.0 + float64(unit.attrs[pb.AttrType_DamageRatio]-target.attrs[pb.AttrType_DamageRelief])*ratioIn
|
||||
var finalDamageRatio = 1.0 + float64(unit.attrs[pb.AttrType_FinalDamageRatio])*ratioIn
|
||||
var finalDamageRelief = 1.0 - float64(target.attrs[pb.AttrType_FinalDamageRelief])*ratioIn
|
||||
|
||||
var criticalRate = (float64(unit.attrs[pb.AttrType_CriticalRate]) - float64(target.attrs[pb.AttrType_CriticalResistance])) * ratioIn
|
||||
|
||||
var factor = this.rd.Float64()
|
||||
|
||||
if factor <= criticalRate {
|
||||
var criticalDamage = float64(unit.attrs[pb.AttrType_CriticalDamage]) * ratioIn
|
||||
var criticalDamageRelief = float64(unit.attrs[pb.AttrType_CriticalDamageRelief]) * ratioIn
|
||||
damage = ((damage - defense) * damageRatio * 2) * (criticalDamage - criticalDamageRelief) * finalDamageRatio * finalDamageRelief
|
||||
} else {
|
||||
damage = (damage - defense) * damageRatio * finalDamageRatio * finalDamageRelief
|
||||
if damage <= 0 {
|
||||
damage = 1
|
||||
}
|
||||
}
|
||||
return int64(-damage)
|
||||
}
|
||||
|
||||
func (this *_BattleCalculator) calcTreat(buff _BattleBuff, unit *_BattleUnit, target *_BattleUnit) int64 {
|
||||
return 0
|
||||
}
|
76
servers/game/logic/player_battle_define.go
Normal file
76
servers/game/logic/player_battle_define.go
Normal file
@ -0,0 +1,76 @@
|
||||
package logic
|
||||
|
||||
const (
|
||||
targetTypeSelf = 0 //自身
|
||||
targetTypeTeammate = 1 //友方
|
||||
targetTypeEnemy = 2 //敌方
|
||||
targetTypeTeammateGender = 3 //友方特定性别
|
||||
targetTypeEnemyGender = 4 //敌方特定性别
|
||||
targetTypeTeammateCountry = 5 //友方特定国家
|
||||
targetTypeEnemyCountry = 6 //敌方特定国家
|
||||
targetTypeTeammateStatus = 7 //友方异常目标
|
||||
targetTypeEnemyStatus = 8 //敌方异常目标
|
||||
targetTypeAttackRate = 9 //击中数量少于目标数量万分比
|
||||
)
|
||||
|
||||
const (
|
||||
countryNone = 0 //无国家
|
||||
countryWei = 1 //魏
|
||||
countryShu = 2 //蜀
|
||||
countryMouse = 3 //鼠辈
|
||||
countryCrowd = 4 //群雄
|
||||
)
|
||||
|
||||
const (
|
||||
rangeTypeSingle = 0 //单个
|
||||
rangeTypeMulti = 0 //多个
|
||||
)
|
||||
|
||||
const (
|
||||
priorityTypeNone = 0 //没有优先
|
||||
priorityTypePosition = 1 //位置优先
|
||||
priorityTypeHp = 2 //血量优先
|
||||
priorityTypeGender = 3 //性别优先
|
||||
priorityTypeRage = 4 //怒气优先
|
||||
priorityTypeAttack = 5 //攻击力优先
|
||||
)
|
||||
|
||||
const (
|
||||
priorityArgFront = 0 //前排
|
||||
priorityArgBack = 1 //后排
|
||||
priorityArgColumn = 2 //纵排
|
||||
priorityArgFemale = 0 //女性
|
||||
priorityArgMale = 1 //男性
|
||||
priorityArgMin = 0 //最低
|
||||
priorityArgMax = 1 //最高
|
||||
)
|
||||
|
||||
const (
|
||||
buffTypeNone = 0
|
||||
buffTypePhysicalDamage = 1 //物理伤害
|
||||
buffTypeMagicDamage = 2 //法术伤害
|
||||
buffTypeStatusAbnormal = 3 //异常状态(无法攻击,无法移动等)
|
||||
buffTypeChangeAttr = 4 //改变属性
|
||||
buffTypeRevive = 5 //复活
|
||||
buffTypeDamageReturn = 6 //伤害反弹
|
||||
buffTypeBisect = 7 //伤害平摊(分担)
|
||||
buffTypeShield = 8 //护盾
|
||||
buffTypeChangeHp = 9 //改变血量
|
||||
buffTypeSteal = 10 //窃取属性
|
||||
buffTypeAddRage = 11 //增加怒气
|
||||
buffTypeImmune = 12 //免疫
|
||||
buffTypeUndead = 13 //不死
|
||||
buffTypeDamageShare = 14 //伤害共享(共享)
|
||||
buffTypeEffectAbnormal = 15 //异常效果(DeBuff)
|
||||
)
|
||||
|
||||
const (
|
||||
skillTypeAttack = 1 //普击
|
||||
skillTypeActive = 2 //主动
|
||||
skillTypePassive = 3 //被动
|
||||
)
|
||||
|
||||
const (
|
||||
ratioIn float64 = 0.0001
|
||||
ratioOut float64 = 10000
|
||||
)
|
@ -47,7 +47,7 @@ func (this *Player) PassedCopyMain(copyMainTable *data.CopyMain, maxScore int32)
|
||||
//this.CopyMainSceneId = uint32(copyChapterTable.SceneId)
|
||||
//this.SaveField("role.mainline_scene_id", this.Role.CopyMainSceneId)
|
||||
|
||||
_ = this.Send(uint16(pb.ModId_ModuleLevel), uint16(pb.MsgId_ModLevelCopyStatusChange), &pb.MsgCopyStatusChangeAck{Status: copyStatus.BuildMsgCopyStatus()})
|
||||
_ = this.Send(pb.ModId_ModuleLevel, pb.MsgId_ModLevelCopyStatusChange, &pb.MsgCopyStatusChangeAck{Status: copyStatus.BuildMsgCopyStatus()})
|
||||
|
||||
//var copyMainRanking = this.manager.arenaManager.copyMainRanking
|
||||
//if copyMainRanking != nil {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"github.com/oylshe1314/framework/util"
|
||||
)
|
||||
|
||||
type Attrs [pb.AttrType_Nums]uint64
|
||||
type Attrs [pb.AttrType_AttrNums]uint64
|
||||
|
||||
type PlayerHero struct {
|
||||
Uid uint64 `json:"uid" key:"1"`
|
||||
@ -69,10 +69,12 @@ func (this *Player) AddHero(heroId uint32) bool {
|
||||
hero.Level = 1
|
||||
}
|
||||
|
||||
this.updateHeroAttrs(hero, nil, nil)
|
||||
|
||||
this.Hero[hero.Uid] = hero
|
||||
this.SaveModel(hero)
|
||||
|
||||
_ = this.Send(uint16(pb.ModId_ModuleHero), uint16(pb.MsgId_ModHeroChange), &pb.HeroChangeListAck{
|
||||
_ = this.Send(pb.ModId_ModuleHero, pb.MsgId_ModHeroChange, &pb.HeroChangeListAck{
|
||||
ChangeList: []*pb.HeroChange{{ChangeType: pb.ChangeType_Add, Hero: hero.BuildMsgHero()}},
|
||||
})
|
||||
|
||||
@ -100,6 +102,8 @@ func (this *Player) AddHeroes(heroId, nums uint32) bool {
|
||||
Level: level,
|
||||
}
|
||||
|
||||
this.updateHeroAttrs(hero, nil, nil)
|
||||
|
||||
this.Hero[hero.Uid] = hero
|
||||
this.SaveModel(hero)
|
||||
|
||||
@ -108,7 +112,7 @@ func (this *Player) AddHeroes(heroId, nums uint32) bool {
|
||||
//this.CheckAchievement(proto.AchievementTypeEquipLevel, uint32(equipTable.Level), 1)
|
||||
}
|
||||
|
||||
_ = this.Send(uint16(pb.ModId_ModuleHero), uint16(pb.MsgId_ModHeroChange), &pb.HeroChangeListAck{
|
||||
_ = this.Send(pb.ModId_ModuleHero, pb.MsgId_ModHeroChange, &pb.HeroChangeListAck{
|
||||
ChangeList: changeList,
|
||||
})
|
||||
|
||||
@ -133,7 +137,7 @@ func (this *Player) ReduceHeroes(heroes map[uint64]*PlayerHero, logType LogType)
|
||||
for _, hero := range heroes {
|
||||
changeList = append(changeList, this.reduceHero(hero, logType))
|
||||
}
|
||||
_ = this.Send(uint16(pb.ModId_ModuleHero), uint16(pb.MsgId_ModHeroChange), &pb.HeroChangeListAck{ChangeList: changeList})
|
||||
_ = this.Send(pb.ModId_ModuleHero, pb.MsgId_ModHeroChange, &pb.HeroChangeListAck{ChangeList: changeList})
|
||||
}
|
||||
|
||||
func (this *Player) BuildMsgHeroListAck() *pb.HeroListAck {
|
||||
|
@ -298,14 +298,6 @@ func (this *Player) calcHeroArtifactAttrs(hero *PlayerHero, lineup *PlayerLineup
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Player) calcHeroSpeedAttrs(hero *PlayerHero, lineup *PlayerLineup, lineupHero *PlayerLineupHero) (attrs Attrs) {
|
||||
if lineup == nil || lineupHero == nil {
|
||||
return
|
||||
}
|
||||
hero.attrs[pb.AttrType_AttrSpeed] = 100 + uint64(20-(4*((lineupHero.Position-1)%3)))
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Player) calcHeroAttrs(hero *PlayerHero, attrsList ...Attrs) bool {
|
||||
var newAttrs Attrs
|
||||
for _, attrs := range attrsList {
|
||||
@ -333,7 +325,6 @@ func (this *Player) updateHeroAttrs(hero *PlayerHero, lineup *PlayerLineup, line
|
||||
this.calcHeroTreasuresAttrs(hero, lineup, lineupHero),
|
||||
this.calcHeroMountsAttrs(hero, lineup, lineupHero),
|
||||
this.calcHeroArtifactAttrs(hero, lineup, lineupHero),
|
||||
this.calcHeroSpeedAttrs(hero, lineup, lineupHero),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ func (this *Player) SendLineupHeroChange(lineups ...*PlayerLineup) {
|
||||
}
|
||||
}
|
||||
if len(heroChangeList) > 0 {
|
||||
_ = this.Send(uint16(pb.ModId_ModuleHero), uint16(pb.MsgId_ModHeroChange), pb.HeroChangeListAck{
|
||||
_ = this.Send(pb.ModId_ModuleHero, pb.MsgId_ModHeroChange, pb.HeroChangeListAck{
|
||||
ChangeList: heroChangeList,
|
||||
})
|
||||
}
|
||||
@ -178,10 +178,10 @@ func (this *Player) SendUpgradeMaster(masterType pb.UpgradeMasterType, preLevel,
|
||||
ack.PreLevel = uint32(preMasterTable.Level)
|
||||
}
|
||||
|
||||
_ = this.Send(uint16(pb.ModId_ModuleRole), uint16(pb.MsgId_ModRoleUpgradeMaster), ack)
|
||||
_ = this.Send(pb.ModId_ModuleRole, pb.MsgId_ModRoleUpgradeMaster, ack)
|
||||
|
||||
if this.updateHeroAttrs(hero, lineup, lineupHero) {
|
||||
_ = this.Send(uint16(pb.ModId_ModuleHero), uint16(pb.MsgId_ModHeroChange), pb.HeroChangeListAck{
|
||||
_ = this.Send(pb.ModId_ModuleHero, pb.MsgId_ModHeroChange, pb.HeroChangeListAck{
|
||||
ChangeList: []*pb.HeroChange{{ChangeType: pb.ChangeType_Changed, Hero: hero.BuildMsgHero()}},
|
||||
})
|
||||
}
|
||||
|
@ -49,23 +49,5 @@ func (this *Player) UpdateBattleHeroCapacity(lineupHero *PlayerLineupHero) {
|
||||
return
|
||||
}
|
||||
|
||||
var attrs = hero.Attrs()
|
||||
|
||||
var capacity = (float64(attrs[pb.AttrType_Attack]) * 2) +
|
||||
(float64(attrs[pb.AttrType_Hp]) * 0.2) +
|
||||
(float64(attrs[pb.AttrType_AttrPhysicalDefense]) * 6) +
|
||||
(float64(attrs[pb.AttrType_AttrMagicDefense]) * 6) +
|
||||
(float64(attrs[pb.AttrType_AttrDamageRatio]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrDamageRelief]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrCriticalRatio]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrCriticalResistance]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrCriticalDamage]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrCriticalDamageRelief]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrHitRate]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrDodgeRate]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrTreatRatio]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrByTreatedRatio]) * 12) +
|
||||
(float64(attrs[pb.AttrType_AttrFinalDamageRatio]) * 12)
|
||||
|
||||
lineupHero.Capacity = uint64(capacity)
|
||||
lineupHero.Capacity = this.calcAttrsCapacity(hero.attrs)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user