397 lines
11 KiB
Go
397 lines
11 KiB
Go
package logic
|
|
|
|
import (
|
|
"ecs/proto"
|
|
"ecs/proto/pb"
|
|
"ecs/servers/game/data"
|
|
"github.com/oylshe1314/framework/util"
|
|
"sort"
|
|
)
|
|
|
|
func (this *Player) EnterBattle(sceneTable *data.Scene) {
|
|
this.Temp.Fighting = true
|
|
this.Temp.RandSeed = util.DefaultRandom.Uint64()
|
|
|
|
this.enterScene(uint32(sceneTable.Id))
|
|
this.copyBattle(sceneTable)
|
|
}
|
|
|
|
func (this *Player) EndBattle() {
|
|
this.Temp.Fighting = false
|
|
this.Temp.RandSeed = 0
|
|
this.enterScene(0)
|
|
}
|
|
|
|
func (this *Player) copyBattle(sceneTable *data.Scene) {
|
|
var ack, err = this.virtualBattle(sceneTable)
|
|
if err != nil {
|
|
_ = this.TipNotice(err)
|
|
return
|
|
}
|
|
|
|
if ack.Succeed {
|
|
this.PassedCopy(sceneTable, ack.Score)
|
|
}
|
|
|
|
_ = 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
|
|
})
|
|
if lineup == nil {
|
|
return nil, proto.TipLineupNotFound
|
|
}
|
|
|
|
var me = &_BattleRole{attacker: true}
|
|
me.capacity, me.unitList, tip = this.loadHeroes(me, lineup)
|
|
if tip != nil {
|
|
_ = this.TipNotice(tip)
|
|
return
|
|
}
|
|
|
|
//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 {
|
|
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),
|
|
}
|
|
|
|
ack.Heroes = make([]*pb.BattleUnit, 6)
|
|
for i := range me.unitList {
|
|
if me.unitList[i] != nil {
|
|
ack.Heroes[i] = &pb.BattleUnit{
|
|
UnitId: me.unitList[i].id,
|
|
}
|
|
}
|
|
}
|
|
|
|
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) 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) 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
|
|
}
|
|
|
|
var monsterTable = this.manager.tables.Monster.Find(int(monsterId))
|
|
if monsterTable == nil {
|
|
return 0, nil, proto.TipDataTablesError
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
unit.attrs[pb.AttrType_Attack] = uint64(monsterTable.AttrValue1)
|
|
unit.attrs[pb.AttrType_Hp] = uint64(monsterTable.AttrValue2)
|
|
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
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *Player) loadSkills(skillIds []int) (skillList []*_BattleSkill, tip proto.TipError) {
|
|
skillList = make([]*_BattleSkill, 0, len(skillIds))
|
|
for _, skillId := range skillIds {
|
|
var skillTable = this.manager.tables.Skill.Find(skillId)
|
|
if skillTable == nil {
|
|
return nil, proto.TipDataTablesError
|
|
}
|
|
|
|
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, 0, len(buffIds))
|
|
for _, buffId := range buffIds {
|
|
var buffTable = this.manager.tables.SkillBuff.Find(buffId)
|
|
if buffTable == nil {
|
|
return nil, proto.TipDataTablesError
|
|
}
|
|
|
|
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 = append(buffList, buff)
|
|
}
|
|
return buffList, nil
|
|
}
|