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 }