diff --git a/common/data/Element/element.go b/common/data/Element/element.go index dab3c9f3..9730d031 100644 --- a/common/data/Element/element.go +++ b/common/data/Element/element.go @@ -95,9 +95,9 @@ var dualElementMap = map[int][2]int{ // 元素组合结构体 type ElementCombination struct { - primary ElementType // 主属性(1-17) - secondary *ElementType // 副属性(1-17,双属性时非空) - id int // 组合ID + Primary ElementType // 主属性(1-17) + Secondary *ElementType // 副属性(1-17,双属性时非空) + ID int // 组合ID } // 创建元素组合(严格验证范围) @@ -116,9 +116,9 @@ func NewElementCombination(id int) (*ElementCombination, error) { primary, secondary = secondary, primary } return &ElementCombination{ - primary: primary, - secondary: &secondary, - id: id, + Primary: primary, + Secondary: &secondary, + ID: id, }, nil } @@ -126,36 +126,36 @@ func NewElementCombination(id int) (*ElementCombination, error) { return nil, fmt.Errorf("单属性ID必须为1-17,实际: %d", id) } return &ElementCombination{ - primary: ElementType(id), - secondary: nil, - id: id, + Primary: ElementType(id), + Secondary: nil, + ID: id, }, nil } // 判断是否为双属性 func (ec *ElementCombination) IsDual() bool { - return ec.secondary != nil + return ec.Secondary != nil } // 获取所有属性 func (ec *ElementCombination) Elements() []ElementType { if ec.IsDual() { - return []ElementType{ec.primary, *ec.secondary} + return []ElementType{ec.Primary, *ec.Secondary} } - return []ElementType{ec.primary} + return []ElementType{ec.Primary} } // 缓存键 func (ec *ElementCombination) CacheKey() string { - return fmt.Sprintf("id_%d", ec.id) + return fmt.Sprintf("id_%d", ec.ID) } // 字符串展示 func (ec *ElementCombination) String() string { if ec.IsDual() { - return fmt.Sprintf("(%v, %v)", ec.primary, *ec.secondary) + return fmt.Sprintf("(%v, %v)", ec.Primary, *ec.Secondary) } - return fmt.Sprintf("(%vv)", ec.primary) + return fmt.Sprintf("(%vv)", ec.Primary) } // 元素计算器(全属性支持+缓存) @@ -375,85 +375,85 @@ func (c *ElementCalculator) GetOffensiveMultiplier(attackerXID, defenderYID int) // 核心计算逻辑(严格遵循橙汁学姐规则) func (c *ElementCalculator) calculateMultiplier(attackerX, defenderY *ElementCombination) float64 { - // 1. 单属性→单属性:直接查表 - if !attackerX.IsDual() && !defenderY.IsDual() { - return c.tableMatrix[attackerX.primary][defenderY.primary] - } + // 1. 单属性→单属性:直接查表 + if !attackerX.IsDual() && !defenderY.IsDual() { + return c.tableMatrix[attackerX.Primary][defenderY.Primary] + } - // 2. 单属性→双属性:拆分防守方,分类计算 - if !attackerX.IsDual() { - y1, y2 := defenderY.primary, *defenderY.secondary - m1 := c.tableMatrix[attackerX.primary][y1] - m2 := c.tableMatrix[attackerX.primary][y2] + // 2. 单属性→双属性:拆分防守方,分类计算 + if !attackerX.IsDual() { + y1, y2 := defenderY.Primary, *defenderY.Secondary + m1 := c.tableMatrix[attackerX.Primary][y1] + m2 := c.tableMatrix[attackerX.Primary][y2] - // 单→双规则:双克制=4,含无效÷4,其他÷2 - if m1 == 2 && m2 == 2 { - return 4.0 - } else if m1 == 0 || m2 == 0 { - return (m1 + m2) / 4.0 - } else { - return (m1 + m2) / 2.0 - } - } + // 单→双规则:双克制=4,含无效÷4,其他÷2 + if m1 == 2 && m2 == 2 { + return 4.0 + } else if m1 == 0 || m2 == 0 { + return (m1 + m2) / 4.0 + } else { + return (m1 + m2) / 2.0 + } + } - // 3. 双属性→单属性:拆分攻击方,分类计算 - if !defenderY.IsDual() { - x1, x2 := attackerX.primary, *attackerX.secondary - k1 := c.tableMatrix[x1][defenderY.primary] - k2 := c.tableMatrix[x2][defenderY.primary] + // 3. 双属性→单属性:拆分攻击方,分类计算 + if !defenderY.IsDual() { + x1, x2 := attackerX.Primary, *attackerX.Secondary + k1 := c.tableMatrix[x1][defenderY.Primary] + k2 := c.tableMatrix[x2][defenderY.Primary] - // 补全默认值(未定义的普通关系为1.0) - if k1 == 0 && c.tableMatrix[x1][defenderY.primary] != 0 { - k1 = 1.0 - } - if k2 == 0 && c.tableMatrix[x2][defenderY.primary] != 0 { - k2 = 1.0 - } + // 补全默认值(未定义的普通关系为1.0) + if k1 == 0 && c.tableMatrix[x1][defenderY.Primary] != 0 { + k1 = 1.0 + } + if k2 == 0 && c.tableMatrix[x2][defenderY.Primary] != 0 { + k2 = 1.0 + } - // 双→单规则:双克制=4,含无效÷4,其他÷2 - if k1 == 2 && k2 == 2 { - return 4.0 - } else if k1 == 0 || k2 == 0 { - return (k1 + k2) / 4.0 - } else { - return (k1 + k2) / 2.0 - } - } + // 双→单规则:双克制=4,含无效÷4,其他÷2 + if k1 == 2 && k2 == 2 { + return 4.0 + } else if k1 == 0 || k2 == 0 { + return (k1 + k2) / 4.0 + } else { + return (k1 + k2) / 2.0 + } + } - // 4. 双属性→双属性:拆分防守方为两个单属性,分别计算双→单后取平均 - x1, x2 := attackerX.primary, *attackerX.secondary - y1, y2 := defenderY.primary, *defenderY.secondary + // 4. 双属性→双属性:拆分防守方为两个单属性,分别计算双→单后取平均 + x1, x2 := attackerX.Primary, *attackerX.Secondary + y1, y2 := defenderY.Primary, *defenderY.Secondary - // 计算攻击方对防守方第一个单属性(y1)的双→单系数 - coeffY1 := c.calculateDualToSingle(x1, x2, y1) - // 计算攻击方对防守方第二个单属性(y2)的双→单系数 - coeffY2 := c.calculateDualToSingle(x1, x2, y2) + // 计算攻击方对防守方第一个单属性(y1)的双→单系数 + coeffY1 := c.calculateDualToSingle(x1, x2, y1) + // 计算攻击方对防守方第二个单属性(y2)的双→单系数 + coeffY2 := c.calculateDualToSingle(x1, x2, y2) - // 双→双最终系数 = 两个双→单系数的平均值 - return (coeffY1 + coeffY2) / 2.0 + // 双→双最终系数 = 两个双→单系数的平均值 + return (coeffY1 + coeffY2) / 2.0 } // 辅助函数:双属性攻击单属性的核心计算(提取复用逻辑) func (c *ElementCalculator) calculateDualToSingle(attacker1, attacker2, defender ElementType) float64 { - k1 := c.tableMatrix[attacker1][defender] - k2 := c.tableMatrix[attacker2][defender] + k1 := c.tableMatrix[attacker1][defender] + k2 := c.tableMatrix[attacker2][defender] - // 补全默认值(未定义的普通关系为1.0) - if k1 == 0 && c.tableMatrix[attacker1][defender] != 0 { - k1 = 1.0 - } - if k2 == 0 && c.tableMatrix[attacker2][defender] != 0 { - k2 = 1.0 - } + // 补全默认值(未定义的普通关系为1.0) + if k1 == 0 && c.tableMatrix[attacker1][defender] != 0 { + k1 = 1.0 + } + if k2 == 0 && c.tableMatrix[attacker2][defender] != 0 { + k2 = 1.0 + } - // 双→单规则应用 - if k1 == 2 && k2 == 2 { - return 4.0 - } else if k1 == 0 || k2 == 0 { - return (k1 + k2) / 4.0 - } else { - return (k1 + k2) / 2.0 - } + // 双→单规则应用 + if k1 == 2 && k2 == 2 { + return 4.0 + } else if k1 == 0 || k2 == 0 { + return (k1 + k2) / 4.0 + } else { + return (k1 + k2) / 2.0 + } } // 全场景测试用例 diff --git a/logic/controller/pet.go b/logic/controller/pet.go index 3901bb8b..da9081e8 100644 --- a/logic/controller/pet.go +++ b/logic/controller/pet.go @@ -54,7 +54,7 @@ func (h *Controller) PetRelease( t := blservice.NewUserService(c.Info.UserID).PetM(int(data.CatchTime), int(data.Flag)) switch data.Flag { case 0: - //todo 仓库 + removeIndex := -1 for i, v := range c.Info.PetList { if v.CatchTime == uint32(data.CatchTime) { @@ -66,16 +66,16 @@ func (h *Controller) PetRelease( if removeIndex != -1 { c.Info.PetList = append(c.Info.PetList[:removeIndex], c.Info.PetList[removeIndex+1:]...) } - if len(c.Info.PetList) > 0 { - result.FirstPetTime = c.Info.PetList[0].CatchTime //设置首发 - } case 1: //todo 背包 c.Info.PetList = append(c.Info.PetList, t) result.PetInfo = t - } + } + if len(c.Info.PetList) > 0 { + result.FirstPetTime = c.Info.PetList[0].CatchTime //设置首发 + } //service.NewUserService(c.Info.UserID).PetAdd( *r) return result, 0 } diff --git a/logic/service/fight/info/BattlePetEntity.go b/logic/service/fight/info/BattlePetEntity.go index 807e4e4f..df0df577 100644 --- a/logic/service/fight/info/BattlePetEntity.go +++ b/logic/service/fight/info/BattlePetEntity.go @@ -39,6 +39,26 @@ func (a *BattlePetEntity) Value(tt uint32) uint32 { func (a *BattlePetEntity) Speed() uint32 { return uint32(calculateRealValue(int64(a.Info.Speed), int(a.Prop.Speed))) +} +func (a *BattlePetEntity) Attack() uint32 { + return uint32(calculateRealValue(int64(a.Info.Attack), int(a.Prop.Attack))) + +} +func (a *BattlePetEntity) Defense() uint32 { + return uint32(calculateRealValue(int64(a.Info.Defence), int(a.Prop.Defence))) + +} +func (a *BattlePetEntity) SAttack() uint32 { + return uint32(calculateRealValue(int64(a.Info.SpecialAttack), int(a.Prop.SpecialAttack))) + +} +func (a *BattlePetEntity) SDefense() uint32 { + return uint32(calculateRealValue(int64(a.Info.SpecialDefence), int(a.Prop.SpecialDefence))) + +} +func (a *BattlePetEntity) Accuracy(b int64) uint32 { + return uint32(calculateRealValue(b, int(a.Prop.Accuracy))) + } type BattlePetEntity struct { @@ -53,14 +73,14 @@ type BattlePetEntity struct { } // 创建精灵实例 -func CreateBattlePetEntity(info *model.PetInfo, rand *rand.Source) *BattlePetEntity { +func CreateBattlePetEntity(info *model.PetInfo, rand *rand.Rand) *BattlePetEntity { ret := &BattlePetEntity{} ret.PetInfo = xmlres.PetMAP[int(info.ID)] //注入精灵信息 ret.Info = *info for i := 0; i < 4; i++ { //todo 技能信息应该每回合进行深拷贝,保证每次的技能效果都是不一样的 - ret.Skills[i] = CreateBattleSkillWithInfinity(&info.SkillList[i], rand) + ret.Skills[i] = CreateBattleSkillWithInfinity(&info.SkillList[i], rand, ret) } return ret @@ -92,9 +112,16 @@ func calculateRealValue(value int64, stat int) int64 { } } -func (u *BattlePetEntity) Type() element.ElementType { +func (u *BattlePetEntity) Type() *element.ElementCombination { + var ff *element.ElementCombination + for _, v := range xmlres.PetMAP { + if v.ID == int(u.Info.ID) { + ff, _ = element.NewElementCombination(v.Type) + } + + } //todo 待实现获取精灵的类型 - return element.ElementType(0) + return ff } diff --git a/logic/service/fight/info/BattleSkillEntity.go b/logic/service/fight/info/BattleSkillEntity.go index 5a2b6f2d..c57c2f10 100644 --- a/logic/service/fight/info/BattleSkillEntity.go +++ b/logic/service/fight/info/BattleSkillEntity.go @@ -29,6 +29,7 @@ var Category = enum.New[struct { Fixed EnumCategory // 固定伤害 Percent EnumCategory // 百分比伤害 True EnumCategory // 真伤 + ALL EnumCategory //任何类型 }]() // BattleSkillEntity 战斗技能实体 @@ -41,21 +42,25 @@ type BattleSkillEntity struct { PP int DamageZone map[EnumCategory]map[EnumsZoneType]map[EnumsZoneType][]float64 // 三维map 伤害类型-》增还是减-》加还是乘-》值 DamageValue decimal.Decimal // 伤害值 - Rand rand.Source + Rand *rand.Rand + Pet *BattlePetEntity // 技能类型属性 //SkillType EnumCategory // 技能类型(物理/特殊/状态) } // CreateBattleSkillWithInfinity 创建战斗技能实例(可指定是否无限PP) -func CreateBattleSkillWithInfinity(skill *model.SkillInfo, rand *rand.Source) *BattleSkillEntity { +func CreateBattleSkillWithInfinity(skill *model.SkillInfo, rand *rand.Rand, pet *BattlePetEntity) *BattleSkillEntity { //如果PP是-1 ,那就是无限PP // ID小于10001的视为无效技能 if skill.ID < 10001 { return nil } + var ret BattleSkillEntity + ret.Rand = rand + ret.Pet = pet // 从资源仓库获取技能数据 move, ok := xmlres.SkillMap[int(skill.ID)] @@ -116,8 +121,9 @@ func (s *BattleSkillEntity) Category() EnumCategory { } // 获取技能属性 -func (s *BattleSkillEntity) Type() element.ElementType { - return element.ElementType(s.Move.Type) +func (s *BattleSkillEntity) Type() *element.ElementCombination { + ret, _ := element.NewElementCombination(s.Move.Type) + return ret } // // 技能产生effect @@ -235,108 +241,112 @@ func (s *BattleSkillEntity) PutDamageZone(e EnumCategory, dtype EnumsZoneType, v // } // 暴击伤害 返回暴击率和是否暴击 -func (s *BattleSkillEntity) CriticalRate() decimal.Decimal { +func (s *BattleSkillEntity) CriticalRate() (decimal.Decimal, uint32) { - return decimal.NewFromFloat(2) + return decimal.NewFromFloat(1), 1 } -// func (s *BattleSkillEntity) criticalrandom() decimal.Decimal { -// //这里应该算上威力区 -// // 初始化随机值,范围217~255 +// 计算是否命中 +func (s *BattleSkillEntity) CriticalisCritical() uint32 { -// randomnum := s.Random().NextLongN(39) + 217 -// // 10. 随机倍率,随机值除以255 -// randomFactor := decimal.NewFromInt(int64(randomnum)).Div(decimal.NewFromInt(255)) -// return randomFactor + if int64(s.Pet.Accuracy(int64(s.Accuracy))) > s.Rand.Int63n(100) { + return 1 + } + return 0 -// } +} +func (s *BattleSkillEntity) CriticalsameTypeBonus() decimal.Decimal { -// // 计算技能威力 -// func (s *BattleSkillEntity) CalculatePower(p *BattlePetEntity) int64 { + // 6. 同系加成(属性相同则乘以同系加成倍率,否则1) + sameTypeBonus := decimal.NewFromFloat(1.0) + if s.Type() == s.Pet.Type() { //使用本系 + sameTypeBonus = decimal.NewFromFloat(1.5) + } -// pet, _ := s.Pet() + stype := s.Type() + ptype := s.Pet.Type() -// // 1. 计算等级因子 (level * 0.4 + 2) -// levelFactor := decimal.NewFromInt(int64(pet.Level)). -// Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2)) + if stype.Secondary == nil && ptype.Secondary != nil && (stype.Primary == ptype.Primary || stype.Primary == *ptype.Secondary) { //判断技能属性是否是精灵双属性之一 + sameTypeBonus = decimal.NewFromFloat(1.5) + } + return sameTypeBonus +} -// // 2. 计算威力因子 (基础威力 + 加算) * 乘算 +func (s *BattleSkillEntity) criticalrandom() decimal.Decimal { -// //powerAdd := decimal.NewFromFloat(s.GetAddValue(EnumCategory., true)) //威力加算区 + randomnum := s.Rand.Int31n(39) + 217 + // 10. 随机倍率,随机值除以255 + randomFactor := decimal.NewFromInt(int64(randomnum)).Div(decimal.NewFromInt(255)) + return randomFactor -// powerMul := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.POWER_MUL]) //威力乘算区 -// powerZone := decimal.NewFromInt(int64(s.Power)).Add(powerAdd).Mul(powerMul) +} -// var ( -// attackDec decimal.Decimal //攻击值 -// defenseDec decimal.Decimal //防御值 -// damageReduction decimal.Decimal //伤害百分比减免 -// ) -// switch s.Category() { //判断技能类型 -// case Category.PHYSICAL: -// attackDec = decimal.NewFromInt(int64(pet.UnitAttributes[AttrType.Attack].Value())) -// defenseDec = decimal.NewFromInt(int64(p.UnitAttributes[AttrType.Defense].Value())) -// damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.ATK_RESISTANCE]) +// 计算技能威力 +func (s *BattleSkillEntity) CalculatePower(deftype int) uint32 { -// case Category.SPECIAL: -// attackDec = decimal.NewFromInt(int64(pet.UnitAttributes[AttrType.Attack].Value())) -// defenseDec = decimal.NewFromInt(int64(p.UnitAttributes[AttrType.Speed].Value())) -// damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.SP_ATK_RESISTANCE]) -// } -// //攻击次数结算 -// attackCount := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.ATTACK_COUNT_ZONE]) -// // 5. 基础伤害公式:等级因子 * 威力因子 * 攻击 / 防御 / 50 + 2,然后乘以攻击次数 -// baseDamage := levelFactor. -// Mul(powerZone). -// Mul(attackDec). -// Div(defenseDec). -// Div(decimal.NewFromInt(50)). -// Add(decimal.NewFromInt(2)). -// Mul(attackCount) + // 1. 计算等级因子 (level * 0.4 + 2) + levelFactor := decimal.NewFromInt(int64(s.Pet.Info.Level)). + Mul(decimal.NewFromFloat(0.4)).Add(decimal.NewFromInt(2)) -// // 6. 同系加成(属性相同则乘以同系加成倍率,否则1) -// sameTypeBonus := decimal.NewFromFloat(1.0) -// if s.Type() == pet.Type() { -// sameTypeBonus = decimal.NewFromFloat(1.5) -// } + // 2. 计算威力因子 (基础威力 + 加算) * 乘算 -// t, _ := element.NewElementCalculator().GetOffensiveMultiplier(int(pet.Type()), int(pet.Type())) + //powerAdd := decimal.NewFromFloat(s.GetAddValue(EnumCategory., true)) //威力加算区 + powerAdd_all := s.GetAddValue(Category.ALL, DamageC.boost) + powerMul_all := s.GetMulValue(Category.ALL, DamageC.boost) -// typeRate := decimal.NewFromFloat(t) + var ( + powerAdd_p decimal.Decimal //威力加算 + powerMul_p decimal.Decimal //威力乘算 + attackDec decimal.Decimal //攻击值 + defenseDec decimal.Decimal //防御值 + //damageReduction decimal.Decimal //伤害百分比减免 + ) + switch s.Category() { //判断技能类型 + case Category.PHYSICAL: -// // 8. 暴击倍率(暴击时使用暴击倍率,否则1) + powerAdd_p = powerAdd_all.Add(s.GetAddValue(Category.PHYSICAL, DamageC.boost)) + powerMul_p = powerMul_all.Add(s.GetMulValue(Category.PHYSICAL, DamageC.boost)) + attackDec = decimal.NewFromInt(int64(s.Pet.Attack())) + defenseDec = decimal.NewFromInt(int64(s.Pet.Defense())) + //damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.ATK_RESISTANCE]) -// criticalRate := decimal.NewFromFloat(1.0) -// if s.isCritical { -// criticalRate = s.CriticalRate() -// } + case Category.SPECIAL: + powerAdd_p = powerAdd_all.Add(s.GetAddValue(Category.SPECIAL, DamageC.boost)) + powerMul_p = powerMul_all.Add(s.GetMulValue(Category.SPECIAL, DamageC.boost)) + attackDec = decimal.NewFromInt(int64(s.Pet.SAttack())) + defenseDec = decimal.NewFromInt(int64(s.Pet.SDefense())) + //damageReduction = decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.SP_ATK_RESISTANCE]) -// // 9. 技能特殊效果倍率 -// specialEffect := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.SPECIAL_EFFECT_MUL]) + default: + return 0 + } -// // 11. 计算总伤害 -// damage := baseDamage. -// Mul(sameTypeBonus). // 同属性加成 -// Mul(typeRate). // 克制系数 -// Mul(criticalRate). //暴击系数 -// Mul(damageReduction). //减伤计算 -// Mul(specialEffect). //特殊效果 -// Mul(s.criticalrandom()) //随机波动 + if powerMul_p.IntPart() == 0 { + powerMul_p = decimal.NewFromInt(1) + } + powerZone := decimal.NewFromInt(int64(s.Power)).Add(powerAdd_p).Mul(powerMul_p) + // 5. 基础伤害公式:等级因子 * 威力因子 * 攻击 / 防御 / 50 + 2 + baseDamage := levelFactor. + Mul(powerZone). + Mul(attackDec). + Div(defenseDec). + Div(decimal.NewFromInt(50)). + Add(decimal.NewFromInt(2)) -// // 12. 存储真实伤害到额外倍率,方便后续查询 -// //context.PutExtraRate("REAL_DAMAGE", damage) + t, _ := element.NewElementCalculator().GetOffensiveMultiplier(s.Type().ID, deftype) -// // 13. 应用固定伤害减免,伤害不能低于0 -// fixReduction := decimal.NewFromFloat(s.DamageZone[DamageMultiplierZoneEnum.DEFENSE_ZONE]) -// if fixReduction.GreaterThan(decimal.Zero) { -// damage = damage.Sub(fixReduction) -// if damage.LessThan(decimal.Zero) { -// damage = decimal.Zero -// } -// } + typeRate := decimal.NewFromFloat(t) -// // 返回最终伤害(整数部分) -// return damage.IntPart() + damage := baseDamage. + Mul(s.CriticalsameTypeBonus()). // 同属性加成 + Mul(typeRate). // 克制系数 -// } + Mul(s.criticalrandom()) //随机波动 + v, ok := s.CriticalRate() + if ok == 1 { + damage.Mul(v) + } + return uint32(damage.IntPart()) + +} diff --git a/logic/service/fight/info/info.go b/logic/service/fight/info/info.go index 49b77400..4825b75b 100644 --- a/logic/service/fight/info/info.go +++ b/logic/service/fight/info/info.go @@ -171,7 +171,8 @@ func (t *NoteReadyToFightInfo) onBothFinished() { // ReadyFightPetInfo 准备战斗的精灵信息结构体,ReadyFightPetInfo类 type ReadyFightPetInfo struct { // 精灵ID,@UInt long - ID uint32 `fieldDesc:"精灵ID" ` + ID uint32 `fieldDesc:"精灵ID" ` + NotAlive bool `struc:"skip"` // 精灵等级,@UInt long Level uint32 `fieldDesc:"精灵等级" ` diff --git a/logic/service/fightc.go b/logic/service/fightc.go index 5fed836e..9271725d 100644 --- a/logic/service/fightc.go +++ b/logic/service/fightc.go @@ -35,11 +35,12 @@ type FightC struct { OurCurrentPet *info.BattlePetEntity //我方精灵 Opp PlayerI OppCurrentPet *info.BattlePetEntity //对方当前精灵 - MAXPET uint32 // 最大精灵数 - OwnerID uint32 // 战斗发起者ID - AFinished bool - BFinished bool - //random *rand.Rand //随机数种子 + + MAXPET uint32 // 最大精灵数 + OwnerID uint32 // 战斗发起者ID + AFinished bool + BFinished bool + random *rand.Rand //随机数种子 StartTime time.Time actionChan chan info.BattleActionI // 所有操作统一从这里进入 Round int //回合数 @@ -65,23 +66,25 @@ func (f *FightC) ChangePet(c PlayerI, id int32) { PlayerID: c.ID(), } - rett := func(t PlayerI) { + rett := func(t PlayerI) *info.BattlePetEntity { for _, v := range t.GetPetInfo() { if v.CatchTime == uint32(id) { - f.OurCurrentPet = info.CreateBattlePetEntity(v, f.Random()) //存入自己的精灵信息 + fs := info.CreateBattlePetEntity(v, f.Random()) //存入自己的精灵信息 copier.Copy(&ret.Reason, &v) ret.Reason.UserId = c.ID() + return fs } } + return nil } if c == f.Our { - rett(f.Our) + f.OurCurrentPet = rett(f.Our) } else { - rett(f.Opp) + f.OppCurrentPet = rett(f.Opp) } f.actionChan <- ret } @@ -152,13 +155,14 @@ func (f *FightC) ReadyFight(c PlayerI) { rrsult() } } -func (f *FightC) Random() *rand.Source { +func (f *FightC) Random() *rand.Rand { //先产生战斗的随机数 // 组合「时间戳(纳秒精度)+ 双方ID + 回合数」生成种子 seed := f.StartTime.UnixNano() ^ int64(f.OwnerID) ^ int64(f.Our.ID()) ^ int64(f.Round) // 用异或运算混合多维度信息 - ret := rand.NewSource(seed) - return &ret + ret := rand.New(rand.NewSource(seed)) + + return ret } @@ -176,7 +180,15 @@ func (f *FightC) NewFight(i *info.NoteReadyToFightInfo, plays PlayerI, mo *model f.Info = i f.StartTime = time.Now() f.actionChan = make(chan info.BattleActionI, 2) // 初始化全局操作通道 - f.OurCurrentPet = info.CreateBattlePetEntity(plays.GetPetInfo()[0], f.Random()) + fmt.Println("战斗开始精灵", plays.GetPetInfo()[0].CatchTime) + + for _, v := range plays.GetPetInfo() { + if v.Hp > 0 { + f.OurCurrentPet = info.CreateBattlePetEntity(plays.GetPetInfo()[0], f.Random()) + } + } + // } + // f.OurCurrentPet = info.CreateBattlePetEntity(plays.GetPetInfo()[0], f.Random()) if mo != nil { f.OppCurrentPet = info.CreateBattlePetEntity(mo, f.Random()) } @@ -222,12 +234,47 @@ func (f *FightC) BroadcastSkill(t info.AttackValueS) { f.Opp.SendAttackValue(t) } +// 检查战斗是否结束 +func (f *FightC) CheakEnd(b uint32) bool { + fmt.Println(f.Round, "检查战斗是否结束") + var tt []info.ReadyFightPetInfo + for _, v := range f.Info.OurPetList { + if v.CatchTime == b { + v.NotAlive = true + + } + tt = append(tt, v) + } + f.Info.OurPetList = tt + var tt1 []info.ReadyFightPetInfo + for _, v := range f.Info.OpponentPetList { + if v.CatchTime == b { + v.NotAlive = true + + } + tt1 = append(tt1, v) + } + f.Info.OpponentPetList = tt1 + for _, v := range f.Info.OurPetList { + if !v.NotAlive { + return false + } + + } + for _, v := range f.Info.OpponentPetList { + if !v.NotAlive { + return false + } + } + return true +} + // 战斗回合循环 func (f *FightC) battleLoop() { for { + f.Round++ //回合数自增 - // f.AFinished = false - // f.BFinished = false + if f.Round > 250 { //回合数超过250,战斗平局结束 } @@ -242,7 +289,7 @@ func (f *FightC) battleLoop() { continue } if a, isExpelled := action.(*info.ActiveSwitchAction); isExpelled { - fmt.Println("对方死亡切换") + //fmt.Println("对方死亡切换") f.Broadcast(a) if !a.Type { continue @@ -295,8 +342,20 @@ func (f *FightC) battleLoop() { } var p_skill [2]*info.SelectSkillAction + var currpet [2]*info.BattlePetEntity + var currpetvale [2]int // 伤害值 + if BattleActionI[0].GetPlayerID() == f.OwnerID { //先反转战斗属性 + currpet[0] = f.OurCurrentPet + currpet[1] = f.OppCurrentPet + + } else { + currpet[0] = f.OppCurrentPet + currpet[1] = f.OurCurrentPet + } + fmt.Println("当前", currpet[0].Info.CatchTime, "敌方", currpet[1].Info.CatchTime) for i := 0; i < 2; i++ { + // TODO: 在这里调用技能结算逻辑 p_skill[i] = BattleActionI[i].(*info.SelectSkillAction) @@ -321,41 +380,65 @@ func (f *FightC) battleLoop() { } } + spower := p_skill[i].Skill.CalculatePower(currpet[i].Type().ID) //开始计算技能效果battleLoop + _, ok := p_skill[i].Skill.CriticalRate() + //CalculatePower() + //记录伤害,到后手方出手时计算伤害 + currpetvale[i] = int(spower) + fmt.Println("技能伤害", spower, "剩余血量", currpet[i].Info.Hp) p_skill[i].Attack = info.AttackValue{ p_skill[i].PlayerID, uint32(p_skill[i].Skill.ID), - 1, - 200, + p_skill[i].Skill.CriticalisCritical(), + spower, 0, - int32(f.OurCurrentPet.Info.MaxHp), - f.OurCurrentPet.Info.MaxHp, + int32(currpet[i].Info.Hp), + currpet[i].Info.MaxHp, 0, 0, []model.SkillInfo{}, - 1, + ok, info.StatusDict{}, info.PropDict{}, } } - p_skill[1].Attack = info.AttackValue{ - p_skill[1].PlayerID, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - []model.SkillInfo{}, - 0, - info.StatusDict{}, - info.PropDict{}, + p_skill[0].Attack.RemainHp = int32(int(currpet[0].Info.Hp) - currpetvale[1]) + currpet[0].Info.Hp = uint32(p_skill[0].Attack.RemainHp) + p_skill[1].Attack.RemainHp = int32(int(currpet[1].Info.Hp) - currpetvale[0]) + currpet[1].Info.Hp = uint32(p_skill[1].Attack.RemainHp) + if p_skill[1].Attack.RemainHp <= 0 { //如果后手方被打死 + p_skill[1].Attack = info.AttackValue{ + p_skill[1].PlayerID, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + []model.SkillInfo{}, + 0, + info.StatusDict{}, + info.PropDict{}, + } + fmt.Println(currpet[1].Info.CatchTime, "被打死") + if f.CheakEnd(currpet[1].Info.CatchTime) { + break + } } + + if p_skill[0].Attack.RemainHp <= 0 { + + if f.CheakEnd(currpet[0].Info.CatchTime) { + break + } + } + fmt.Println("P1", p_skill[0].Attack.RemainHp, "P2", p_skill[1].Attack.RemainHp) f.BroadcastSkill(info.AttackValueS{ p_skill[0].Attack, p_skill[1].Attack, })