上传战斗相关逻辑

This commit is contained in:
liwei1dao 2022-09-13 17:59:40 +08:00
parent 5f0c222a21
commit ddb6879c02
15 changed files with 359 additions and 161 deletions

View File

@ -37,6 +37,10 @@ type AttributeNumeric struct {
BuffProValue *FixedNumeric BuffProValue *FixedNumeric
} }
func (this *AttributeNumeric) Value() float32 {
return this.fixedValue.Scalar()
}
func (this *AttributeNumeric) SetBase(value float32) float32 { func (this *AttributeNumeric) SetBase(value float32) float32 {
this.BaseValue.Set(value) this.BaseValue.Set(value)
this.onChange() this.onChange()

View File

@ -1,105 +1,79 @@
package component package component
import ( import "go_dreamfactory/modules/battle/fight/attribute"
"go_dreamfactory/modules/battle/fight/attribute"
)
type FightRoleData struct { type FightRoleData struct {
//基础属性---------------------------------------------------------------------------------------------------------------------------
/// <summary>
/// 角色名
/// </summary>
Name string
/// <summary> /// <summary>
/// 阵营 1=我 2=敌 /// 阵营 1=我 2=敌
/// </summary> /// </summary>
Side byte Side byte
/// <summary> /// <summary>
/// 种族 1灼热, 2涌动, 3呼啸, 4闪耀
/// </summary>
Race byte
/// <summary>
/// 站位 1~5
/// </summary>
Pos byte
/// <summary>
/// 唯一标记同时也是List FightBase.Roles的索引 /// 唯一标记同时也是List FightBase.Roles的索引
/// </summary> /// </summary>
Rid byte Rid byte
/// <summary>
/// 是否活着
/// </summary>
ALive bool
/// <summary>
/// 是否队长
/// </summary>
Captain bool
/// <summary>
/// 队长技 id
/// </summary>
CaptainSkillId int
/// <summary>
/// 英雄ID
/// </summary>
HeroID string
//战斗属性--------------------------------------------------------------------------------------------------------------------------- //region 战斗属性
/// <summary> /// <summary>
/// 行动值 /// 行动值
/// </summary> /// </summary>
Operate attribute.AttributeNumeric Operate *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 最大生命 /// 最大生命
/// </summary> /// </summary>
MaxHp attribute.AttributeNumeric MaxHp *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 当前生命 /// 当前生命
/// </summary> /// </summary>
Hp attribute.AttributeNumeric Hp *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 攻击 /// 攻击
/// </summary> /// </summary>
Atk attribute.AttributeNumeric Atk *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 防御 /// 防御
/// </summary> /// </summary>
Def attribute.AttributeNumeric Def *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 速度 /// 速度
/// </summary> /// </summary>
Speed attribute.AttributeNumeric Speed *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 暴击率 /// 暴击率
/// </summary> /// </summary>
Critical attribute.AttributeNumeric Critical *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 暴击伤害 /// 暴击伤害
/// </summary> /// </summary>
CriticalPower attribute.AttributeNumeric CriticalPower *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 效果命中 /// 效果命中
/// </summary> /// </summary>
EffectHit attribute.AttributeNumeric EffectHit *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 效果抵抗 /// 效果抵抗
/// </summary> /// </summary>
EfectResist attribute.AttributeNumeric EfectResist *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 失手率 /// 失手率
/// </summary> /// </summary>
LostHold attribute.AttributeNumeric LostHold *attribute.AttributeNumeric
/// <summary> /// <summary>
/// 会心率 /// 会心率
/// </summary> /// </summary>
UnderStand attribute.AttributeNumeric UnderStand *attribute.AttributeNumeric
/// <summary>
/// 最后一次skillAtk技能选择的目标
/// </summary>
LastChooseTarget []byte
} }

View File

@ -0,0 +1,138 @@
package core
import "go_dreamfactory/modules/battle/fight/component"
type (
///战斗控制器
IFight interface {
GetRoles() []IFightRole
/// 战前逻辑
BeforeStart()
///开始战斗
StartFight()
/// 开始一个回合
TurnRound()
/// 校验战斗结束
CheckFightEnd()
/// <summary>
/// 获取行动角色
/// 计算当前可以行动的角色没有时返回null
/// </summary>
GetActionRole() IFightRole
/// 增加一个参战角色
AddRole(role IFightRole)
/// 触发队长技队长技配置在atk表中触发顺序无所谓
EmitCaptainSkill()
/// <summary>
/// LastActionRole触发SkillId技能选择的目标是TargetRid
/// 手动时,表现层在玩家操作后,调用本方法
/// 自动战斗或服务端里通过FightAI逻辑来自动触发
/// </summary>
/// <param name="skillid">技能ID</param>
/// <param name="targetRid">选择的目标rid</param>
EmitSkill(skillId int32, targetRid []int32)
}
//战斗角色
IFightRole interface {
GetData() component.FightRoleData
/// 获取行动令牌
StartAction()
/// 结束行动令牌
StopAction()
/// 修改行动值
ModifyOperateValue(newNum float32)
///接收伤害
ReceiveDamage(damageValue float32) int
/// 是否致死伤害
WillDead(damageValue float32) bool
/// 接收治疗
ReceiveCure(cureValue float32) int
/// <summary>
/// 当前是否能进行攻击行为
/// 如果有行动类控制buff如昏迷冰冻等则不能攻击
/// </summary>
CanAtk() bool
/// 是否死亡
IsDead() bool
/// 获取下一个技能id
GetNextSkillId() int32
/// 获取后续子技能
GetAfterAtk(skillId int) ISkil
/// 触发SkillId技能选择的目标是TargetRid
EmitSkill(skillId int32, targetRid []int32)
/// 自身的 Buff 和 被动 是否有指定标签
HasTag(pTag string) bool
///战斗结束清理
Clear()
}
//AI
IFightAI interface {
/// 自动触发技能
AutoEmitSkill(pFightRole IFightRole)
}
//技能对象
ISkil interface {
/// <summary>
/// 触发
/// 遍历所有ChildSkills生成对应的实例并Emit触发
/// </summary>
Emit()
/// <summary>
/// 减少CD回合数
/// </summary>
/// <returns>新的回合数</returns>
MinusCD() int32
/// <summary>
/// 增加CD回合数
/// </summary>
/// <returns>新的回合数</returns>
ResetCD() int32
/// <summary>
/// 设置CD回合数为新的值
/// </summary>
/// <param name="newVal"></param>
/// <returns></returns>
SetCD(newVal byte) int32
/// <summary>
/// 战斗结束时的清理
/// </summary>
Clear()
}
//Buff对象
IBuff interface {
/// 激活Buff
Activate()
/// 结束Buff
End()
/// 增加CD回合数
AddCD(pVal int32) int32
/// 减少CD回合数
MinusCD(pVal int32) int32
/// 设置CD回合数为新的值
SetCD(newVal int32) int32
/// <summary>
/// 是否存在指定Tag
/// </summary>
HasTag(pTag string) bool
/// 战斗结束时的清理
Clear()
}
///事件管理
IFightEvent interface {
//发送事件
EmitForInt(eventNumber int, args ...interface{})
//发送事件
EmitForStr(eventName string, args ...interface{})
/// 监听消息
OnForStr(eventName string, f interface{})
/// 监听消息
OnForInt(eventNumber int, f interface{})
/// 移除监听消息
OffForStr(eventName string, f interface{})
/// 移除监听消息
OffForInt(eventNumber int, f interface{})
}
)

View File

@ -1,4 +1,4 @@
package fight package core
import "fmt" import "fmt"
@ -164,8 +164,8 @@ const (
type EOrderType int8 type EOrderType int8
const ( const (
Asc EOrderType = iota EOrderType_Asc EOrderType = iota
Desc EOrderType_Desc
) )
type ComModifyOperate struct { type ComModifyOperate struct {

View File

@ -1,4 +1,20 @@
package fight package fight
import "go_dreamfactory/modules/battle/fight/core"
type FightAI struct { type FightAI struct {
fight core.IFight
}
/// <summary>
/// 自动触发技能
/// </summary>
func (this *FightAI) AutoEmitSkill(pFightRole core.IFightRole) {
//todo...根据规则,设置对应技能和目标
skillid := pFightRole.GetNextSkillId() // fightRole.Data.SkillsInfo.Keys.ToArray()[0];
//临时,随机取一个敌人
targets := FightTargetFrom(this.fight.GetRoles(), pFightRole, int32(core.AferSkillFromType_Enemy))
// FightBase.EmitSkill(skillid, new int[] { targets[0].Data.Rid }) ;
this.fight.EmitSkill(skillid, []int32{int32(targets[0].GetData().Rid)})
} }

View File

@ -1,81 +1,80 @@
package fight package fight
func NewFightBase() *FightBase { import (
return &FightBase{} "go_dreamfactory/modules/battle/fight/core"
} )
/// <summary>
/// 每场战斗需要new一个类因为客户端有同时进行多场战斗的需求所以这里不能是单例
/// </summary>
type FightBase struct { type FightBase struct {
/// <summary> /// 战斗控制器
fight core.IFight
/// 战斗类型 /// 战斗类型
/// </summary> fightType core.FightType
fightType FightType
/// <summary>
/// 战斗是否进行中 /// 战斗是否进行中
/// </summary>
fightIng bool fightIng bool
/// <summary>
/// 所有参战角色集合 /// 所有参战角色集合
/// </summary> Roles []core.IFightRole
Roles []*FightRole
/// <summary>
/// 当前回合满足行动值大于等于100的所有角色 /// 当前回合满足行动值大于等于100的所有角色
/// </summary> CanAtkRoles []core.IFightRole
CanAtkRoles []*FightRole
/// <summary>
/// 最后一次攻击的角色 /// 最后一次攻击的角色
/// </summary> LastActionRole core.IFightRole
LastActionRole FightRole
/// <summary>
/// 是否自动战斗
/// </summary>
AutoFight bool
/// <summary>
/// 战斗AI /// 战斗AI
/// </summary> FightAI core.IFightAI
FightAI FightAI ///事件系统
/// <summary> FightEvent core.IFightEvent
/// 随机数种子 }
/// </summary>
RandSeed int64
/// <summary>
/// 事件系统
/// </summary>
FightEvent IFightEvent
/// <summary>
/// 战报
/// </summary>
FightLog FightLog
/// <summary> /// 开始战斗
/// 是否可进入下个循环 func (this *FightBase) StartFight() {
/// </summary> //战斗开始事件触发
/// <remarks> this.FightEvent.EmitForInt(int(core.EventType_OnFightStart))
/// 客户端专用逻辑 ///战斗开始触发
/// </remarks> this.fight.BeforeStart()
ToNextRound bool ///触发队长技
this.fight.EmitCaptainSkill()
///初始化参战角色行动值
this.InitRoleOperateValue()
///开始新的回合
this.fight.TurnRound()
}
/// 开始一个回合
func (this *FightBase) TurnRound() {
//获取当前出手的角色
actionRole := this.fight.GetActionRole()
if actionRole != nil {
//开始行动
actionRole.StartAction()
if actionRole.CanAtk() {
this.FightEvent.EmitForInt((int)(core.EventType_OnRoundStart), actionRole)
//自动战斗逻辑
this.FightAI.AutoEmitSkill(actionRole)
}
} else {
}
} }
/// <summary> /// <summary>
/// 开始战斗 /// 初始化所有角色的行动值
/// </summary> /// </summary>
func (this *FightBase) StartFight() { func (this *FightBase) InitRoleOperateValue() {
this.fightIng = true
// FightDebug.Log("=========开始战斗=========") }
//记录战报 /// <summary>
// var com = new(ComStartFight) /// 排序所有角色
// FightLog.AddCommand(com) /// </summary>
//不直接用enum防止装箱拆箱 /// <param name="orderBy">排序方式</param>
this.FightEvent.Emit(int(EventType_OnFightStart)) /// <param name="orderType">升序还是降序asc/desc </param>
func (this *FightBase) Order(orderBy string, pOrder core.EOrderType) {
// BeforeStart() if len(this.Roles) <= 1 {
// EmitCaptainSkill() return
// EmitPassiveSkillSkill() }
// //todo...符文技??
// InitRoleOperateValue() // if (pOrder == core.EOrderType_Asc){
// TurnRound()
// }
// else{
// }
} }

View File

@ -1,17 +1,5 @@
package fight package fight
type IFightEvent interface {
Emit(eventNumber int, args ...interface{})
}
type FightEvent struct { type FightEvent struct {
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="eventNumber"></param>
/// <param name="args"></param>
func (this *FightEvent) Emit(eventNumber int, args ...interface{}) {
}

View File

@ -1,14 +0,0 @@
package fight
type FightLog struct {
Commands []interface{}
}
/// <summary>
/// 增加战报日志
/// </summary>
/// <param name="log"></param>
func (this *FightLog) AddCommand(log interface{}) {
//FightDebug.Log($"<color=#35ff02>战报:{log.ToString()}</color>");
// this.Commands = app
}

View File

@ -1,7 +0,0 @@
package fight
import "go_dreamfactory/modules/battle/fight/component"
type FightRole struct {
Data component.FightRoleData
}

View File

@ -1,7 +1,102 @@
package fight package fight
import "go_dreamfactory/modules/battle/fight/core"
/// <summary> /// <summary>
/// 子技能目标选择 /// 从roles里过滤出符合设定的对象List
/// </summary> /// </summary>
type FightTarget struct { /// <param name="roles">筛选前List<FightRole></param>
/// <param name="actionRole">当前行动role</param>
/// <param name="from">afterSkill里设置的From</param>
/// <returns></returns>
func FightTargetFrom(roles []core.IFightRole, actionRole core.IFightRole, from int32) []core.IFightRole {
switch from {
case int32(core.AferSkillFromType_All):
// 选所有
return roles
case int32(core.AferSkillFromType_Friend):
// 只选友方
result := make([]core.IFightRole, 0)
// roles.FindAll(role => role.Data.Side == actionRole.Data.Side);
for _, v := range roles {
if v.GetData().Side == actionRole.GetData().Side {
result = append(result, v)
}
}
return result
case int32(core.AferSkillFromType_Enemy):
// 只选敌方
// return roles.FindAll(role => role.Data.Side != actionRole.Data.Side);
// 只选友方
result := make([]core.IFightRole, 0)
// roles.FindAll(role => role.Data.Side == actionRole.Data.Side);
for _, v := range roles {
if v.GetData().Side != actionRole.GetData().Side {
result = append(result, v)
}
}
return result
case int32(core.AferSkillFromType_Self):
// 只选自己
return []core.IFightRole{actionRole}
case int32(core.AferSkillFromType_PlayerChoose):
// 只选skillAtk里选择的目标
// return roles.FindAll(role => actionRole.Data.LastChooseTarget.Contains(role.Data.Rid));
result := make([]core.IFightRole, 0)
// roles.FindAll(role => role.Data.Side == actionRole.Data.Side);
for _, v := range roles {
for _, v1 := range actionRole.GetData().LastChooseTarget {
if v.GetData().Rid == v1 {
result = append(result, v)
break
}
}
}
return result
case int32(core.AferSkillFromType_FriendExceptSelf):
// 除自己外的友方
// return roles.FindAll(role => role.Data.Side == actionRole.Data.Side && role != actionRole);
result := make([]core.IFightRole, 0)
// roles.FindAll(role => role.Data.Side == actionRole.Data.Side);
for _, v := range roles {
if v.GetData().Side == actionRole.GetData().Side && v != actionRole {
result = append(result, v)
}
}
return result
case int32(core.AferSkillFromType_EnemyExceptChoose):
// 除选定目标外的其他敌方
// return roles.FindAll(role => role.Data.Side != actionRole.Data.Side && !actionRole.Data.LastChooseTarget.Contains(role.Data.Rid));
result := make([]core.IFightRole, 0)
for _, v := range roles {
if v.GetData().Side != actionRole.GetData().Side {
for _, v1 := range actionRole.GetData().LastChooseTarget {
if v.GetData().Rid == v1 {
result = append(result, v)
break
}
}
}
}
return result
case int32(core.AferSkillFromType_FriendExceptChoose):
// 除选定目标外的其他敌方
// return roles.FindAll(role => role.Data.Side != actionRole.Data.Side && !actionRole.Data.LastChooseTarget.Contains(role.Data.Rid));
result := make([]core.IFightRole, 0)
for _, v := range roles {
if v.GetData().Side != actionRole.GetData().Side {
for _, v1 := range actionRole.GetData().LastChooseTarget {
if v.GetData().Rid == v1 {
result = append(result, v)
break
}
}
}
}
return result
// 除选定目标外的其他友方
// return roles.FindAll(role => role.Data.Side == actionRole.Data.Side && !actionRole.Data.LastChooseTarget.Contains(role.Data.Rid));
}
return []core.IFightRole{}
} }

View File

@ -1 +0,0 @@
package fight

View File

@ -1 +0,0 @@
package skill

View File

@ -1 +0,0 @@
package skill

View File

@ -1,10 +0,0 @@
package skill
/// <summary>
/// 主动/队长技能
/// </summary>
/// <remarks>
/// 遍历触发子技能
/// </remarks>
type FightSkill struct {
}

View File

@ -0,0 +1,18 @@
package fight
import (
"go_dreamfactory/modules/battle/fight/core"
"sort"
)
type FightRoleSlice []core.IFightRole
func (x FightRoleSlice) Len() int { return len(x) }
func (x FightRoleSlice) Less(i, j int) bool {
return x[i].GetData().Operate.Value() < x[j].GetData().Operate.Value()
}
func (x FightRoleSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x FightRoleSlice) Sort(pType string) {
sort.Sort(x)
}