Compile-driven bulk-copy loop (tools/engine-port/m1_copy_loop.py) pulled the precise reference closure of the battle-core roots, stopping at the classify god-object/View-VFX-UI boundary. 782 files; no re-explosion (M0 had estimated ~order 1000). Residual frontier = 52 shim-classified + 80 external (Unity/BCL) types to author next.
215 lines
4.5 KiB
C#
215 lines
4.5 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Wizard;
|
|
|
|
public class AIEmoteQuery
|
|
{
|
|
public enum Category
|
|
{
|
|
UnexpectedPlayResult_Good = 1,
|
|
UnexpectedPlayResult_Bad = 2,
|
|
LongThinking = 3,
|
|
UnexpectedBattleResult = 11,
|
|
ReverseDisAdv = 12,
|
|
CheckMated = 13,
|
|
HuntDown = 14,
|
|
RemainTooPP = 15,
|
|
SpellBanishOverExpected = 21,
|
|
FatalAttack = 22,
|
|
OpponentRemainTooPP = 31,
|
|
OpponentReverseDisAdvFail = 32,
|
|
OpponentGetGreatMerit = 33,
|
|
OpponentPlayGiant = 34,
|
|
OpponentBanishSpell_Good = 35,
|
|
OpponentBanishSpell_Bad = 36,
|
|
OpponentWellHealing = 37,
|
|
EliminatedAllyLegion = 101,
|
|
EnoughUnit = 102,
|
|
Awake = 401,
|
|
EnoughGrave = 501
|
|
}
|
|
|
|
private EnemyAI enemyAI;
|
|
|
|
private bool _isActivate = true;
|
|
|
|
private AIEmoteSet _curEmoteSet;
|
|
|
|
private bool _emotePermission;
|
|
|
|
private bool _useInnerEmote;
|
|
|
|
private Queue<int> _previousEmoteQueue;
|
|
|
|
private Queue<int> _previousPlayerEmoteQueue;
|
|
|
|
private Dictionary<int, int> _categoryIntervalDic;
|
|
|
|
private const int EMOTE_QUEUE_LENGTH = 3;
|
|
|
|
public bool UseInnerEmote => _useInnerEmote;
|
|
|
|
public AIEmoteQuery(EnemyAI ai)
|
|
{
|
|
enemyAI = ai;
|
|
_emotePermission = true;
|
|
_useInnerEmote = false;
|
|
_previousEmoteQueue = new Queue<int>(3);
|
|
_previousPlayerEmoteQueue = new Queue<int>(3);
|
|
_categoryIntervalDic = new Dictionary<int, int>();
|
|
}
|
|
|
|
public void SetOnOffEmote(bool isActivate, bool useInnerEmote)
|
|
{
|
|
_isActivate = isActivate;
|
|
_useInnerEmote = useInnerEmote;
|
|
}
|
|
|
|
public void SetEmoteSet(AIEmoteSet emoteSet)
|
|
{
|
|
_curEmoteSet = emoteSet;
|
|
}
|
|
|
|
public void UpdateCategoryInterval()
|
|
{
|
|
foreach (int item in new List<int>(_categoryIntervalDic.Keys))
|
|
{
|
|
int num = _categoryIntervalDic[item];
|
|
if (num > 0)
|
|
{
|
|
_categoryIntervalDic[item] = num - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetInterval(int emoteKey, int turnCount)
|
|
{
|
|
if (_categoryIntervalDic.ContainsKey(emoteKey))
|
|
{
|
|
_categoryIntervalDic[emoteKey] = turnCount;
|
|
}
|
|
else
|
|
{
|
|
_categoryIntervalDic.Add(emoteKey, turnCount);
|
|
}
|
|
}
|
|
|
|
public int GetCategoryInterval(int emoteKey)
|
|
{
|
|
if (!_categoryIntervalDic.ContainsKey(emoteKey))
|
|
{
|
|
return 0;
|
|
}
|
|
return _categoryIntervalDic[emoteKey];
|
|
}
|
|
|
|
public AIEmoteCmd SearchEmoteAtRandom(int emoteKey, bool isAlly = true)
|
|
{
|
|
if (!_isActivate)
|
|
{
|
|
return null;
|
|
}
|
|
if (_curEmoteSet == null)
|
|
{
|
|
return null;
|
|
}
|
|
if (!_curEmoteSet.EmoteCmds.Any((AIEmoteCmd c) => c.CategoryKey == emoteKey))
|
|
{
|
|
return null;
|
|
}
|
|
if (!_emotePermission)
|
|
{
|
|
return null;
|
|
}
|
|
if (!_useInnerEmote && emoteKey <= 1000)
|
|
{
|
|
return null;
|
|
}
|
|
AIEmoteCmd aIEmoteCmd = null;
|
|
IList<AIEmoteCmd> list = FilterEmoteByPreviousPlayed(_curEmoteSet.EmoteCmds.Where((AIEmoteCmd c) => c.CategoryKey == emoteKey), isAlly);
|
|
int count = list.Count;
|
|
if (count <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
if (count > 1)
|
|
{
|
|
int index = enemyAI.AIStableRandom() % count;
|
|
aIEmoteCmd = list[index];
|
|
}
|
|
else
|
|
{
|
|
aIEmoteCmd = list[0];
|
|
}
|
|
if (aIEmoteCmd != null)
|
|
{
|
|
Queue<int> queue = (isAlly ? _previousEmoteQueue : _previousPlayerEmoteQueue);
|
|
if (queue.Count == 3)
|
|
{
|
|
queue.Dequeue();
|
|
}
|
|
queue.Enqueue(aIEmoteCmd.ID);
|
|
aIEmoteCmd.isAI = isAlly;
|
|
}
|
|
return aIEmoteCmd;
|
|
}
|
|
|
|
public AIEmoteCmd SearchEmoteByID(int emoteID)
|
|
{
|
|
if (_curEmoteSet == null)
|
|
{
|
|
return null;
|
|
}
|
|
if (!_curEmoteSet.EmoteCmds.Any((AIEmoteCmd c) => c.ID == emoteID))
|
|
{
|
|
return null;
|
|
}
|
|
return _curEmoteSet.EmoteCmds.First((AIEmoteCmd c) => c.ID == emoteID);
|
|
}
|
|
|
|
public IEnumerable<AIEmoteCmd> SearchEmoteByCategory(int emoteCategory)
|
|
{
|
|
if (_curEmoteSet == null)
|
|
{
|
|
return null;
|
|
}
|
|
if (!_curEmoteSet.EmoteCmds.Any((AIEmoteCmd c) => c.CategoryKey == emoteCategory))
|
|
{
|
|
return null;
|
|
}
|
|
return _curEmoteSet.EmoteCmds.Where((AIEmoteCmd c) => c.CategoryKey == emoteCategory);
|
|
}
|
|
|
|
public void OnOperation()
|
|
{
|
|
_emotePermission = true;
|
|
}
|
|
|
|
public void OnCardPlayEmotion()
|
|
{
|
|
_emotePermission = false;
|
|
}
|
|
|
|
private IList<AIEmoteCmd> FilterEmoteByPreviousPlayed(IEnumerable<AIEmoteCmd> emoteCmds, bool isAlly)
|
|
{
|
|
IList<AIEmoteCmd> list = new List<AIEmoteCmd>();
|
|
Queue<int> queue = (isAlly ? _previousEmoteQueue : _previousPlayerEmoteQueue);
|
|
foreach (AIEmoteCmd emoteCmd in emoteCmds)
|
|
{
|
|
if (queue.Contains(emoteCmd.ID))
|
|
{
|
|
if (enemyAI.AIStableRandom() % 4 == 0)
|
|
{
|
|
list.Add(emoteCmd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
list.Add(emoteCmd);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
}
|