战斗切精灵失效bug待修复

This commit is contained in:
2025-09-07 05:58:47 +08:00
parent 9d2de92dd6
commit e111e08638
6 changed files with 330 additions and 209 deletions

View File

@@ -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
}
}
// 全场景测试用例

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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())
}

View File

@@ -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:"精灵等级" `

View File

@@ -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,
})