253 lines
5.4 KiB
Go
253 lines
5.4 KiB
Go
package input
|
|
|
|
import "github.com/gogf/gf/v2/util/grand"
|
|
|
|
func compactSlots(slots []*Input) []*Input {
|
|
if len(slots) == 0 {
|
|
return nil
|
|
}
|
|
ret := make([]*Input, 0, len(slots))
|
|
for _, slot := range slots {
|
|
if slot == nil {
|
|
continue
|
|
}
|
|
ret = append(ret, slot)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func uniqueControllerCount(slots []*Input) int {
|
|
if len(slots) == 0 {
|
|
return 0
|
|
}
|
|
seen := make(map[uint32]struct{}, len(slots))
|
|
count := 0
|
|
for _, slot := range slots {
|
|
if slot == nil || slot.Player == nil {
|
|
continue
|
|
}
|
|
userID := slot.Player.GetInfo().UserID
|
|
if _, ok := seen[userID]; ok {
|
|
continue
|
|
}
|
|
seen[userID] = struct{}{}
|
|
count++
|
|
}
|
|
return count
|
|
}
|
|
|
|
// TeamSlots 返回当前输入所在阵营的全部有效战斗位视图。
|
|
func (our *Input) TeamSlots() []*Input {
|
|
if our == nil {
|
|
return nil
|
|
}
|
|
if len(our.Team) == 0 {
|
|
return []*Input{our}
|
|
}
|
|
return compactSlots(our.Team)
|
|
}
|
|
|
|
// TeamSlotIndex 返回当前输入在本阵营中的原始站位下标。
|
|
func (our *Input) TeamSlotIndex() int {
|
|
if our == nil || len(our.Team) == 0 {
|
|
return 0
|
|
}
|
|
for idx, teammate := range our.Team {
|
|
if teammate == our {
|
|
return idx
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// Teammates 返回队友列表,不包含自己。
|
|
func (our *Input) Teammates() []*Input {
|
|
if our == nil {
|
|
return nil
|
|
}
|
|
teammates := make([]*Input, 0, len(our.Team))
|
|
for _, teammate := range our.TeamSlots() {
|
|
if teammate == nil || teammate == our {
|
|
continue
|
|
}
|
|
teammates = append(teammates, teammate)
|
|
}
|
|
return teammates
|
|
}
|
|
|
|
// LivingTeammates 返回当前仍有存活出战精灵的队友列表。
|
|
func (our *Input) LivingTeammates() []*Input {
|
|
if our == nil {
|
|
return nil
|
|
}
|
|
teammates := make([]*Input, 0, len(our.Team))
|
|
for _, teammate := range our.Teammates() {
|
|
currentPet := teammate.CurrentPet()
|
|
if currentPet == nil || currentPet.Info.Hp == 0 {
|
|
continue
|
|
}
|
|
teammates = append(teammates, teammate)
|
|
}
|
|
return teammates
|
|
}
|
|
|
|
// HasLivingTeammate 用于快速判断当前战斗位是否还有存活队友。
|
|
func (our *Input) HasLivingTeammate() bool {
|
|
return len(our.LivingTeammates()) > 0
|
|
}
|
|
|
|
// TeamInputCount 返回当前阵营有效 input 数量。
|
|
func (our *Input) TeamInputCount() int {
|
|
return len(our.TeamSlots())
|
|
}
|
|
|
|
// OpponentInputCount 返回敌方阵营有效 input 数量。
|
|
func (our *Input) OpponentInputCount() int {
|
|
if our == nil {
|
|
return 0
|
|
}
|
|
if len(our.OppTeam) == 0 {
|
|
if our.Opp != nil {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
return len(compactSlots(our.OppTeam))
|
|
}
|
|
|
|
// IsMultiInputSide 判断当前阵营是否为多 input。
|
|
func (our *Input) IsMultiInputSide() bool {
|
|
return our.TeamInputCount() > 1
|
|
}
|
|
|
|
// IsMultiInputBattle 判断当前战斗是否包含多 input 站位。
|
|
func (our *Input) IsMultiInputBattle() bool {
|
|
if our == nil {
|
|
return false
|
|
}
|
|
return our.TeamInputCount() > 1 || our.OpponentInputCount() > 1
|
|
}
|
|
|
|
// TeamControllerCount 返回当前阵营实际操作者数量。
|
|
func (our *Input) TeamControllerCount() int {
|
|
if our == nil {
|
|
return 0
|
|
}
|
|
return uniqueControllerCount(our.TeamSlots())
|
|
}
|
|
|
|
// IsSingleControllerMultiInputSide 判断当前阵营是否为“单人控制的多 input”。
|
|
func (our *Input) IsSingleControllerMultiInputSide() bool {
|
|
return our.IsMultiInputSide() && our.TeamControllerCount() <= 1
|
|
}
|
|
|
|
// TeamSlotAt 返回指定己方站位。
|
|
func (our *Input) TeamSlotAt(index int) *Input {
|
|
if our == nil {
|
|
return nil
|
|
}
|
|
if index >= 0 && index < len(our.Team) {
|
|
return our.Team[index]
|
|
}
|
|
if index == 0 {
|
|
return our
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// OpponentSlotAt 返回指定敌方站位。
|
|
func (our *Input) OpponentSlotAt(index int) *Input {
|
|
if our == nil {
|
|
return nil
|
|
}
|
|
if index >= 0 && index < len(our.OppTeam) {
|
|
return our.OppTeam[index]
|
|
}
|
|
if index == 0 {
|
|
return our.Opp
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func nextLivingSlotIndex(slots []*Input, start int) int {
|
|
if len(slots) == 0 {
|
|
return -1
|
|
}
|
|
if start < 0 {
|
|
start = 0
|
|
}
|
|
if start >= len(slots) {
|
|
start = 0
|
|
}
|
|
|
|
availableIndex := -1
|
|
for offset := 0; offset < len(slots); offset++ {
|
|
idx := (start + offset) % len(slots)
|
|
slot := slots[idx]
|
|
if slot == nil {
|
|
continue
|
|
}
|
|
if availableIndex < 0 {
|
|
availableIndex = idx
|
|
}
|
|
current := slot.CurrentPet()
|
|
if current != nil && current.Info.Hp > 0 {
|
|
return idx
|
|
}
|
|
}
|
|
return availableIndex
|
|
}
|
|
|
|
// OpponentSlotAtOrNextLiving 返回指定敌方站位;若该目标已死亡,则顺延到下一只存活精灵。
|
|
func (our *Input) OpponentSlotAtOrNextLiving(index int) (*Input, int) {
|
|
if our == nil {
|
|
return nil, -1
|
|
}
|
|
if len(our.OppTeam) == 0 {
|
|
return our.OpponentSlotAt(index), index
|
|
}
|
|
resolvedIndex := nextLivingSlotIndex(our.OppTeam, index)
|
|
if resolvedIndex < 0 {
|
|
return nil, -1
|
|
}
|
|
return our.OppTeam[resolvedIndex], resolvedIndex
|
|
}
|
|
|
|
// RandomOpponentSlotIndex 返回一个可用的敌方站位下标,优先从存活站位中随机。
|
|
func (our *Input) RandomOpponentSlotIndex() int {
|
|
if our == nil {
|
|
return 0
|
|
}
|
|
if len(our.OppTeam) == 0 {
|
|
if our.Opp != nil {
|
|
return 0
|
|
}
|
|
return 0
|
|
}
|
|
|
|
living := make([]int, 0, len(our.OppTeam))
|
|
available := make([]int, 0, len(our.OppTeam))
|
|
for idx, opponent := range our.OppTeam {
|
|
if opponent == nil {
|
|
continue
|
|
}
|
|
available = append(available, idx)
|
|
current := opponent.CurrentPet()
|
|
if current != nil && current.Info.Hp > 0 {
|
|
living = append(living, idx)
|
|
}
|
|
}
|
|
|
|
candidates := living
|
|
if len(candidates) == 0 {
|
|
candidates = available
|
|
}
|
|
if len(candidates) == 0 {
|
|
return 0
|
|
}
|
|
if len(candidates) == 1 {
|
|
return candidates[0]
|
|
}
|
|
return candidates[grand.Intn(len(candidates))]
|
|
}
|