diff --git a/Game/AI/CoreFunction.cs b/Game/AI/CoreFunction.cs new file mode 100644 index 00000000..301530e7 --- /dev/null +++ b/Game/AI/CoreFunction.cs @@ -0,0 +1,4098 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using YGOSharp.Network; +using YGOSharp.Network.Enums; +using System.IO; +using YGOSharp.OCGWrapper.Enums; + +namespace WindBot.Game.AI +{ + /// + /// function of link ocgcore,approximately equivalent to core lua function + /// + public class CoreFunction + { + public enum ReceiveType + { + Null, + Success, + LuaError, + CoreError, + BufferError, + ClientError + + } + public byte[] Data { get; set; } + public Duel Duel { get; private set; } + public YGOClient Connection { get; private set; } + /* + If true, we can get information about all cards by CoreFunction, + including the facdedown cards and the enemy cards, which are not allowed by rules. + For certain special situations, it can be used appropriately, + such as get card information when viewing the enemy cards. + */ + public bool GodMode { get; set; } + + public ReceiveType type; + + private IList resetCards = new List(); + + private const int PLAYER_NONE = 2; + private const int PLAYER_ALL = 3; + private const int PLAYER_NULL = 4; + private const int MAX_EX_PARAMETERS = 11; + private const int LOCATION_REASON_TOFIELD = 0x1; + private static class FunctionCode + { + public enum Type + { + Card, + Duel + } + public enum Card + { + GetCode, + GetOriginalCodeRule, + GetPreviousCodeOnField, + GetUnionCount, + GetTributeRequirement, + + GetOriginalCode, + GetType, + GetOriginalType, + GetFusionType, + GetSynchroType, + GetXyzType, + GetLinkType, + GetLevel, + GetRank, + GetLink, + GetOriginalLevel, + GetOriginalRank, + GetLeftScale, + GetOriginalLeftScale, + GetRightScale, + GetOriginalRightScale, + GetCurrentScale, + GetLinkedGroupCount, + GetMutualLinkedGroupCount, + GetColumnGroupCount, + GetAttribute, + GetOriginalAttribute, + GetRace, + GetOriginalRace, + GetAttack, + GetBaseAttack, + GetTextAttack, + GetDefense, + GetBaseDefense, + GetTextDefense, + GetPreviousTypeOnField, + GetPreviousLevelOnField, + GetPreviousRankOnField, + GetPreviousAttributeOnField, + GetPreviousRaceOnField, + GetPreviousAttackOnField, + GetPreviousDefenseOnField, + GetOwner, + GetControler, + GetPreviousControler, + GetReason, + GetReasonPlayer, + GetPosition, + GetPreviousPosition, + GetBattlePosition, + GetLocation, + GetPreviousLocation, + GetSequence, + GetSummonType, + GetSummonLocation, + GetSummonPlayer, + GetDestination, + GetLeaveFieldDest, + GetTurnID, + GetFieldID, + GetRealFieldID, + GetTurnCounter, + GetMaterialCount, + GetEquipCount, + GetOverlayCount, + GetAttackedGroupCount, + GetAttackedCount, + GetAttackAnnouncedCount, + GetCardTargetCount, + GetOwnerTargetCount, + + GetFusionCode, + GetLinkCode, + + IsFusionCode, + IsLinkCode, + IsSetCard, + IsOriginalSetCard, + IsPreviousSetCard, + IsFusionSetCard, + IsLinkSetCard, + IsOriginalCodeRule, + IsCode, + IsLevel, + IsRank, + IsLink, + IsAttack, + IsDefense, + IsLinkRace, + IsFusionAttribute, + IsLinkAttribute, + + GetSynchroLevel, + GetRitualLevel, + + IsLinkMarker, + IsType, + IsFusionType, + IsSynchroType, + IsXyzType, + IsLinkType, + IsRace, + IsAttribute, + IsReason, + IsSummonType, + IsSummonLocation, + IsSummonPlayer, + IsStatus, + IsRelateToChain, + IsPosition, + IsPreviousPosition, + IsControler, + IsPreviousControler, + IsLocation, + IsPreviousLocation, + IsLevelBelow, + IsLevelAbove, + IsRankBelow, + IsRankAbove, + IsLinkBelow, + IsLinkAbove, + IsAttackBelow, + IsAttackAbove, + IsDefenseBelow, + IsDefenseAbove, + IsCanHaveCounter, + IsFusionSummonableCard, + IsSpecialSummonable, + IsAbleToHand, + IsAbleToRemoveAsCost, + IsDiscardable, + IsCanOverlay, + + GetLinkedGroup, + GetMutualLinkedGroup, + GetColumnGroup, + GetMaterial, + GetEquipGroup, + GetAttackedGroup, + GetBattledGroup, + GetCardTarget, + GetOwnerTarget, + + IsLinkState, + IsExtraLinkState, + IsAllColumn, + IsExtraDeckMonster, + IsDualState, + IsDirectAttacked, + IsRelateToBattle, + IsDisabled, + IsSummonableCard, + IsAbleToDeck, + IsAbleToExtra, + IsAbleToGrave, + IsAbleToHandAsCost, + IsAbleToDeckAsCost, + IsAbleToExtraAsCost, + IsAbleToDeckOrExtraAsCost, + IsAbleToGraveAsCost, + IsReleasable, + IsReleasableByEffect, + IsAttackable, + IsFaceup, + IsAttackPos, + IsFacedown, + IsDefensePos, + IsOnField, + IsPublic, + IsForbidden, + IsAbleToChangeControler, + IsCanChangePosition, + IsCanTurnSet, + + GetLinkedZone, + GetMutualLinkedZone, + GetFusionAttribute, + GetLinkAttribute, + GetLinkRace, + + GetReasonCard, + GetEquipTarget, + GetPreviousEquipTarget, + GetOverlayTarget, + GetFirstCardTarget, + GetBattleTarget, + + IsNotTuner, + CheckEquipTarget, + CheckUnionTarget, + IsHasCardTarget, + IsRelateToCard, + CheckFusionSubstitute, + IsCanBeBattleTarget, + IsSynchroSummonable, + + GetEffectCount, + GetFlagEffect, + GetCounter, + + IsSummonable, + IsMSetable, + IsXyzSummonable, + IsLinkSummonable, + IsXyzLevel, + GetFlagEffectLabel, + GetColumnZone, + GetOverlayGroup, + CheckRemoveOverlayCard, + IsHasEffect, + GetAttackableTarget, + + IsCanBeCardTarget, + IsCanBeDisabledByCard, + IsImmuneToCard, + IsDestructable, + + IsSSetable, + IsAbleToRemove, + IsChainAttackable, + IsControlerCanBeChanged, + IsCanAddCounter, + IsCanRemoveCounter, + + IsCanBeFusionMaterial, + IsCanBeSynchroMaterial, + IsCanBeRitualMaterial, + IsCanBeXyzMaterial, + IsCanBeLinkMaterial, + CheckUniqueOnField + + } + public enum Duel + { + GetLP, + GetTurnCount, + GetDrawCount, + GetBattleDamage, + GetLinkedZone, + GetRitualMaterial, + IsPlayerCanAdditionalSummon, + GetBattledCount, + + GetTurnPlayer, + GetCurrentChain, + GetCurrentPhase, + IsDamageCalculated, + GetAttacker, + GetAttackTarget, + CheckPhaseActivity, + IsAbleToEnterBP, + + GetDecktopGroup, + GetExtraTopGroup, + GetReleaseGroup, + GetReleaseGroupCount, + GetFusionMaterial, + IsPlayerAffectedByEffect, + IsPlayerCanDraw, + IsPlayerCanDiscardDeck, + IsPlayerCanDiscardDeckAsCost, + IsPlayerCanSSet, + IsPlayerCanSpecialSummonCount, + IsPlayerCanRelease, + IsPlayerCanSendtoHand, + IsPlayerCanSendtoGrave, + IsPlayerCanSendtoDeck, + + + GetBattleMonster, + GetFlagEffect, + GetFlagEffectLabel, + IsCanAddCounter, + IsCanRemoveCounter, + GetCounter, + IsEnvironment, + CheckLPCost, + CheckSummonedCount, + GetLocationCount, + GetUsableMZoneCount, + + GetLinkedGroup, + GetLinkedGroupCount, + GetFieldCard, + CheckLocation, + GetFieldGroup, + GetFieldGroupCount, + GetOverlayGroup, + GetOverlayCount, + + GetTributeGroup, + CheckRemoveOverlayCard, + IsPlayerCanSummon, + IsPlayerCanMSet, + IsPlayerCanSpecialSummon, + IsPlayerCanSpecialSummonMonster, + IsPlayerCanRemove + } + } + private class DataReader + { + public MemoryStream Stream { get; private set; } + public BinaryReader Packet { get; private set; } + + public DataReader(MemoryStream stream, BinaryReader packet) + { + Stream = stream; + Packet = packet; + } + public void Close() + { + Packet?.Close(); + Stream?.Close(); + } + } + + public CoreFunction(Duel duel, YGOClient connection) + { + Duel = duel; + Connection = connection; + Data = null; + GodMode = false; + } + + private DataReader GetDataReader(byte[] data) + { + if (data?.Length <= 0) return null; + MemoryStream stream = new MemoryStream(data); + BinaryReader packet = new BinaryReader(stream); + return new DataReader(stream, packet); + } + private void Close(DataReader dreader) + { + Data = null; + dreader?.Close(); + } + + /// + /// Called when determining whether a function is executing correctly + /// + public bool FunctionSuccess() + { + return type == ReceiveType.Success; + } + + private bool CheckGodMode(ClientCard card) + { + if (card == null) return false; + if (GodMode) return true; + if (card.Sequence < 0) return false; + if (card.Controller == 0) + { + if (card.Location == CardLocation.Deck) return false; + if (card.Location == CardLocation.Removed && card.IsFacedown()) return false; + return true; + + } + else + { + if (((card.Location & CardLocation.Onfield) > 0 && !card.IsFacedown()) || card.Location == CardLocation.Overlay) return true; + return false; + } + } + + private void WriteCard(BinaryWriter reply,ClientCard card) + { + RestoreCardsData(); + if (card == null) + { + reply.Write((byte)PLAYER_NONE); + } + else + { + //if (card.Sequence < 0 && GodMode) GetFieldGroup(0, (int)card.Location, (int)card.Location); + int controller = 0; + int sequence = -1; + if (GodMode && card.Sequence < 0) + { + int[] data = GetRealPosition(card, card.Location); + controller = data[0]; + sequence = data[1]; + } + else + { + controller = card.Controller; + sequence = card.Sequence; + } + reply.Write((byte)controller); + reply.Write((int)card.Location); + reply.Write(sequence); + } + } + + private int SearchCard(IList cards,ClientCard card) + { + for (int i = 0; i < cards.Count; i++) + { + if (card == cards[i]) return i; + } + return -1; + } + + private int[] GetRealPosition(ClientCard card,CardLocation loction) + { + //Controller Sequence + if (card == null) return new int[] { 0, -1 }; + int sequence = -1; + switch (loction) + { + case CardLocation.Deck: + if ((sequence = SearchCard(Duel.Fields[1].Deck, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].Deck, card)) > 0) return new int[] { 0, sequence }; + break; + case CardLocation.Hand: + if ((sequence = SearchCard(Duel.Fields[1].Hand, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].Hand, card)) > 0) return new int[] { 0, sequence }; + break; + case CardLocation.MonsterZone: + if ((sequence = SearchCard(Duel.Fields[1].MonsterZone, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].MonsterZone, card)) > 0) return new int[] { 0, sequence }; + break; + case CardLocation.SpellZone: + if ((sequence = SearchCard(Duel.Fields[1].SpellZone, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].SpellZone, card)) > 0) return new int[] { 0, sequence }; + break; + case CardLocation.Grave: + if ((sequence = SearchCard(Duel.Fields[1].Graveyard, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].Graveyard, card)) > 0) return new int[] { 0, sequence }; + break; + case CardLocation.Removed: + if ((sequence = SearchCard(Duel.Fields[1].Banished, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].Banished, card)) > 0) return new int[] { 0, sequence }; + break; + case CardLocation.Extra: + if ((sequence = SearchCard(Duel.Fields[1].ExtraDeck, card)) > 0) return new int[] { 1, sequence }; + if ((sequence = SearchCard(Duel.Fields[0].ExtraDeck, card)) > 0) return new int[] { 0, sequence }; + break; + default: + break; + } + return new int[] { 0, -1 }; + } + + private void ReadGroup(BinaryReader packet,IList cards) + { + int count = packet.ReadInt32(); + int id; + int player; + int loc; + int seq; + ClientCard rcard; + for (int i = 0; i < count; ++i) + { + id = packet.ReadInt32(); + player = Duel.GetLocalPlayer(packet.ReadByte()); + loc = packet.ReadInt32(); + seq = packet.ReadInt32(); + rcard = Duel.GetCard(player, (CardLocation)loc, seq); + UpdateCardByCore(rcard, id, player, loc, seq); + cards.Add(rcard); + } + } + + /// + /// Update card data by core,only id,player,loc,seq + /// + private void UpdateCardByCore(ClientCard rcard,int id,int player,int loc,int seq) + { + if (CheckGodMode(rcard)) + { + + if (rcard.Sequence < 0) + { + resetCards.Add(rcard); + } + rcard.SetId(id); + rcard.SetController(player); + rcard.SetLocation((CardLocation)loc); + rcard.SetSequence(seq); + } + } + + private void ReadCard(BinaryReader packet,ClientCard rcard) + { + int id = packet.ReadInt32(); + if (id == 0) return; + int player = Duel.GetLocalPlayer(packet.ReadByte()); + int loc = packet.ReadInt32(); + int seq = packet.ReadInt32(); + rcard = Duel.GetCard(player, (CardLocation)loc, seq); + UpdateCardByCore(rcard, id, player, loc, seq); + } + + /// + /// Try to manually call this function after operating the card to avoid data confusion + /// + public void RestoreCardsData() + { + if (resetCards?.Count <= 0) return; + foreach (var resetCard in resetCards) + { + resetCard.SetController(0); + resetCard.SetId(0); + resetCard.SetSequence(-1); + } + resetCards.Clear(); + } + + private bool CheckError(DataReader dreader) + { + try + { + ReceiveType receiveType = (ReceiveType)dreader.Packet.ReadInt32(); + type = receiveType; + if (receiveType != ReceiveType.Success) + { +#if DEBUG + Logger.DebugWriteLine("Handle data Error!"); + Logger.DebugWriteLine("Error Type:" + receiveType); + FunctionCode.Type func_type = (FunctionCode.Type)dreader.Packet.ReadByte(); + if (func_type == FunctionCode.Type.Card) + { + FunctionCode.Card func_code = (FunctionCode.Card)dreader.Packet.ReadUInt16(); + Logger.DebugWriteLine("Error data is:" + func_type + ":" + func_code); + } + else if (func_type == FunctionCode.Type.Duel) + { + FunctionCode.Duel func_code = (FunctionCode.Duel)dreader.Packet.ReadUInt16(); + Logger.DebugWriteLine("Error data is:" + func_type + ":" + func_code); + } +#endif + Close(dreader); + return false; + } + } + catch (Exception e) + { +#if DEBUG + Logger.DebugWriteLine("Receive Error:" + e.Message); +#endif + type = ReceiveType.BufferError; + Close(dreader); + return false; + } + return true; + } + + private void DefaultCardFunctionWrite(FunctionCode.Card functionCode,BinaryWriter reply, ClientCard card) + { + reply.Write((byte)FunctionCode.Type.Card); + reply.Write((short)functionCode); + WriteCard(reply, card); + } + + private T ClientErrorReturn(T value) + { + type = ReceiveType.ClientError; +#if DEBUG + Logger.DebugWriteLine("Parameter Error!"); + Logger.DebugWriteLine("Error Type:" + type); +#endif + return value; + } + + private IList HandleCardToDoubleInt(FunctionCode.Card functionCode, ClientCard card) + { + IList results = new List(); + if (!CheckGodMode(card)) return ClientErrorReturn(results); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode,reply, card); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return results; + int result; + for (int i = 0; i < 2; ++i) + { + result = dreader.Packet.ReadInt32(); + if (result == 0 && (functionCode == FunctionCode.Card.GetCode || + functionCode == FunctionCode.Card.GetOriginalCodeRule || + functionCode == FunctionCode.Card.GetPreviousCodeOnField)) continue; + results.Add(result); + } + Close(dreader); + return results; + } + + private int? HandleCardToInt(FunctionCode.Card functionCode, ClientCard card) + { + if (!CheckGodMode(card)) return ClientErrorReturn((int?)null); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + int result = dreader.Packet.ReadInt32(); + Close(dreader); + return result; + } + + private int? HandleIntToInt(FunctionCode.Card functionCode, ClientCard card,int parameter) + { + if (!CheckGodMode(card)) return ClientErrorReturn((int?)null); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + reply.Write((byte)parameter); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + int result = dreader.Packet.ReadInt32(); + Close(dreader); + return result; + } + + private IList HandleCardToIntEx(FunctionCode.Card functionCode, ClientCard card) + { + IList results = new List(); + if (!CheckGodMode(card)) return ClientErrorReturn(results); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return results; + int count = dreader.Packet.ReadInt32(); + int result; + for (int i = 0; i < count; ++i) + { + result = dreader.Packet.ReadInt32(); + if (result == 0) continue; + } + Close(dreader); + return results; + } + + private bool HandleCardIntIntExToBool(FunctionCode.Card functionCode, ClientCard card, int parameter, params int[] parameters) + { + if (!CheckGodMode(card)) return ClientErrorReturn(false); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + int max_parameter_count = parameters.Count() > MAX_EX_PARAMETERS ? MAX_EX_PARAMETERS : parameters.Count(); + reply.Write((parameters.Count() + 1)); + reply.Write(parameter); + for (int i = 0; i < max_parameter_count; ++i) + { + reply.Write(parameters[i]); + }; + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return false; + byte result = dreader.Packet.ReadByte(); + Close(dreader); + return result == 1 ? true : false; + } + + private bool HandleCardIntToBool(FunctionCode.Card functionCode, ClientCard card, int parameter) + { + if (!CheckGodMode(card)) return ClientErrorReturn(false); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + reply.Write(parameter); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return false; + byte result = dreader.Packet.ReadByte(); + Close(dreader); + return result == 1 ? true : false; + } + + private bool HandleCardToBool(FunctionCode.Card functionCode, ClientCard card) + { + if (!CheckGodMode(card)) return ClientErrorReturn(false); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return false; + byte result = dreader.Packet.ReadByte(); + Close(dreader); + return result == 1 ? true : false; + } + + private bool HandleDoubleCardToBool(FunctionCode.Card functionCode, ClientCard cardA, ClientCard cardB) + { + if (!CheckGodMode(cardA) || !CheckGodMode(cardB)) return ClientErrorReturn(false); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, cardA); + WriteCard(reply,cardB); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return false; + byte result = dreader.Packet.ReadByte(); + Close(dreader); + return result == 1 ? true : false; + } + + private ClientCard HandleCardToCard(FunctionCode.Card functionCode, ClientCard card) + { + ClientCard rcard = null; + if (!CheckGodMode(card)) return ClientErrorReturn(rcard); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + ReadCard(dreader.Packet, rcard); + Close(dreader); + return rcard; + } + + private object HandleDuel(FunctionCode.Duel functionCode, params object[] parameters) + { + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + reply.Write((byte)FunctionCode.Type.Duel); + reply.Write((short)functionCode); + switch (functionCode) + { + case FunctionCode.Duel.GetLP: case FunctionCode.Duel.GetTurnCount: case FunctionCode.Duel.GetDrawCount: + case FunctionCode.Duel.GetBattleDamage: case FunctionCode.Duel.GetLinkedZone:case FunctionCode.Duel.GetBattleMonster: + case FunctionCode.Duel.GetRitualMaterial: case FunctionCode.Duel.IsPlayerCanAdditionalSummon: case FunctionCode.Duel.GetBattledCount: + { + int player = (int)parameters[0]; + reply.Write((byte)player); + } + break; + case FunctionCode.Duel.GetTurnPlayer: case FunctionCode.Duel.GetCurrentChain: case FunctionCode.Duel.GetCurrentPhase: + case FunctionCode.Duel.IsDamageCalculated: case FunctionCode.Duel.GetAttacker: case FunctionCode.Duel.GetAttackTarget: + case FunctionCode.Duel.CheckPhaseActivity: case FunctionCode.Duel.IsAbleToEnterBP: + break; + case FunctionCode.Duel.GetFlagEffect: case FunctionCode.Duel.GetFlagEffectLabel: case FunctionCode.Duel.GetDecktopGroup: + case FunctionCode.Duel.GetExtraTopGroup: case FunctionCode.Duel.GetFusionMaterial: case FunctionCode.Duel.IsPlayerAffectedByEffect: + case FunctionCode.Duel.IsPlayerCanDraw: case FunctionCode.Duel.IsPlayerCanDiscardDeck: case FunctionCode.Duel.IsPlayerCanDiscardDeckAsCost: + case FunctionCode.Duel.IsPlayerCanSpecialSummonCount: + { + int player = (int)parameters[0]; + int parameter = (int)parameters[1]; + reply.Write((byte)player); + reply.Write(parameter); + } + break; + case FunctionCode.Duel.GetReleaseGroup: + case FunctionCode.Duel.GetReleaseGroupCount: + { + int player = (int)parameters[0]; + bool parameter = (bool)parameters[1]; + int bparameter = parameter ? 1 : 0; + reply.Write((byte)player); + reply.Write((byte)bparameter); + } + break; + case FunctionCode.Duel.IsCanAddCounter: + { + int player = (int)parameters[0]; + int countertype = (int)parameters[1]; + int count = (int)parameters[2]; + ClientCard c = (ClientCard)parameters[3]; + reply.Write((byte)player); + if (countertype >= 0 && count >= 0 && c != null) + { + reply.Write((byte)1); + reply.Write(countertype); + reply.Write(count); + WriteCard(reply, c); + } + else + { + reply.Write((byte)0); + } + } + break; + case FunctionCode.Duel.IsCanRemoveCounter: + { + int player = (int)parameters[0]; + int s = (int)parameters[1]; + int o = (int)parameters[2]; + int countertype = (int)parameters[3]; + int count = (int)parameters[4]; + int reason = (int)parameters[5]; + reply.Write((byte)player); + reply.Write(s); + reply.Write(o); + reply.Write(countertype); + reply.Write(count); + reply.Write(reason); + } + break; + case FunctionCode.Duel.GetCounter: + { + int player = (int)parameters[0]; + int s = (int)parameters[1]; + int o = (int)parameters[2]; + int countertype = (int)parameters[3]; + reply.Write((byte)player); + reply.Write(s); + reply.Write(o); + reply.Write(countertype); + } + break; + case FunctionCode.Duel.IsEnvironment: + { + int code = (int)parameters[0]; + int player = (int)parameters[1]; + int loc = (int)parameters[2]; + reply.Write(code); + reply.Write((byte)player); + reply.Write(loc); + } + break; + case FunctionCode.Duel.CheckLPCost: + { + int player = (int)parameters[0]; + int cost = (int)parameters[1]; + reply.Write((byte)player); + reply.Write(cost); + } + break; + case FunctionCode.Duel.CheckSummonedCount: + case FunctionCode.Duel.GetTributeGroup: + { + ClientCard c = (ClientCard)parameters[0]; + WriteCard(reply, c); + } + break; + case FunctionCode.Duel.GetLocationCount: + { + int player = (int)parameters[0]; + int location = (int)parameters[1]; + int use_player = (int)parameters[2]; + int reason = (int)parameters[3]; + int zone = (int)parameters[4]; + reply.Write((byte)player); + reply.Write(location); + reply.Write((byte)use_player); + reply.Write(reason); + reply.Write(zone); + } + break; + case FunctionCode.Duel.GetUsableMZoneCount: + { + int player = (int)parameters[0]; + int use_player = (int)parameters[1]; + reply.Write((byte)player); + reply.Write((byte)use_player); + } + break; + case FunctionCode.Duel.GetLinkedGroup: case FunctionCode.Duel.GetLinkedGroupCount: case FunctionCode.Duel.GetFieldCard: + case FunctionCode.Duel.CheckLocation: case FunctionCode.Duel.GetFieldGroup: case FunctionCode.Duel.GetFieldGroupCount: + case FunctionCode.Duel.GetOverlayGroup: case FunctionCode.Duel.GetOverlayCount: + { + int player = (int)parameters[0]; + int parameter1 = (int)parameters[1]; + int parameter2 = (int)parameters[1]; + reply.Write((byte)player); + reply.Write(parameter1); + reply.Write(parameter2); + } + break; + case FunctionCode.Duel.CheckRemoveOverlayCard: + { + int player = (int)parameters[0]; + int s = (int)parameters[1]; + int o = (int)parameters[2]; + int count = (int)parameters[3]; + int reason = (int)parameters[4]; + reply.Write((byte)player); + reply.Write(s); + reply.Write(o); + reply.Write(count); + reply.Write(reason); + } + break; + case FunctionCode.Duel.IsPlayerCanSummon: + case FunctionCode.Duel.IsPlayerCanMSet: + { + int player = (int)parameters[0]; + int sumtype = (int)parameters[1]; + ClientCard c = (ClientCard)parameters[2]; + reply.Write((byte)player); + reply.Write(sumtype); + WriteCard(reply, c); + } + break; + case FunctionCode.Duel.IsPlayerCanSSet: + case FunctionCode.Duel.IsPlayerCanRelease: + case FunctionCode.Duel.IsPlayerCanSendtoHand: + case FunctionCode.Duel.IsPlayerCanSendtoGrave: + case FunctionCode.Duel.IsPlayerCanSendtoDeck: + { + int player = (int)parameters[0]; + ClientCard c = (ClientCard)parameters[1]; + reply.Write((byte)player); + WriteCard(reply, c); + } + break; + case FunctionCode.Duel.IsPlayerCanSpecialSummon: + { + int player = (int)parameters[0]; + int sumtype = (int)parameters[1]; + int sumpos = (int)parameters[2]; + int target_player = (int)parameters[3]; + ClientCard c = (ClientCard)parameters[4]; + reply.Write((byte)player); + reply.Write(sumtype); + reply.Write(sumpos); + reply.Write((byte)target_player); + WriteCard(reply, c); + } + break; + case FunctionCode.Duel.IsPlayerCanSpecialSummonMonster: + { + Action WriteIntOrNull = (binaryWriter, value) => + { + if (value != null) + { + binaryWriter.Write((byte)1); + binaryWriter.Write((int)value); + } + else binaryWriter.Write((byte)0); + }; + int player = (int)parameters[0]; + int code = (int)parameters[1]; + int? setcode = (int?)parameters[2]; + int? type = (int?)parameters[3]; + int? atk = (int?)parameters[4]; + int? def = (int?)parameters[5]; + int? level = (int?)parameters[6]; + int? race = (int?)parameters[7]; + int? attribute = (int?)parameters[8]; + int pos = (int)parameters[9]; + int target_player = (int)parameters[10]; + int sumtype = (int)parameters[11]; + reply.Write((byte)player); + reply.Write(code); + WriteIntOrNull(reply, setcode); + WriteIntOrNull(reply, type); + WriteIntOrNull(reply, atk); + WriteIntOrNull(reply, def); + WriteIntOrNull(reply, level); + WriteIntOrNull(reply, race); + WriteIntOrNull(reply, attribute); + reply.Write(pos); + reply.Write((byte)target_player); + reply.Write(sumtype); + } + break; + case FunctionCode.Duel.IsPlayerCanRemove: + { + int player = (int)parameters[0]; + ClientCard c = (ClientCard)parameters[1]; + int reason = (int)parameters[2]; + reply.Write((byte)player); + WriteCard(reply, c); + reply.Write(reason); + } + break; + default: + return null; + } + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + switch (functionCode) + { + case FunctionCode.Duel.GetLP: case FunctionCode.Duel.GetTurnCount: case FunctionCode.Duel.GetDrawCount: + case FunctionCode.Duel.GetTurnPlayer:case FunctionCode.Duel.GetFlagEffect: case FunctionCode.Duel.GetCounter: + case FunctionCode.Duel.GetBattleDamage: case FunctionCode.Duel.GetLocationCount: case FunctionCode.Duel.GetUsableMZoneCount: + case FunctionCode.Duel.GetLinkedGroupCount: case FunctionCode.Duel.GetLinkedZone: case FunctionCode.Duel.GetCurrentChain: + case FunctionCode.Duel.GetCurrentPhase: case FunctionCode.Duel.GetReleaseGroupCount: case FunctionCode.Duel.GetFieldGroupCount: + case FunctionCode.Duel.GetOverlayCount: case FunctionCode.Duel.GetBattledCount: + { + int result = dreader.Packet.ReadInt32(); + Close(dreader); + return result; + } + case FunctionCode.Duel.GetFlagEffectLabel: + { + IList results = new List(); + int count = dreader.Packet.ReadInt32(); + for (int i = 0; i < count; ++i) + { + results.Add(dreader.Packet.ReadInt32()); + } + Close(dreader); + return results; + } + case FunctionCode.Duel.IsCanAddCounter: case FunctionCode.Duel.IsCanRemoveCounter:case FunctionCode.Duel.IsEnvironment: + case FunctionCode.Duel.CheckLPCost: case FunctionCode.Duel.CheckSummonedCount: case FunctionCode.Duel.CheckLocation: + case FunctionCode.Duel.IsDamageCalculated: case FunctionCode.Duel.CheckRemoveOverlayCard: case FunctionCode.Duel.IsPlayerAffectedByEffect: + case FunctionCode.Duel.IsPlayerCanDraw: case FunctionCode.Duel.IsPlayerCanDiscardDeck: case FunctionCode.Duel.IsPlayerCanDiscardDeckAsCost: + case FunctionCode.Duel.IsPlayerCanSummon: case FunctionCode.Duel.IsPlayerCanMSet: case FunctionCode.Duel.IsPlayerCanSSet: + case FunctionCode.Duel.IsPlayerCanSpecialSummon: case FunctionCode.Duel.IsPlayerCanSpecialSummonMonster: case FunctionCode.Duel.IsPlayerCanSpecialSummonCount: + case FunctionCode.Duel.IsPlayerCanRelease: case FunctionCode.Duel.IsPlayerCanSendtoHand: case FunctionCode.Duel.IsPlayerCanSendtoGrave: + case FunctionCode.Duel.IsPlayerCanSendtoDeck: case FunctionCode.Duel.IsPlayerCanRemove: case FunctionCode.Duel.IsPlayerCanAdditionalSummon: + case FunctionCode.Duel.CheckPhaseActivity: case FunctionCode.Duel.IsAbleToEnterBP: + { + byte result = dreader.Packet.ReadByte(); + Close(dreader); + return result == 1 ? true : false; + } + case FunctionCode.Duel.GetLinkedGroup: case FunctionCode.Duel.GetDecktopGroup: case FunctionCode.Duel.GetExtraTopGroup: + case FunctionCode.Duel.GetReleaseGroup: case FunctionCode.Duel.GetTributeGroup: case FunctionCode.Duel.GetRitualMaterial: + case FunctionCode.Duel.GetFieldGroup: case FunctionCode.Duel.GetOverlayGroup: + { + IList results = new List(); + ReadGroup(dreader.Packet, results); + Close(dreader); + return results; + } + case FunctionCode.Duel.GetBattleMonster: + { + IList results = new List(); + ClientCard rcard = null; + byte not_null = dreader.Packet.ReadByte(); + if (not_null == 1) + { + ReadCard(dreader.Packet, rcard); + results.Add(rcard); + ReadCard(dreader.Packet, rcard); + results.Add(rcard); + Close(dreader); + return results; + } + else + { + Close(dreader); + return null; + } + } + case FunctionCode.Duel.GetFieldCard: case FunctionCode.Duel.GetAttacker: case FunctionCode.Duel.GetAttackTarget: + { + ClientCard rcard = null; + ReadCard(dreader.Packet, rcard); + Close(dreader); + return rcard; + } + case FunctionCode.Duel.GetFusionMaterial: + { + IList> results = new List>(); + results.Add(new List()); + results.Add(new List()); + ReadGroup(dreader.Packet, results[0]); + ReadGroup(dreader.Packet, results[1]); + Close(dreader); + return results; + } + default: + return null; + } + } + + private object HandleCardSpecial(FunctionCode.Card functionCode, ClientCard card, params object[] parameters) + { + if (!CheckGodMode(card)) return ClientErrorReturn(card); + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + switch (functionCode) + { + case FunctionCode.Card.IsSummonable: + case FunctionCode.Card.IsMSetable: + { + byte ignore_count = (bool)parameters[0] ? (byte)1 : (byte)0; + int minc = (int)parameters[1]; + int zone = (int)parameters[2]; + reply.Write(ignore_count); + reply.Write(minc); + reply.Write(zone); + } + break; + case FunctionCode.Card.IsXyzSummonable: + { + int minc = (int)parameters[0]; + int maxc = (int)parameters[1]; + reply.Write(minc); + reply.Write(maxc); + } + break; + case FunctionCode.Card.IsHasEffect: + { + int code = (int)parameters[0]; + int check_player = (int)parameters[1]; + reply.Write(code); + reply.Write((byte)check_player); + } + break; + case FunctionCode.Card.IsLinkSummonable: + { + ClientCard lcard = (ClientCard)parameters[0]; + int minc = (int)parameters[1]; + int maxc = (int)parameters[2]; + WriteCard(reply, lcard); + reply.Write(minc); + reply.Write(maxc); + } + break; + case FunctionCode.Card.GetFlagEffectLabel: + { + int code = (int)parameters[0]; + reply.Write(code); + } + break; + case FunctionCode.Card.GetColumnZone: + { + int location = (int)parameters[0]; + int player = (int)parameters[1]; + reply.Write(location); + reply.Write(player); + } + break; + case FunctionCode.Card.GetOverlayGroup: + case FunctionCode.Card.GetAttackableTarget: + break; + case FunctionCode.Card.CheckRemoveOverlayCard: + { + int player = (int)parameters[0]; + int count = (int)parameters[1]; + int reason = (int)parameters[2]; + reply.Write((byte)player); + reply.Write(count); + reply.Write(reason); + } + break; + case FunctionCode.Card.IsXyzLevel: + { + ClientCard xyzc = (ClientCard)parameters[0]; + if (!CheckGodMode(xyzc)) return null; + int lv = (int)parameters[1]; + WriteCard(reply,xyzc); + reply.Write(lv); + } + break; + case FunctionCode.Card.IsSSetable: + { + bool ignore_field = (bool)parameters[0]; + int b_ignore_field = ignore_field ? 1 : 0; + reply.Write((byte)b_ignore_field); + } + break; + case FunctionCode.Card.IsAbleToRemove: + { + int player = (int)parameters[0]; + int pos = (int)parameters[1]; + int reason = (int)parameters[2]; + reply.Write((byte)player); + reply.Write(pos); + reply.Write(reason); + } + break; + case FunctionCode.Card.IsChainAttackable: + { + int ac = (int)parameters[0]; + bool monsteronly = (bool)parameters[1]; + int bmonsteronly = monsteronly ? 1 : 0; + reply.Write(ac); + reply.Write((byte)bmonsteronly); + } + break; + case FunctionCode.Card.IsControlerCanBeChanged: + { + bool ignore_mzone = (bool)parameters[0]; + int zone = (int)parameters[1]; + int bignore_mzone = ignore_mzone ? 1 : 0; + reply.Write((byte)bignore_mzone); + reply.Write(zone); + } + break; + case FunctionCode.Card.IsCanAddCounter: + { + int countertype = (int)parameters[0]; + int count = (int)parameters[1]; + bool singly = (bool)parameters[2]; + int location = (int)parameters[3]; + int bsingly = singly ? 1 : 0; + reply.Write(countertype); + reply.Write(count); + reply.Write((byte)bsingly); + reply.Write(location); + } + break; + case FunctionCode.Card.IsCanRemoveCounter: + { + int player = (int)parameters[0]; + int countertype = (int)parameters[1]; + int count = (int)parameters[2]; + int reason = (int)parameters[3]; + reply.Write((byte)player); + reply.Write(countertype); + reply.Write(count); + reply.Write(reason); + } + break; + case FunctionCode.Card.IsCanBeFusionMaterial: + { + ClientCard fc = (ClientCard)parameters[0]; + int summon_type = (int)parameters[1]; + WriteCard(reply, fc); + reply.Write(summon_type); + } + break; + case FunctionCode.Card.IsCanBeSynchroMaterial: + { + ClientCard fc = (ClientCard)parameters[0]; + ClientCard tuner = (ClientCard)parameters[1]; + WriteCard(reply, fc); + WriteCard(reply, tuner); + } + break; + case FunctionCode.Card.IsCanBeRitualMaterial: + case FunctionCode.Card.IsCanBeXyzMaterial: + case FunctionCode.Card.IsCanBeLinkMaterial: + { + ClientCard sc = (ClientCard)parameters[0]; + WriteCard(reply, sc); + } + break; + case FunctionCode.Card.CheckUniqueOnField: + { + int check_player = (int)parameters[0]; + int check_location = (int)parameters[1]; + ClientCard icard = (ClientCard)parameters[2]; + reply.Write((byte)check_player); + reply.Write(check_location); + WriteCard(reply, icard); + } + break; + default: + return null; + } + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + switch (functionCode) + { + case FunctionCode.Card.IsSummonable:case FunctionCode.Card.IsMSetable: case FunctionCode.Card.IsXyzSummonable: + case FunctionCode.Card.IsLinkSummonable: case FunctionCode.Card.CheckRemoveOverlayCard: case FunctionCode.Card.IsXyzLevel: + case FunctionCode.Card.IsHasEffect: case FunctionCode.Card.IsSSetable: case FunctionCode.Card.IsAbleToRemove: + case FunctionCode.Card.IsChainAttackable: case FunctionCode.Card.IsControlerCanBeChanged: case FunctionCode.Card.IsCanAddCounter: + case FunctionCode.Card.IsCanRemoveCounter: case FunctionCode.Card.IsCanBeFusionMaterial: case FunctionCode.Card.IsCanBeSynchroMaterial: + case FunctionCode.Card.IsCanBeRitualMaterial: case FunctionCode.Card.IsCanBeXyzMaterial: case FunctionCode.Card.IsCanBeLinkMaterial: + case FunctionCode.Card.CheckUniqueOnField: + { + byte result = dreader.Packet.ReadByte(); + Close(dreader); + return result == 1 ? true : false; + } + case FunctionCode.Card.GetFlagEffectLabel: + { + IList results = new List(); + int count = dreader.Packet.ReadInt32(); + for (int i = 0; i < count; ++i) + { + results.Add(dreader.Packet.ReadInt32()); + } + Close(dreader); + return results; + } + case FunctionCode.Card.GetColumnZone: + { + int result = dreader.Packet.ReadInt32(); + Close(dreader); + return result; + } + case FunctionCode.Card.GetOverlayGroup: + { + IList cards = new List(); + int count = dreader.Packet.ReadInt32(); + int id; + int player; + int loc; + int seq; + ClientCard rcard; + for (int i = 0; i < count; ++i) + { + id = dreader.Packet.ReadInt32(); + player = Duel.GetLocalPlayer(dreader.Packet.ReadByte()); + if (player < 0 || player > 1) + { + player = GetControler(card); + } + loc = dreader.Packet.ReadInt32(); + seq = dreader.Packet.ReadInt32(); + rcard = Duel.GetCard(player, (int)((CardLocation)loc|CardLocation.MonsterZone), card.Sequence, seq); + UpdateCardByCore(rcard, id, player, loc, seq); + cards.Add(rcard); + } + Close(dreader); + return cards; + } + case FunctionCode.Card.GetAttackableTarget: + { + object[] results = new object[2]; + IList cards = new List(); + results[0] = dreader.Packet.ReadByte(); + int count = dreader.Packet.ReadInt32(); + ClientCard rcard = null; + for (int i = 0; i < count; ++i) + { + ReadCard(dreader.Packet, rcard); + cards.Add(rcard); + } + Close(dreader); + results[1] = cards; + return results; + } + default: + return null; + } + } + + private int? HandleDoubleCardToInt(FunctionCode.Card functionCode, ClientCard cardA, ClientCard cardB) + { + if (!CheckGodMode(cardA) || !CheckGodMode(cardB)) return ClientErrorReturn((int?)null); ; + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, cardA); + WriteCard(reply, cardB); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + int result = dreader.Packet.ReadInt32(); + Close(dreader); + return result; + } + + private int? HandleCardIntToInt(FunctionCode.Card functionCode, ClientCard card, int parameter) + { + if (!CheckGodMode(card)) return ClientErrorReturn((int?)null); ; + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + reply.Write(parameter); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return null; + int result = dreader.Packet.ReadInt32(); + Close(dreader); + return result; + } + + private IList HandleCardToGroup(FunctionCode.Card functionCode, ClientCard card) + { + IList cards = new List(); + if (!CheckGodMode(card)) return ClientErrorReturn(cards); ; + BinaryWriter reply = GamePacketFactory.Create(CtosMessage.AiRequest); + DefaultCardFunctionWrite(functionCode, reply, card); + Connection.Send(reply, true); + DataReader dreader = GetDataReader(Data); + if (!CheckError(dreader)) return cards; + ReadGroup(dreader.Packet, cards); + Close(dreader); + return cards; + } + + //=================== Card =================== + + /// + /// Returns the current codename for card (possibly because the effect changes) + /// 返回卡片 c 的当前卡号(可能因为效果改变) + /// + public IList GetCode(ClientCard c) + { + return HandleCardToDoubleInt(FunctionCode.Card.GetCode, c); + } + + /// + /// Returns the codename on the c rule (used as a card rule on this card) + /// 返回卡片 c 规则上的代号(这张卡规则上当作XXX使用) + /// + public IList GetOriginalCodeRule(ClientCard c) + { + return HandleCardToDoubleInt(FunctionCode.Card.GetOriginalCodeRule, c); + } + + /// + ///Returns the card number prior to the c position change + /// 返回卡片 c 位置变化之前在场上的卡号 + /// + public IList GetPreviousCodeOnField(ClientCard c) + { + return HandleCardToDoubleInt(FunctionCode.Card.GetPreviousCodeOnField, c); + } + + /// + /// Returns the number of ally cards for the current device + /// 返回卡片 c 当前装备的同盟卡数量,第二个返回值是 旧同盟 的数量 + /// + public IList GetUnionCount(ClientCard c) + { + return HandleCardToDoubleInt(FunctionCode.Card.GetUnionCount, c); + } + + /// + /// Returns the minimum and maximum number of sacrifices required to normally call c + /// 返回通常召唤卡片 c 所需要的祭品的最小和最大数量 + /// + public IList GetTributeRequirement(ClientCard c) + { + return HandleCardToDoubleInt(FunctionCode.Card.GetTributeRequirement, c); + } + + + /// + /// Returns the code number of the card in c + /// 返回卡片 c 的卡片记载的卡号 + /// + public int GetOriginalCode(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalCode, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the Type property + /// 返回卡片 c 的当前类型 + /// + public int GetType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetType, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the type of card entry for c + /// 返回卡片 c 的卡片记载的类型 + /// + public int GetOriginalType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalType, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 用作融合素材时的类型(与GetType的区别在于对于魔陷区的怪兽卡,返回其原本类型 + /// + public int GetFusionType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetFusionType, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 用作同调素材时的类型(与GetType的区别在于对于魔陷区的怪兽卡,返回其原本类型) + /// + public int GetSynchroType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetSynchroType, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 用作同调素材时的类型(与GetType的区别在于对于魔陷区的怪兽卡,返回其原本类型) + /// + public int GetXyzType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetXyzType, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 用作连接素材时的类型(与GetType的区别在于对于魔陷区的怪兽卡,返回其原本类型) + /// + public int GetLinkType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLinkType, c); + if (result == null) return 0; + return (int)result; + } + + /// + ///Returns the current level of c + /// 返回卡片 c 的当前等级 + /// + public int GetLevel(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLevel, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the current class of c + /// 返回卡片 c 的当前阶级 + /// + public int GetRank(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetRank, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 的连接标记数量 + /// + public int GetLink(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLink, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the rank of the card in c + /// 返回卡片 c 的卡片记载的等级 + /// + public int GetOriginalLevel(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalLevel, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the class of the card in c + /// 返回卡片 c 的卡片记载的阶级 + /// + public int GetOriginalRank(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalRank, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the left-hand pendulum scale of c + /// 返回卡片 c 的左灵摆刻度 + /// + public int GetLeftScale(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLeftScale, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the original left-hand pendulum scale of c + /// 返回卡片 c 的原本的左灵摆刻度 + /// + public int GetOriginalLeftScale(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalLeftScale, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the right-hand pendulum scale of c + /// 返回卡片 c 的右灵摆刻度 + /// + public int GetRightScale(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetRightScale, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the original right pendulum scale of c + /// 返回卡片 c 的原本的右灵摆刻度 + /// + public int GetOriginalRightScale(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalRightScale, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 的当前灵摆刻度若 c 在左侧的灵摆区,则返回左灵摆刻度;否则返回右灵摆刻度 + /// + public int GetCurrentScale(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetCurrentScale, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回卡片 c 的连接区的卡片组的卡的数量(目前只限怪兽区) + /// + public int GetLinkedGroupCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLinkedGroupCount, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回和卡片 c 互相连接状态的卡片组的数量 + /// + public int GetMutualLinkedGroupCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetMutualLinkedGroupCount, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// 返回与卡片 c 同一纵列的 c 以外的卡片的数量 + /// + public int GetColumnGroupCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetColumnGroupCount, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the current attribute of c + /// 返回卡片 c 的当前属性 注:对某些多属性怪兽如光与暗之龙,此函数的返回值可能是几个属性的组合值 + /// + public int GetAttribute(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetAttribute, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the attributes of the card that c is describing + /// 返回卡片 c 的卡片记载的属性 + /// + public int GetOriginalAttribute(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalAttribute, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the current race of c + /// 返回卡片 c 的当前种族 注:对某些多种族怪兽如动画效果的魔术猿,此函数的返回值可能是几个种族的组合值 + /// + public int GetRace(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetRace, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the c of the card record race + /// 返回卡片 c 的卡片记载的种族 + /// + public int GetOriginalRace(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOriginalRace, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return the current attack power of c, the return value is a negative that is "?" + /// 返回卡片 c 的当前攻击力 + /// + public int GetAttack(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetAttack, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return the original attack power of c + /// 返回卡片 c 的原本攻击力 + /// + public int GetBaseAttack(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetBaseAttack, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the attack power recorded on card c + /// 返回卡片 c 的卡片记载的攻击力,返回值是负数表示是"?" + /// + public int GetTextAttack(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetTextAttack, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return to the original c of the defense + /// Returns the current defense of c, the return value is negative that is "?" + /// + public int GetDefense(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetDefense, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return to the original c of the defense + /// 返回卡片 c 的原本守备力 + /// + public int GetBaseDefense(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetBaseDefense, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return the c 's card record of the garrison + /// 返回卡片 c 的卡片记载的守备力,返回值是负数表示是"?" + /// + public int GetTextDefense(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetTextDefense, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the type before the c position change + /// 返回卡片 c 位置变化之前在场上的类型 + /// + public int GetPreviousTypeOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousTypeOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the rank before the c position change + /// 返回卡片 c 位置变化之前在场上的等级 + /// + public int GetPreviousLevelOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousLevelOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the class before the c position changes + /// 返回卡片 c 位置变化之前在场上的阶级 + /// + public int GetPreviousRankOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousRankOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the attribute before the c position change + /// 返回卡片 c 位置变化之前在场上的属性 + /// + public int GetPreviousAttributeOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousAttributeOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the attribute before the c position change + /// 返回卡片 c 位置变化之前在场上的种族 + /// + public int GetPreviousRaceOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousRaceOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the attack power before the c position changes + /// 返回卡片 c 位置变化之前在场上的攻击力 + /// + public int GetPreviousAttackOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousAttackOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the defensive power before the c position changes + /// 返回卡片 c 位置变化之前在场上的守备力 + /// + public int GetPreviousDefenseOnField(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousDefenseOnField, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the holder of c + /// 返回卡片 c 的持有者 + /// + public int GetOwner(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOwner, c); + if (result == null) return PLAYER_NONE; + return (int)result; + } + + /// + /// Returns the current controller of c + /// 返回卡片 c 的当前控制者 + /// + public int GetControler(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetControler, c); + if (result == null) return PLAYER_NONE; + return (int)result; + } + + /// + /// Returns the controller before the position change of c + /// 返回卡片 c 的位置变化之前的控制者 + /// + public int GetPreviousControler(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousControler, c); + if (result == null) return PLAYER_NONE; + return (int)result; + } + + /// + /// Returns the position change reason for c + /// 返回卡片 c 的位置变化原因 + /// + public int GetReason(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetReason, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the player that caused the position of c to change + /// 返回导致卡片 c 的位置变化的玩家 + /// + public int GetReasonPlayer(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetReasonPlayer, c); + if (result == null) return PLAYER_NONE; + return (int)result; + } + + /// + /// Returns the current representation of c + /// 返回卡片 c 当前的表示形式 + /// + public int GetPosition(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPosition, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the representation of the position before the c position changes + /// 返回卡片 c 位置变化前的表示形式 + /// + public int GetPreviousPosition(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousPosition, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the representation of c before this battle occurs + /// 返回卡片 c 在本次战斗发生之前的表示形式 + /// + public int GetBattlePosition(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetBattlePosition, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the current position of c + /// 返回卡片 c 当前的所在位置 + /// + public int GetLocation(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLocation, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the position before the c position changes + /// 返回卡片 c 位置变化前的所在的位置 + /// + public int GetPreviousLocation(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetPreviousLocation, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the serial number of the current position + /// 返回卡片 c 在当前位置的序号 在场上时,序号代表所在的格子,从左往右分别是0-4,5-6,场地魔法格的序号为5,左右灵摆区域为6-7在其它地方时,序号表示的是第几张卡,最下面的卡的序号为0 + /// + public int GetSequence(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetSequence, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the call / special call of c + /// 返回卡片 c 的召唤/特殊召唤的方式 + /// + public int GetSummonType(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetSummonType, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the call position of c + /// 返回卡片 c 的召唤/特殊召唤的位置 + /// + public int GetSummonLocation(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetSummonLocation, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return to Summoner / Special Summoner c Players + /// 返回召唤/特殊召唤 c 上场的玩家 + /// + public int GetSummonPlayer(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetSummonPlayer, c); + if (result == null) return PLAYER_NONE; + return (int)result; + } + + /// + /// Returns the destination of the c position change + /// 返回卡片 c 位置变化的目的地此函数仅在处理位置转移代替效果时有效 + /// + public int GetDestination(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetDestination, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Returns the destination of an effect (such as the universe) that was changed as a result of departure from c + /// 返回卡片 c 离场时因改变去向的效果(如大宇宙)的目的地 + /// + public int GetLeaveFieldDest(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetLeaveFieldDest, c); + if (result == null) return 0; + return (int)result; + } + + /// + /// Return c The round to the current position + /// 返回卡片 c 转移到当前位置的回合 + /// + public int GetTurnID(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetTurnID, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the time stamp of the transition to the current position + /// 返回卡片 c 转移到当前位置的时间标识此数值唯一,越小表示c是越早出现在那个位置卡片从里侧翻开也会改变此数值 + /// + public int GetFieldID(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetFieldID, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the actual timestamp for the c transition to the current position + /// 返回卡片 c 转移到当前位置的真实的时间标识卡片从里侧翻开不会改变此数值 + /// + public int GetRealFieldID(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetRealFieldID, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the round counter for c + /// 返回卡片 c 的回合计数器 + /// + public int GetTurnCounter(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetTurnCounter, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the amount of material used for c appearance + /// 返回卡片 c 出场使用的素材数量 + /// + public int GetMaterialCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetMaterialCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the number of cards currently loaded + /// 返回卡片 c 当前装备着的卡片数量 + /// + public int GetEquipCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetEquipCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the number of cards currently stacked + /// 返回卡片 c 当前叠放着的卡片数量 + /// + public int GetOverlayCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOverlayCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the number of cards that have been attacked this turn + /// 返回卡片 c 本回合攻击过的卡片数量 + /// + public int GetAttackedGroupCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetAttackedGroupCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the number of times this round has been attacked + /// 返回卡片 c 本回合攻击过的次数 注:如果此值与 Card.GetAttackedGroupCount(c) 的返回值不同,那么说明卡片c本回合进行过直接攻击 + /// + public int GetAttackedCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetAttackedCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// 返回卡片 c 本回合攻击宣言的次数 注:攻击被无效不会被计入攻击过的次数,但是会计入攻击宣言的次数 + /// + public int GetAttackAnnouncedCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetAttackAnnouncedCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the number of current persistent objects + /// 返回卡片 c 当前的永续对象的数量 + /// + public int GetCardTargetCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetCardTargetCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the number of cards that take c as the persistent object + /// 返回取卡片 c 作为永续对象的卡的数量 + /// + public int GetOwnerTargetCount(ClientCard c) + { + int? result = HandleCardToInt(FunctionCode.Card.GetOwnerTargetCount, c); + if (result == null) return -1; + return (int)result; + } + + /// + /// Return c as the fusion material when the card number (including the original c card number) + /// 返回卡片 c 作为融合素材时的卡号。第2个返回值开始是其他的卡号 + /// + public IList GetFusionCode(ClientCard c) + { + return HandleCardToIntEx(FunctionCode.Card.GetFusionCode, c); + } + + /// + /// 返回卡片 c 作为连接素材的卡号。第2个返回值开始是其他的卡号 + /// + public IList GetLinkCode(ClientCard c) + { + return HandleCardToIntEx(FunctionCode.Card.GetLinkCode, c); + } + + /// + /// Check the c as a fusion material can be used as the card number for the code card + /// 检查卡片 c 作为融合素材时能否当作卡号为 code 的卡,额外参数是其他 code + /// + public bool IsFusionCode(ClientCard c,int code, params int[] ex_code) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsFusionCode, c, code, ex_code); + } + + /// + /// 检查卡片 c 作为连接素材时能否当作卡号为 code 的卡,额外参数是其他 code + /// + public bool IsLinkCode(ClientCard c, int code, params int[] ex_code) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsLinkCode, c, code, ex_code); + } + + /// + /// Check whether c is a card with the name setname + /// 检查卡片 c 是否是卡名含有 setname 的卡(也就是字段),额外参数是其他 setname + /// + public bool IsSetCard(ClientCard c, int setcode, params int[] ex_setcode) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsSetCard, c, setcode, ex_setcode); + } + + /// + /// 检查卡片 c 是否是原本卡名含有 setname 的卡(也就是字段) + /// + public bool IsOriginalSetCard(ClientCard c, int setcode, params int[] ex_setcode) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsOriginalSetCard, c, setcode, ex_setcode); + } + + /// + /// Check whether the name c contains a setname before the c position changes + /// 检查卡片 c 位置变化之前是否是名字含有 setname 的卡(也就是字段) + /// + public bool IsPreviousSetCard(ClientCard c, int setcode, params int[] ex_setcode) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsPreviousSetCard, c, setcode, ex_setcode); + } + + /// + /// Check the c as a fusion material can be used as a name setname card + /// 检查卡片 c 作为融合素材时能否当作名字含有 setname 的卡(也就是字段) + /// + public bool IsFusionSetCard(ClientCard c, int setcode, params int[] ex_setcode) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsFusionSetCard, c, setcode, ex_setcode); + } + + /// ) + /// 检查卡片 c 作为连接素材时能否当作名字含有 setname 的卡(也就是字段) + /// + public bool IsLinkSetCard(ClientCard c, int setcode, params int[] ex_setcode) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsLinkSetCard, c, setcode, ex_setcode); + } + + /// + /// 检查卡片 c 的卡号是否规则上(就是CDB里显示的卡密)是 code1[, 或者为 code2...] + /// + public bool IsOriginalCodeRule(ClientCard c, int code, params int[] ex_code) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsOriginalCodeRule, c, code, ex_code); + } + + /// + /// Check whether the card number c is code1 [, or code2 ...] + /// 检查卡片 c 的卡号是否是 code1[, 或者为 code2...] + /// + public bool IsCode(ClientCard c, int code, params int[] ex_code) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsCode, c, code, ex_code); + } + + /// + /// 检查卡片 c 是否是等级 level1[, 或者为 level2...] + /// + public bool IsLevel(ClientCard c, int level, params int[] ex_level) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsLevel, c, level, ex_level); + } + + /// + /// 检查卡片 c 是否是阶级 rank1[, 或者为 rank2...] + /// + public bool IsRank(ClientCard c, int rank, params int[] ex_rank) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsRank, c, rank, ex_rank); + } + + /// + /// 检查卡片 c 的连接标记数量是否是 link1[, 或者为 link2...] + /// + public bool IsLink(ClientCard c, int link, params int[] ex_link) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsLink, c, link, ex_link); + } + + /// + /// 检查卡片 c 的攻击力是否是 atk1[, 或者为 atk2...],如果c不是怪兽卡,或者不在 LOCATION_MZONE 则都返回false + /// + public bool IsAttack(ClientCard c, int attack, params int[] ex_attack) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsAttack, c, attack, ex_attack); + } + + /// + /// 检查卡片 c 的守备力是否是 def1[, 或者为 def2...],如果c不是怪兽卡,或者不在 LOCATION_MZONE 则都返回false + /// + public bool IsDefense(ClientCard c, int defense, params int[] ex_defense) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsDefense, c, defense, ex_defense); + } + + /// + /// 检查卡片 c [由 player 连接召唤时]用作连接素材时是否属于种族 race + /// + public bool IsLinkRace(ClientCard c, int race, int player = PLAYER_NONE) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsLinkRace, c, race, player); + } + + /// + /// 检查卡片 c [由 player 融合召唤时]用作融合素材是否属于属性 attribute + /// + public bool IsFusionAttribute(ClientCard c, int attribute, int player = PLAYER_NONE) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsFusionAttribute, c, attribute, player); + } + + /// + /// 检查卡片 c [由 player 连接召唤时]用作连接素材是否属于属性 attribute + /// + public bool IsLinkAttribute(ClientCard c, int attribute, int player = PLAYER_NONE) + { + return HandleCardIntIntExToBool(FunctionCode.Card.IsLinkAttribute, c, attribute, player); + } + + /// + /// Return to the co-ordination of c with the call monster sc with the level + /// 返回卡片 c 的对于同调怪兽 sc 的同调用等级此函数除了某些特定卡如调节支援士,返回值与Card.GetLevel(c) 相同 + /// + public int GetSynchroLevel(ClientCard c, ClientCard sc) + { + int? result = HandleDoubleCardToInt(FunctionCode.Card.GetSynchroLevel, c, sc); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the ritual liberation level for rc ritual monsters + /// 返回卡片 c 的对于仪式怪兽 rc 仪式解放等级此函数除了某些特定卡如仪式供物,返回值与Card.GetLevel(c) 相同 + /// + public int GetRitualLevel(ClientCard c, ClientCard sc) + { + int? result = HandleDoubleCardToInt(FunctionCode.Card.GetRitualLevel, c, sc); + if (result == null) return -1; + return (int)result; + } + + /// + /// 检查卡片 c 是否是连接标记为 dir 的卡 + /// + public bool IsLinkMarker(ClientCard c, int dir) + { + return HandleCardIntToBool(FunctionCode.Card.IsLinkMarker, c, dir); + } + + /// + /// Check if c is of type type + /// 检查卡片 c 是否属于类型 type + /// + public bool IsType(ClientCard c, int type) + { + return HandleCardIntToBool(FunctionCode.Card.IsType, c, type); + } + + /// + /// 检查卡片 c 用作融合素材时是否属于类型 type (与IsType的区别在于对于魔陷区的怪兽卡,用其原本类型作判断) + /// + public bool IsFusionType(ClientCard c, int type) + { + return HandleCardIntToBool(FunctionCode.Card.IsFusionType, c, type); + } + + /// + /// 检查卡片 c 用作同调素材时是否属于类型 type (与IsType的区别在于对于魔陷区的怪兽卡,用其原本类型作判断) + /// + public bool IsSynchroType(ClientCard c, int type) + { + return HandleCardIntToBool(FunctionCode.Card.IsSynchroType, c, type); + } + + /// + /// 检查卡片 c 用作超量素材时是否属于类型 type (与IsType的区别在于对于魔陷区的怪兽卡,用其原本类型作判断) + /// + public bool IsXyzType(ClientCard c, int type) + { + return HandleCardIntToBool(FunctionCode.Card.IsXyzType, c, type); + } + + /// + /// 检查卡片 c 用作连接素材时是否属于类型 type (与IsType的区别在于对于魔陷区的怪兽卡,用其原本类型作判断) + /// + public bool IsLinkType(ClientCard c, int type) + { + return HandleCardIntToBool(FunctionCode.Card.IsLinkType, c, type); + } + + /// + /// Check if c is race race + /// 检查卡片 c 是否属于种族 race + /// + public bool IsRace(ClientCard c, int race) + { + return HandleCardIntToBool(FunctionCode.Card.IsRace, c, race); + } + + /// + /// Check whether c belongs to attribute attribute + /// 检查卡片 c 是否属于属性 attribute + /// + public bool IsAttribute(ClientCard c, int attribute) + { + return HandleCardIntToBool(FunctionCode.Card.IsAttribute, c, attribute); + } + + /// + /// Check if c contains the reason + /// 检查卡片 c 是否包含原因 reason + /// + public bool IsReason(ClientCard c, int reason) + { + return HandleCardIntToBool(FunctionCode.Card.IsReason, c, reason); + } + + /// + /// 检查卡片 c 的召唤类型是否是 sumtype + /// + public bool IsSummonType(ClientCard c, int sumtype) + { + return HandleCardIntToBool(FunctionCode.Card.IsSummonType, c, sumtype); + } + + /// + /// 检查卡片 c 的召唤区域是否是 tloc + /// + public bool IsSummonLocation(ClientCard c, int tloc) + { + return HandleCardIntToBool(FunctionCode.Card.IsSummonLocation, c, tloc); + } + + /// + ///检查卡片 c 的召唤玩家是否是 sumplayer + /// + public bool IsSummonPlayer(ClientCard c, int sumplayer) + { + return HandleCardIntToBool(FunctionCode.Card.IsSummonPlayer, c, sumplayer); + } + + /// + /// Check whether c contains a status code + ///检查卡片 c 是否包含某个状态码 status + /// + public bool IsStatus(ClientCard c, int status) + { + return HandleCardIntToBool(FunctionCode.Card.IsStatus, c, status); + } + + /// + /// Check if c is linked to chained chainc + ///检查卡片 c 是否和连锁 chainc 有联系。 chainc==0 表示当前连锁 + /// + public bool IsRelateToChain(ClientCard c, int chainc) + { + return HandleCardIntToBool(FunctionCode.Card.IsRelateToChain, c, chainc); + } + + /// + /// Check whether c is the representation pos + ///检查卡片 c 是否是表示形式 pos + /// + public bool IsPosition(ClientCard c, int pos) + { + return HandleCardIntToBool(FunctionCode.Card.IsPosition, c, pos); + } + + /// + /// Check whether the c position before the change is represented by pos + ///检查卡片 c 位置变化之前是否是表示形式 pos + /// + public bool IsPreviousPosition(ClientCard c, int pos) + { + return HandleCardIntToBool(FunctionCode.Card.IsPreviousPosition, c, pos); + } + + /// + /// Check whether the current control of c is a controler + ///检查卡片 c 的当前控制着是否是 controler + /// + public bool IsControler(ClientCard c, int controler) + { + return HandleCardIntToBool(FunctionCode.Card.IsControler, c, controler); + } + + /// + ///检查卡片 c 的当前控制着是否是 controler + /// + public bool IsPreviousControler(ClientCard c, int controler) + { + return HandleCardIntToBool(FunctionCode.Card.IsPreviousControler, c, controler); + } + + /// + /// Check if c is the current location + ///检查卡片 c 当前位置是否是 location + /// + public bool IsLocation(ClientCard c, int location) + { + return HandleCardIntToBool(FunctionCode.Card.IsLocation, c, location); + } + + /// + /// Check if the location before c is location + ///检查卡片 c 之前的位置是否是 location + /// + public bool IsPreviousLocation(ClientCard c, int location) + { + return HandleCardIntToBool(FunctionCode.Card.IsPreviousLocation, c, location); + } + + /// + /// Check whether c is below the level level (at least 1) + ///检查卡片 c 是否是等级 level 以下(至少为1) + /// + public bool IsLevelBelow(ClientCard c, int level) + { + return HandleCardIntToBool(FunctionCode.Card.IsLevelBelow, c, level); + } + + /// + /// Check whether c is above level level + ///检查卡片 c 是否是等级 level 以上 + /// + public bool IsLevelAbove(ClientCard c, int level) + { + return HandleCardIntToBool(FunctionCode.Card.IsLevelAbove, c, level); + } + + /// + /// Check whether c is below the rank rank (at least 1) + ///检查卡片 c 是否是阶级 rank 以下(至少为1) + /// + public bool IsRankBelow(ClientCard c, int rank) + { + return HandleCardIntToBool(FunctionCode.Card.IsRankBelow, c, rank); + } + + /// + ///Check whether c is above the class rank + ///检查卡片 c 是否是阶级 rank 以上 + /// + public bool IsRankAbove(ClientCard c, int rank) + { + return HandleCardIntToBool(FunctionCode.Card.IsRankAbove, c, rank); + } + + /// + ///检查卡片 c 是否连接标记数量是 link 以下(至少为1) + /// + public bool IsLinkBelow(ClientCard c, int link) + { + return HandleCardIntToBool(FunctionCode.Card.IsLinkBelow, c, link); + } + + /// + ///检查卡片 c 是否连接标记数量是 link 以上 + /// + public bool IsLinkAbove(ClientCard c, int link) + { + return HandleCardIntToBool(FunctionCode.Card.IsLinkAbove, c, link); + } + + /// + /// Check whether c is attack power atk below (at least 0) + ///检查卡片 c 是否是攻击力 atk 以下(至少为0) + /// + public bool IsAttackBelow(ClientCard c, int atk) + { + return HandleCardIntToBool(FunctionCode.Card.IsAttackBelow, c, atk); + } + + /// + ///Check whether c is more than attack power atk + ///检查卡片 c 是否是攻击力 atk 以上 + /// + public bool IsAttackAbove(ClientCard c, int atk) + { + return HandleCardIntToBool(FunctionCode.Card.IsAttackAbove, c, atk); + } + + /// + /// Check whether c is defensive def below (at least 0) + ///检查卡片 c 是否是守备力 def 以下(至少为0) + /// + public bool IsDefenseBelow(ClientCard c, int def) + { + return HandleCardIntToBool(FunctionCode.Card.IsDefenseBelow, c, def); + } + + /// + ///Check c is defensive def above + ///检查卡片 c 是否是守备力 def 以上 + /// + public bool IsDefenseAbove(ClientCard c, int def) + { + return HandleCardIntToBool(FunctionCode.Card.IsDefenseAbove, c, def); + } + + /// + ///检查卡片 c 是否可以放置 countertype 类型的指示物 + /// + public bool IsCanHaveCounter(ClientCard c, int countertype) + { + return HandleCardIntToBool(FunctionCode.Card.IsDefenseAbove, c, countertype); + } + + /// + ///检查卡片 c 是否是可[用 sum_type 方式]融合召唤的卡 + /// + public bool IsFusionSummonableCard(ClientCard c, int sum_type = 0) + { + return HandleCardIntToBool(FunctionCode.Card.IsFusionSummonableCard, c, sum_type); + } + + /// + /// Check if you can make a special call to c + ///检查是否可以对卡片 c [用 sum_type 方式]进行特殊召唤手续 + /// + public bool IsSpecialSummonable(ClientCard c, int sum_type = 0) + { + return HandleCardIntToBool(FunctionCode.Card.IsSpecialSummonable, c, sum_type); + } + + /// + /// Check whether c can hand + ///检查卡片 c 是否可以送去[玩家 player 的]手牌 + /// + public bool IsAbleToHand(ClientCard c, int player) + { + return HandleCardIntToBool(FunctionCode.Card.IsAbleToHand, c, player); + } + + /// + ///Check whether c can be excluded as a cost + ///检查卡片 c 是否可以[以 pos 表示形式]作为cost除外 + /// + public bool IsAbleToRemoveAsCost(ClientCard c, int pos = (int)CardPosition.FaceUp) + { + return HandleCardIntToBool(FunctionCode.Card.IsAbleToRemoveAsCost, c, pos); + } + + /// + /// Check whether c can be discarded + ///检查卡片 c 是否可以以 reason 原因丢弃 + /// + public bool IsDiscardable(ClientCard c, int reason = (int)CardReason.Cost) + { + return HandleCardIntToBool(FunctionCode.Card.IsDiscardable, c, reason); + } + + /// + ///检查卡片 c 是否可以被[玩家 player]叠放 + /// + public bool IsCanOverlay(ClientCard c, int player) + { + return HandleCardIntToBool(FunctionCode.Card.IsCanOverlay, c, player); + } + + /// + ///返回卡片 c 的连接区的卡片组(目前只限怪兽区) + /// + public IList GetLinkedGroup(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetLinkedGroup, c); + } + + /// + ///返回和卡片 c 互相连接状态的卡片组 + /// + public IList GetMutualLinkedGroup(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetMutualLinkedGroup, c); + } + + /// + ///返回与卡片 c 同一纵列的 c 以外的卡片组 + /// + public IList GetColumnGroup(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetColumnGroup, c); + } + + /// + ///Returns the material used for the appearance of c) + ///返回卡片 c 出场使用的素材 + /// + public IList GetMaterial(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetMaterial, c); + } + + /// + /// Returns the current set of cards + ///返回卡片 c 当前装备着的卡片组 + /// + public IList GetEquipGroup(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetEquipGroup, c); + } + + /// + ///Returns the card set attacked by this turn + ///返回卡片 c 本回合攻击过的卡片组 + /// + public IList GetAttackedGroup(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetAttackedGroup, c); + } + + /// + /// Returns the deck of the card that fought this turn + ///返回本回合与卡片 c 进行过战斗的卡片组 进行过战斗指发生过伤害的计算,用于剑斗兽等卡的判定 + /// + public IList GetBattledGroup(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetBattledGroup, c); + } + + /// + /// Returns all currently persistent objects + ///返回卡片 c 当前所有的永续对象 + /// + public IList GetCardTarget(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetCardTarget, c); + } + + /// + /// Returns all cards with c as the persistent object + ///返回取卡片 c 作为永续对象的所有卡 + /// + public IList GetOwnerTarget(ClientCard c) + { + return HandleCardToGroup(FunctionCode.Card.GetOwnerTarget, c); + } + + /// + ///检查卡片 c 是否是连接状态 + /// + public bool IsLinkState(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsLinkState, c); + } + + /// + ///检查卡片 c 是否是额外连接状态 + /// + public bool IsExtraLinkState(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsExtraLinkState, c); + } + + /// + ///检查与卡片 c 同一纵列的区域是否全都有卡 + /// + public bool IsAllColumn(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAllColumn, c); + } + + /// + ///检查卡片 c 是否属于额外卡组的怪兽(融合·同调·超量·连接) + /// + public bool IsExtraDeckMonster(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsExtraDeckMonster, c); + } + + /// + /// Check whether c is in the re-call state + ///检查卡片 c 属否处于再召唤状态 + /// + public bool IsDualState(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsDualState, c); + } + + /// + /// Check whether c direct attack + ///检查卡片 c 是否直接攻击过 + /// + public bool IsDirectAttacked(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsDirectAttacked, c); + } + + /// + /// Check whether c is associated with this battle + ///检查卡片 c 是否和本次战斗关联 注:此效果通常用于伤害计算后伤害阶段结束前,用于检查战斗的卡是否离场过 + /// + public bool IsRelateToBattle(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsRelateToBattle, c); + } + + /// + /// Check whether c is in an invalid state + ///检查卡片 c 是否处于无效状态 + /// + public bool IsDisabled(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsDisabled, c); + } + + /// + /// Check whether c is a card that can be called normally + ///检查卡片 c 是否是可通常召唤的卡 + /// + public bool IsSummonableCard(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsSummonableCard, c); + } + + /// + /// Check whether c can be sent to the card group + ///检查卡片 c 是否可以送去卡组 + /// + public bool IsAbleToDeck(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToDeck, c); + } + + /// + /// Check if c can send extra cards + ///检查卡片 c 是否可以送去额外卡组 对于非融合、同调等额外怪兽或者非灵摆怪兽此函数均返回false + /// + public bool IsAbleToExtra(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToExtra, c); + } + + /// + /// Check whether c can be sent to the cemetery + ///检查卡片 c 是否可以送去墓地 + /// + public bool IsAbleToGrave(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToGrave, c); + } + + /// + /// Check whether c can be sent as the cost of hand cards + ///检查卡片 c 是否可以作为cost送去手牌 + /// + public bool IsAbleToHandAsCost(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToHandAsCost, c); + } + + /// + /// Check whether c can be sent to the card as a cost group + ///检查卡片 c 是否可以作为cost送去卡组 + /// + public bool IsAbleToDeckAsCost(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToDeckAsCost, c); + } + + /// + /// Check whether c can be sent as an additional cost card group + ///检查卡片 c 是否可以作为cost送去额外卡组,主卡组的灵摆卡会返回false + /// + public bool IsAbleToExtraAsCost(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToExtraAsCost, c); + } + + /// + /// Check whether c can be sent as a cost card group or additional card group (for the new Yu-xia, sword fighting beast fusion call monster detection procedures) + ///检查卡片 c 是否可以作为cost送去卡组或额外卡组(用于新宇侠、剑斗兽融合怪兽的召唤手续检测) + /// + + + public bool IsAbleToDeckOrExtraAsCost(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToDeckOrExtraAsCost, c); + } + + /// + ///Check whether c can be sent to the cemetery as a cost + ///检查卡片 c 是否可以作为cost送去墓地 + /// + public bool IsAbleToGraveAsCost(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToGraveAsCost, c); + } + + /// + /// Check whether c can be liberated (non-superior call) + ///检查卡片 c 是否可以被解放(非上级召唤用) + /// + public bool IsReleasable(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsReleasable, c); + } + + /// + ///Check whether c can be liberated by the effect + ///检查卡片 c 是否可以被效果解放 + /// + public bool IsReleasableByEffect(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsReleasableByEffect, c); + } + + /// + /// Check whether c can attack + ///检查卡片 c 是否可以攻击 + /// + public bool IsAttackable(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAttackable, c); + } + + /// + /// Check whether c is a surface-side representation + ///检查卡片 c 是否是表侧表示 + /// + public bool IsFaceup(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsFaceup, c); + } + + /// + ///Check whether c is an attack + ///检查卡片 c 是否是攻击表示 + /// + public bool IsAttackPos(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAttackPos, c); + } + + /// + /// Check whether c is the backside representation + ///检查卡片 c 是否是里侧表示 + /// + public bool IsFacedown(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsFacedown, c); + } + + /// + /// Check whether c is a defensive representation + ///检查卡片 c 是否是守备表示 + /// + public bool IsDefensePos(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsDefensePos, c); + } + + /// + /// Check if c is present + ///检查卡片 c 是否在场 + /// + public bool IsOnField(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsOnField, c); + } + + /// + /// Check if c is open + ///检查卡片 c 是否处于公开状态 + /// + public bool IsPublic(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsPublic, c); + } + + /// + ///Check whether c is in the declaration prohibition state + ///检查卡片 c 是否处于被宣言禁止状态 + /// + public bool IsForbidden(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsForbidden, c); + } + + /// + /// Check whether c can change the control + ///检查卡片 c 是否可以改变控制权 + /// + public bool IsAbleToChangeControler(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsAbleToChangeControler, c); + } + + /// + ///检查卡片 c 是否可以用效果改变表示形式 + /// + public bool IsCanChangePosition(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsCanChangePosition, c); + } + + /// + /// Check whether c can turn into the inside of that + ///检查卡片 c 是否可以转成里侧表示 + /// + public bool IsCanTurnSet(ClientCard c) + { + return HandleCardToBool(FunctionCode.Card.IsCanTurnSet, c); + } + + /// + ///返回以玩家 player 来看的所有连接区域 + /// + public int GetLinkedZone(ClientCard c,int player) + { + int? result = HandleIntToInt(FunctionCode.Card.GetLinkedZone, c, player); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回[以 player 来看的]与卡片 c 互相连接的卡 所在的区域 + /// + public int GetMutualLinkedZone(ClientCard c, int player) + { + int? result = HandleIntToInt(FunctionCode.Card.GetMutualLinkedZone, c, player); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回卡片 c [由 player 融合召唤时]用作融合素材时的属性 + /// + public int GetFusionAttribute(ClientCard c, int player = PLAYER_NONE) + { + int? result = HandleIntToInt(FunctionCode.Card.GetFusionAttribute, c, player); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回卡片 c [由 player 连接召唤时]用作连接素材时的属性 + /// + public int GetLinkAttribute(ClientCard c, int player = PLAYER_NONE) + { + int? result = HandleIntToInt(FunctionCode.Card.GetLinkAttribute, c, player); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回卡片 c [由 player 连接召唤时]作为连接素材时的种族 + /// + public int GetLinkRace(ClientCard c, int player = PLAYER_NONE) + { + int? result = HandleIntToInt(FunctionCode.Card.GetLinkRace, c, player); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the card that caused the position of c to change + ///返回导致卡片 c 的位置变化的卡 + /// + public ClientCard GetReasonCard(ClientCard c) + { + return HandleCardToCard(FunctionCode.Card.GetReasonCard, c); + } + + /// + /// Returns the current artefact object + ///返回卡片 c 当前的装备对象 + /// + public ClientCard GetEquipTarget(ClientCard c) + { + return HandleCardToCard(FunctionCode.Card.GetEquipTarget, c); + } + + /// + ///Returns the device object before c + ///返回卡片 c 之前的装备对象 + /// + public ClientCard GetPreviousEquipTarget(ClientCard c) + { + return HandleCardToCard(FunctionCode.Card.GetPreviousEquipTarget, c); + } + + /// + ///Returns the card with c as the excess material + ///返回以卡片 c 为超量素材的卡 + /// + public ClientCard GetOverlayTarget(ClientCard c) + { + return HandleCardToCard(FunctionCode.Card.GetOverlayTarget, c); + } + + /// + /// Returns c the current first persistent object + ///返回卡片 c 当前第一个永续对象,没有则返回 nil + /// + public ClientCard GetFirstCardTarget(ClientCard c) + { + return HandleCardToCard(FunctionCode.Card.GetFirstCardTarget, c); + } + + /// + ///Returns the card that fought with c + ///返回与卡片 c 进行战斗的卡,没有则返回nil + /// + public ClientCard GetBattleTarget(ClientCard c) + { + return HandleCardToCard(FunctionCode.Card.GetBattleTarget, c); + } + + /// + ///Check whether c can be used as a non-adjustment + ///检查卡片 c 是否可以作为同调怪兽 sc 的调整以外的怪兽 + /// + public bool IsNotTuner(ClientCard c, ClientCard sc) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsNotTuner, c, sc); + } + + /// + /// Check whether c2 is the correct equipment object for c1 + ///检查卡片 c2是否是卡片 c1 的正确的装备对象 + /// + public bool CheckEquipTarget(ClientCard c1, ClientCard c2) + { + return HandleDoubleCardToBool(FunctionCode.Card.CheckEquipTarget, c1, c2); + } + + /// + ///检查卡片 c2 是否是卡片 c1 的正确的同盟对象 + /// + public bool CheckUnionTarget(ClientCard c1, ClientCard c2) + { + return HandleDoubleCardToBool(FunctionCode.Card.CheckUnionTarget, c1, c2); + } + + /// + /// Check whether c1 takes c2 as a persistent object + ///检查卡片 c2 是否取卡片 c1 为永续对象 + /// + public bool IsHasCardTarget(ClientCard c1, ClientCard c2) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsHasCardTarget, c1, c2); + } + + /// + /// Check whether c1 and c2 are linked + ///检查卡片 c1 是否和卡片 c2 有联系 + /// + public bool IsRelateToCard(ClientCard c1, ClientCard c2) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsRelateToCard, c1, c2); + } + + /// + /// Check whether the c can replace the material description card name of the fusion monster fc + ///检查卡片 c 能否代替融合怪兽 fc 的记述卡名的素材 + /// + public bool CheckFusionSubstitute(ClientCard c, ClientCard fc) + { + return HandleDoubleCardToBool(FunctionCode.Card.CheckFusionSubstitute, c, fc); + } + + /// + /// Check whether c1 can become a target of c2 + ///检查卡片 c1 是否可以成为卡片 c2 的攻击目标 + /// + public bool IsCanBeBattleTarget(ClientCard c1, ClientCard c2) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsCanBeBattleTarget, c1, c2); + } + + /// + ///Returns the number of effects that c is affected by the type of code + ///返回卡片 c 受到影响的种类是code的效果的数量 + /// + public int GetEffectCount(ClientCard c, int code) + { + int? result = HandleCardIntToInt(FunctionCode.Card.GetEffectCount, c, code); + if (result == null) return -1; + return (int)result; + } + + /// + ///The type of returned c is the number of identifying effects of the code + ///返回卡片 c 的种类是 code 的标识效果的数量 + /// + public int GetFlagEffect(ClientCard c, int code) + { + int? result = HandleCardIntToInt(FunctionCode.Card.GetFlagEffect, c, code); + if (result == null) return -1; + return (int)result; + } + + /// + ///Returns the number of countertype types on c + ///返回卡片 c 上的 countertype 类型的指示物的数量, countertype==0 则返回卡片 c 上所有类型的指示物数量之和 + /// + public int GetCounter(ClientCard c, int countertype) + { + int? result = HandleCardIntToInt(FunctionCode.Card.GetCounter, c, countertype); + if (result == null) return -1; + return (int)result; + } + + /// + /// Check whether c is usually called (not including the normally called set) + ///检查卡片 c 是否可以进行通常召唤(不包含通常召唤的set),ignore_count==true 则不检查召唤次数限制,minc 表示至少需要的祭品数(用于区分妥协召唤与上级召唤),zone 表示必须要召唤到的区域 + /// + public bool IsSummonable(ClientCard c, bool ignore_count = false, int minc = 0, int zone = 0x1f) + { + object result = HandleCardSpecial(FunctionCode.Card.IsSummonable, c, ignore_count, minc, zone); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether c can be normally called set + ///检查卡片 c 是否可进行通常召唤的set,ignore_count==true 则不检查召唤次数限制 minc 表示至少需要的祭品数(用于区分妥协召唤set与上级召唤set),zone 表示必须要放置到的区域 + /// + public bool IsMSetable(ClientCard c, bool ignore_count = false, int minc = 0, int zone = 0x1f) + { + object result = HandleCardSpecial(FunctionCode.Card.IsMSetable, c, ignore_count, minc, zone); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether mg can be selected in the [min-max months] excessive material on the c to call the excess procedure + ///检查是否可以在场上的卡[中选出 minc-maxc 个超量素材]对卡片 c 进行超量召唤手续 c 如果不是超量会返回 false + /// + public bool IsXyzSummonable(ClientCard c, int minc = 0, int maxc = 0) + { + object result = HandleCardSpecial(FunctionCode.Card.IsXyzSummonable, c, minc, maxc); + if (result == null) return false; + return (bool)result; + } + + /// + ///检查是否可以用[包含卡 lcard 的]场上的卡[选出 minc-maxc 个连接素材]对卡片 c 进行连接召唤手续 c 如果不是连接会返回 false + /// + public bool IsLinkSummonable(ClientCard c, ClientCard lcard = null, int minc = 0, int maxc = 0) + { + object result = HandleCardSpecial(FunctionCode.Card.IsLinkSummonable, c, lcard, minc, maxc); + if (result == null) return false; + return (bool)result; + } + + /// + /// The type of c is the label that identifies the effect of code, and returns nil if it does not + ///返回卡片 c 的种类为 code 的标识效果的Label(数量可能不止1个) + /// + public IList GetFlagEffectLabel(ClientCard c, int code) + { + object result = HandleCardSpecial(FunctionCode.Card.GetFlagEffectLabel, c, code); + if (result == null) return new List(); + return (IList)result; + } + + /// + ///返回[以 player 来看的] location 范围内与卡片 c 同一纵列的区域(c 所在的位置排除), + /// + public int GetColumnZone(ClientCard c, int location, int player) + { + object result = HandleCardSpecial(FunctionCode.Card.GetColumnZone, c, location, player); + if (result == null) return -1; + return (int)result; + } + + /// + ///Returns all stacked cards at a specified location + ///返回卡片 c 当前叠放着的卡片组 + /// + public IList GetOverlayGroup(ClientCard c) + { + object result = HandleCardSpecial(FunctionCode.Card.GetOverlayGroup, c); + if (result == null) return new List(); + return (IList)result; + } + + /// + /// Check if the player can remove at least count cards for the specified reason + ///检查玩家 player 能否以 reason 为原因,至少取除卡片 c 下面叠放的 count 张卡 + /// + public bool CheckRemoveOverlayCard(ClientCard c, int player, int count, int reason) + { + object result = HandleCardSpecial(FunctionCode.Card.CheckRemoveOverlayCard, c, player, count, reason); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check if c is affected by the effect type + ///检查卡片 c 是否受到效果种类是code的效果的影响 + /// + public bool IsHasEffect(ClientCard c, int code, int check_player = PLAYER_NONE) + { + object result = HandleCardSpecial(FunctionCode.Card.IsHasEffect, c, code, check_player); + if (result == null) return false; + return (bool)result; + } + + /// + /// Returns the attackable card set and whether it can attack directly + ///返回卡片 c 可攻击的卡片组以及能否直接攻击,[0]是否可以攻击,[1]卡片组 + /// + public object[] GetAttackableTarget(ClientCard c) + { + object result = HandleCardSpecial(FunctionCode.Card.GetAttackableTarget, c); + if (result == null) return new object[0]; + return (object[])result; + } + + /// + /// Check c for excess monster xyzc with the level of whether the excess is lv + ///检查卡片 c 对于超量怪兽 xyzc 的超量用等级是否是 lv + /// + public bool IsXyzLevel(ClientCard c, ClientCard xyzc, int lv) + { + object result = HandleCardSpecial(FunctionCode.Card.IsXyzLevel, c, xyzc, lv); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether c can be the object of sc + /// 检查卡片 c 是否可以成为卡片sc的效果对象 + /// + public bool IsCanBeCardTarget(ClientCard c, ClientCard sc) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsCanBeCardTarget, c, sc); + } + + /// + /// 检查卡片 c 是否可以被sc的效果无效 + /// + public bool IsCanBeDisabledByCard(ClientCard c, ClientCard sc) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsCanBeDisabledByCard, c, sc); + } + + /// + /// Check whether c immune sc + /// 检查卡片 c 是否可以免疫sc的效果 + /// + public bool IsImmuneToCard(ClientCard c, ClientCard sc) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsImmuneToCard, c, sc); + } + + /// + /// Check whether c can be destoryed by sc + /// 检查卡片 c 是否可以被sc的效果破坏 + /// + public bool IsDestructable(ClientCard c, ClientCard sc) + { + return HandleDoubleCardToBool(FunctionCode.Card.IsDestructable, c, sc); + } + + /// + /// Check whether c can be set to the magic trap area, ignore_field = true is disregard of the trap area trap trap + /// 检查卡片 c 是否可以set到魔法陷阱区,ignore_field==true 则无视魔陷区格子是否能使用的限制 + /// + public bool IsSSetable(ClientCard c, bool ignore_field = false) + { + object result = HandleCardSpecial(FunctionCode.Card.IsSSetable, c, ignore_field); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether c can be player except player + /// 检查卡片 c 是否可以被[玩家 player 以 pos 的表示形式,reason 原因]除外 + /// + public bool IsAbleToRemove(ClientCard c, int player, int pos = (int)CardPosition.FaceUp, int reason = (int)CardReason.Effect) + { + object result = HandleCardSpecial(FunctionCode.Card.IsAbleToRemove, c, player,pos,reason); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether c can be a continuous attack, c the number of attacks declared> = ac return false + /// 检查卡片 c 是否可以连续攻击,c 的攻击宣言次数>=ac 则返回false monsteronly==true 则表示只能对怪兽攻击 + /// + public bool IsChainAttackable(ClientCard c, int ac = 2, bool monsteronly = false) + { + object result = HandleCardSpecial(FunctionCode.Card.IsChainAttackable, c, ac, monsteronly); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether the control of c can be changed + /// 检查卡片 c 的控制权是否可以改变。 ignore_mzone==true 会忽视转移控制权后的玩家场上是否有空格位, zone 表示必须要使用的位置 + /// + public bool IsControlerCanBeChanged(ClientCard c, bool ignore_mzone = false, int zone = 0xff) + { + object result = HandleCardSpecial(FunctionCode.Card.IsControlerCanBeChanged, c, ignore_mzone, zone); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check if c can place count counters of type countertype [singly = true] + /// 检查是否可以给[在 location 区域存在的]卡片 c [逐个(singly==true)]放置 count 个 countertype 类型的指示物 + /// + public bool IsCanAddCounter(ClientCard c, int countertype, int count, int location, bool singly = false) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanAddCounter, c, countertype, count, singly,location); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check if the player player can remove count counters of type c on c for reason + /// 检查玩家 player 是否可以以原因 reason 移除卡片 c 上的 count 个 countertype 类型的指示物 + /// + public bool IsCanRemoveCounter(ClientCard c, int player, int countertype, int count, int reason) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanRemoveCounter, c, player, countertype, count, reason); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查卡片 c 是否可以成为[融合怪兽 fc 的 summon_type 方式的]融合素材 + /// + public bool IsCanBeFusionMaterial(ClientCard c, ClientCard fc = null, int summon_type = (int)SummonType.Fusion) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanBeFusionMaterial, c, fc, summon_type); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查卡片 c 是否可以成为[以 tuner 为调整的同调怪兽 sc 的]同调素材 + /// + public bool IsCanBeSynchroMaterial(ClientCard c, ClientCard sc = null, ClientCard tuner = null) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanBeSynchroMaterial, c, sc, tuner); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查卡片 c 是否可以作为[仪式怪兽 sc 的]仪式素材,没有指定sc的场合,必须填nil + /// + public bool IsCanBeRitualMaterial(ClientCard c, ClientCard sc = null) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanBeRitualMaterial, c, sc); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查卡片 c 是否可以成为[超量怪兽 sc 的]超量素材,没有指定sc的场合,必须填nil + /// + public bool IsCanBeXyzMaterial(ClientCard c, ClientCard sc = null) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanBeXyzMaterial, c, sc); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查卡片 c 是否可以成为[连接怪兽 sc 的]连接素材,没有指定sc的场合,必须填nil + /// + public bool IsCanBeLinkMaterial(ClientCard c, ClientCard sc = null) + { + object result = HandleCardSpecial(FunctionCode.Card.IsCanBeLinkMaterial, c, sc); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查卡片 c 在 check_player 场上[check_location 区域]的唯一性[, 忽略卡片 icard 的唯一性影响] + /// + public bool CheckUniqueOnField(ClientCard c, int check_player, int check_location = (int)CardLocation.Onfield, ClientCard icard = null) + { + object result = HandleCardSpecial(FunctionCode.Card.CheckUniqueOnField, c, check_player, check_location, icard); + if (result == null) return false; + return (bool)result; + } + + //=================== Duel =================== + + /// + /// Returns the current LP of the player's player + /// 返回玩家 player 的当前LP + /// + public int GetLP(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetLP, player); + if (result == null) return -1; + return (int)result; + } + + /// + /// 返回[玩家 player 所经过的]当前的回合数 + /// + public int GetTurnCount(int player = PLAYER_NONE) + { + object result = HandleDuel(FunctionCode.Duel.GetTurnCount, player); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the player's number of rules drawn per turn + /// 返回玩家 player 每回合的规则抽卡数量 + /// + public int GetDrawCount(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetDrawCount, player); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the player's player's damage during this battle + /// 返回玩家 player 在本次战斗中受到的伤害 + /// + public int GetBattleDamage(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetBattleDamage, player); + if (result == null) return -1; + return (int)result; + } + + /// + /// 返回以玩家 player 来看的所有连接区域 + /// + public int GetLinkedZone(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetLinkedZone, player); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the player's deck of cards available for ritual summoning material + /// 返回玩家 player 可用的用于仪式召唤素材的卡片组 + /// + public IList GetRitualMaterial(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetRitualMaterial, player); + if (result == null) return new List(); + return (IList)result; + } + + /// + /// Returns the current round of players + /// 返回当前的回合玩家 + /// + public int GetTurnPlayer() + { + object result = HandleDuel(FunctionCode.Duel.GetTurnPlayer); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the chain number currently being processed + /// 返回当前正在处理的连锁序号 + /// + public int GetCurrentChain() + { + object result = HandleDuel(FunctionCode.Duel.GetCurrentChain); + if (result == null) return -1; + return (int)result; + } + + /// + /// Returns the current stage + /// 返回当前的阶段 + /// + public int GetCurrentPhase() + { + object result = HandleDuel(FunctionCode.Duel.GetCurrentPhase); + if (result == null) return -1; + return (int)result; + } + + /// + /// Used to check if damage has been calculated during the damage phase + /// 用于在伤害阶段检查是否已经计算了战斗伤害 + /// + public bool IsDamageCalculated() + { + object result = HandleDuel(FunctionCode.Duel.IsDamageCalculated); + if (result == null) return false; + return (bool)result; + } + + /// + /// Return the card for this combat attack + /// 返回此次战斗攻击的卡 + /// + public ClientCard GetAttacker() + { + return (ClientCard)HandleDuel(FunctionCode.Duel.GetAttacker); + } + + /// + /// Return the card for this combat attack + /// 返回此次战斗被攻击的卡,如果返回null表示是直接攻击 + /// + public ClientCard GetAttackTarget() + { + return (ClientCard)HandleDuel(FunctionCode.Duel.GetAttackTarget); + } + + /// + /// heck the player at the current stage whether the operation + /// 检查玩家在当前阶段是否有操作 + /// + public bool CheckPhaseActivity() + { + object result = HandleDuel(FunctionCode.Duel.CheckPhaseActivity); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether the player can enter the combat phase of the round + /// 检查回合玩家能否进入战斗阶段 + /// + public bool IsAbleToEnterBP() + { + object result = HandleDuel(FunctionCode.Duel.IsAbleToEnterBP); + if (result == null) return false; + return (bool)result; + } + + /// + /// Returns the count card at the top of the player's deck + /// 返回玩家 player 的卡组最上方的 count 张卡 + /// + public IList GetDecktopGroup(int player, int count) + { + object result = HandleDuel(FunctionCode.Duel.GetDecktopGroup, player,count); + if (result == null) return new List(); + return (IList)result; + } + + /// + /// Return to the player player can be liberated (non-superior summoned use) of the deck, use_hand is true, including the hand card + /// 返回玩家 player 可解放(非上级召唤用)的卡片组, use_hand==true 则包括手卡 + /// + public IList GetReleaseGroup(int player, bool use_hand = false) + { + object result = HandleDuel(FunctionCode.Duel.GetReleaseGroup, player, use_hand); + if (result == null) return new List(); + return (IList)result; + } + + /// + /// Return player player can be liberated (non-superior summoned with) the number of cards, use_hand is true, including the hand card + /// 返回玩家 player 可解放(非上级召唤用)的卡片数量, use_hand==true 则包括手卡 + /// + public int GetReleaseGroupCount(int player, bool use_hand = false) + { + object result = HandleDuel(FunctionCode.Duel.GetReleaseGroupCount, player, use_hand); + if (result == null) return -1; + return (int)result; + } + + /// + /// 第一个返回值是 玩家 player [在区域 location 内的]可用的用于融合召唤素材的卡片组(包含受 EFFECT_EXTRA_FUSION_MATERIAL 效果影响的卡) + /// 第二个返回值是 只包含 手卡、怪兽区[、除外、墓地、卡组、额外卡组、P区·魔陷区原本种类是] 怪兽卡的卡片组(也即是没有包含受 EFFECT_EXTRA_FUSION_MATERIAL 效果影响的卡) + /// + public IList> GetFusionMaterial(int player, int location = (int)CardLocation.Hand | (int)CardLocation.MonsterZone) + { + object result = HandleDuel(FunctionCode.Duel.GetFusionMaterial, player, location); + if (result == null) return new List>(); + return (IList>)result; + } + + /// + /// Check if the player is affected by the effect of the code type + /// 检查玩家 player 是否受到种类为 code 的效果影响 + /// + public bool IsPlayerAffectedByEffect(int player, int code) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerAffectedByEffect, player, code); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check the player player can effect pumping [count Zhang] card + /// 检查玩家 player 是否可以效果抽[count 张]卡 + /// + public bool IsPlayerCanDraw(int player, int count = 0) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanDraw, player, count); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check player player can put the card group top count cards sent to the cemetery + /// 检查玩家 player 是否可以把卡组顶端 count 张卡送去墓地 + /// + public bool IsPlayerCanDiscardDeck(int player, int count = 0) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanDiscardDeck, player, count); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check the player player can put the card group top count cards sent to the cemetery as cost + /// 检查玩家 player 能否把卡组顶端 count 张卡送去墓地作为cost + /// + public bool IsPlayerCanDiscardDeckAsCost(int player, int count = 0) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanDiscardDeckAsCost, player, count); + if (result == null) return false; + return (bool)result; + } + + /// + /// 检查玩家 player 是否可以把卡片[ c ]盖放到魔陷区 + /// + public bool IsPlayerCanSSet(int player, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSSet, player, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check whether the player player special call count times + ///检查玩家 player 能否特殊召唤 count 次 + /// + public bool IsPlayerCanSpecialSummonCount(int player, int count) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSpecialSummonCount, player, count); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check whether the player can liberate the player c + ///检查玩家 player 是否能解放[卡片 c] + /// + public bool IsPlayerCanRelease(int player, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanRelease, player, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check whether the player can send c to hand + ///检查玩家是否能把卡片[c]送去手牌 + /// + public bool IsPlayerCanSendtoHand(int player, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSendtoHand, player, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check whether the player can send c to the cemetery + ///检查玩家是否能把卡片[c]送去墓地 + /// + public bool IsPlayerCanSendtoGrave(int player, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSendtoGrave, player, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check whether the player can send c to the card group + ///检查玩家是否能把卡片[c]送去卡组 + /// + public bool IsPlayerCanSendtoDeck(int player, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSendtoDeck, player, c); + if (result == null) return false; + return (bool)result; + } + + /// + /// 返回玩家 player 的额外卡组表侧表示的卡中最上方的 count 张卡 + /// + public IList GetExtraTopGroup(int player, int count) + { + object result = HandleDuel(FunctionCode.Duel.GetExtraTopGroup, player, count); + if (result == null) return new List(); + return (IList)result; + } + + /// + /// Return the card for this combat attack + /// 返回本次进行战斗的怪兽。以玩家 player 来看,第一个是自己的怪兽,第二个是对方的怪兽,没有进行战斗的怪兽的话,则为null + /// + public IList GetBattleMonster(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetBattleMonster,player); + if (result == null) + { + return type == ReceiveType.Success ? null : new List(); + } + return (IList)result; + } + + /// + /// Returns the number of specific marker effects for the player's player + /// 返回玩家 player 的 code 标识效果的数量 + /// + public int GetFlagEffect(int player, int code) + { + object result = HandleDuel(FunctionCode.Duel.GetFlagEffect, player,code); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回玩家 player 的种类为 code 的标识效果的全部Label + /// + public IList GetFlagEffectLabel(int player, int code) + { + object result = HandleDuel(FunctionCode.Duel.GetFlagEffectLabel, player, code); + if (result == null) return new List(); + return (IList)result; + } + + /// + ///检查玩家 player 能否[向卡片 c]添加[count 个 countertype 类型的]指示物,如果 player 不是 0或者1,则返回false 额外参数如果要用,必须全写 + /// + public bool IsCanAddCounter(int player, int countertype = -1, int count = -1, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsCanAddCounter, player, countertype, count, c); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check if the player player can remove count counters of type c on c for reason + ///检查玩家 player 以 reason 为原因是否能移除场上的 countertype 类型的 count 个指示物 + /// + public bool IsCanRemoveCounter(int player, int s, int o, int countertype, int count, int reason) + { + object result = HandleDuel(FunctionCode.Duel.IsCanRemoveCounter, player, s, o, countertype, count, reason); + if (result == null) return false; + return (bool)result; + } + + /// + /// Returns the number of counterstype types that exist on the farm + ///返回场上存在的 countertype 类型的指示物的数量 + /// + public int GetCounter(int player, int s, int o, int countertype) + { + object result = HandleDuel(FunctionCode.Duel.GetCounter, player, s, o, countertype); + if (result == null) return -1; + return (int)result; + } + + /// + ///检查场地代号是否是code [,来源玩家是否是 player][,生效区域是否在 loc 内] + /// + public bool IsEnvironment(int code, int player = PLAYER_ALL, int loc = (int)CardLocation.FieldZone | (int)CardLocation.Onfield) + { + object result = HandleDuel(FunctionCode.Duel.IsEnvironment, code, player, loc); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check player player can pay cost point lp + ///检查玩家 player 是否能支付cost点lp + /// + public bool CheckLPCost(int player, int cost) + { + object result = HandleDuel(FunctionCode.Duel.CheckLPCost, player, cost); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check whether the round player can still summon this turn [Card c] + ///检查回合玩家本回合是否还能通常召唤[卡片 c] + /// + public bool CheckSummonedCount(ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.CheckSummonedCount, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///Returns the number of spaces available in the player's field + ///返回玩家 player 的场上区域 location 内的可用的[区域 zone 里的]空格数 + /// + public int GetLocationCount(int player, int location, int use_player = PLAYER_NULL, int reason = LOCATION_REASON_TOFIELD, int zone = 0xff) + { + object result = HandleDuel(FunctionCode.Duel.GetLocationCount, player, location, use_player, reason, zone); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回玩家 player 场上[对于 use_player 来说]可用的怪兽区数量(?) + /// + public int GetUsableMZoneCount(int player, int use_player = PLAYER_NULL) + { + object result = HandleDuel(FunctionCode.Duel.GetUsableMZoneCount, player, use_player); + if (result == null) return -1; + return (int)result; + } + + /// + ///返回以玩家 player 来看的 s_range 和 o_range 区域的处于连接状态的卡片组 + /// + public IList GetLinkedGroup(int player, int s_range, int o_range) + { + object result = HandleDuel(FunctionCode.Duel.GetLinkedGroup, player, s_range, o_range); + if (result == null) return new List(); + return (IList)result; + } + + /// + ///返回以玩家 player 来看的 s_range 和 o_range 区域的处于连接状态的卡片的数量 + /// + public int GetLinkedGroupCount(int player, int s_range, int o_range) + { + object result = HandleDuel(FunctionCode.Duel.GetLinkedGroupCount, player, s_range, o_range); + if (result == null) return -1; + return (int)result; + } + + /// + /// Back to player The player's field is located in the location number seq card + ///返回玩家 player 的场上位于区域 location 序号为 seq 的卡,常用于获得场地区域·灵摆区域的卡 + /// + public ClientCard GetFieldCard(int player, int location, int seq) + { + return (ClientCard)HandleDuel(FunctionCode.Duel.GetFieldCard, player, location, seq); + } + + /// + /// Check if the player's player field is seq in the location of the space is availabl + ///检查玩家 player 的场上位于区域 location 序号为 seq 的空格是否可用 + /// + public bool CheckLocation(int player, int location, int seq) + { + object result = HandleDuel(FunctionCode.Duel.CheckLocation, player, location, seq); + if (result == null) return false; + return (bool)result; + } + + /// + /// Returns the card at the specified location + ///返回以 player 来看的指定位置的卡,s 代表以 player 来看的自己的位置,o 代表以 player 来看的对方的位置 + /// + public IList GetFieldGroup(int player, int s, int o) + { + object result = HandleDuel(FunctionCode.Duel.GetFieldGroup, player, s, o); + if (result == null) return new List(); + return (IList)result; + } + + /// + ///Returns the number of cards in the specified location + ///同 Duel.GetFieldGroup ,只是返回的是卡的数量 + /// + public int GetFieldGroupCount(int player, int s, int o) + { + object result = HandleDuel(FunctionCode.Duel.GetFieldGroupCount, player, s, o); + if (result == null) return -1; + return (int)result; + } + + /// + ///Returns all stacked cards at a specified location + ///返回以 player 来看的指定位置的所有叠放的卡 + /// + public IList GetOverlayGroup(int player, int s, int o) + { + object result = HandleDuel(FunctionCode.Duel.GetOverlayGroup, player, s, o); + if (result == null) return new List(); + return (IList)result; + } + + /// + ///Returns the number of all stacked cards in the specified location + ///返回以 player 来看的指定位置的所有叠放的卡的数量 + /// + public int GetOverlayCount(int player, int s, int o) + { + object result = HandleDuel(FunctionCode.Duel.GetOverlayCount, player, s, o); + if (result == null) return -1; + return (int)result; + } + + /// + ///Returns the deck of cards used for the normal summon c to be released (for higher-level summons) + ///返回场上用于通常召唤卡片 c 可解放(上级召唤用)的卡片组 + /// + public IList GetTributeGroup(ClientCard c) + { + object result = HandleDuel(FunctionCode.Duel.GetTributeGroup, c); + if (result == null) return new List(); + return (IList)result; + } + + /// + ///Check if the player can remove at least count cards for the specified reason + ///检查 player 能否以原因 reason 移除以 player 来看的指定位置至少 count 张卡 + /// + public bool CheckRemoveOverlayCard(int player, int s, int o, int count, int reason) + { + object result = HandleDuel(FunctionCode.Duel.CheckRemoveOverlayCard, player, s, o,count,reason); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check player player can usually call [c, to sumtype] + ///检查玩家 player 是否可以通常召唤[c,以 sumtype 方式] + /// + public bool IsPlayerCanSummon(int player, int sumtype = 0, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSummon, player, sumtype, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///检查玩家 player 是否可以盖放怪兽[c,以sumtype方式] + /// + public bool IsPlayerCanMSet(int player, int sumtype = 0, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanMSet, player, sumtype, c); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check player player can special summon [c to target_player field to sumtype summation, sumpos form] + ///检查玩家 player 能否特殊召唤[卡片 c 到 target_player 场上,以 sumtype 召唤方式,sumpos 表示形式] + /// + public bool IsPlayerCanSpecialSummon(int player, int sumtype = 0, int sumpos = 0, int target_player = PLAYER_NULL, ClientCard c = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSpecialSummon, player, sumtype, sumpos, target_player, c); + if (result == null) return false; + return (bool)result; + } + + /// + ///Check player player can be pos to the form of special summon the parameters of the monster to the target_player field + ///检查玩家 player 是否可以[以 sumtype 方式][以 pos 表示形式]特殊召唤 给定参数的怪兽到 target_player 场上 + /// + public bool IsPlayerCanSpecialSummonMonster(int player, int code, int target_player, int sumtype = 0,int pos = (int)CardPosition.FaceUp,int ? setcode = null, int? type = null,int? atk = null,int? def = null, + int? level = null,int? race = null,int? attribute = null) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanSpecialSummonMonster, player, code, setcode, type, atk, def, level, race, + attribute, pos, target_player, sumtype); + if (result == null) return false; + return (bool)result; + } + + /// + /// Check whether the player player except c + ///检查玩家 player 是否能[以 reason 原因]除外[卡片 c] + /// + public bool IsPlayerCanRemove(int player, ClientCard c = null,int reason = (int)CardReason.Effect) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanRemove, player, c, reason); + if (result == null) return false; + return (bool)result; + } + + /// + ///检查玩家是否可以额外的增加通常召唤次数。 + /// + public bool IsPlayerCanAdditionalSummon(int player) + { + object result = HandleDuel(FunctionCode.Duel.IsPlayerCanAdditionalSummon, player); + if (result == null) return false; + return (bool)result; + } + + /// + /// Returns the number of times a player fought this turn + ///返回玩家 player 这回合战斗过的次数 + /// + public int GetBattledCount(int player) + { + object result = HandleDuel(FunctionCode.Duel.GetBattledCount, player); + if (result == null) return -1; + return (int)result; + } + + + } +} diff --git a/Game/AI/Executor.cs b/Game/AI/Executor.cs index d2a43e1c..3d5aa49c 100644 --- a/Game/AI/Executor.cs +++ b/Game/AI/Executor.cs @@ -15,6 +15,7 @@ public abstract class Executor public IList Executors { get; private set; } public GameAI AI { get; private set; } public AIUtil Util { get; private set; } + public CoreFunction CoreFunction { get; private set; } protected MainPhase Main { get; private set; } protected BattlePhase Battle { get; private set; } @@ -32,6 +33,7 @@ protected Executor(GameAI ai, Duel duel) AI = ai; Util = new AIUtil(duel); Executors = new List(); + CoreFunction = AI.CoreFunction; Bot = Duel.Fields[0]; Enemy = Duel.Fields[1]; @@ -276,5 +278,20 @@ private bool DefaultNoExecutor() { return Executors.All(exec => exec.Type != Type || exec.CardId != Card.Id); } + + public int ClientFieldToPlayer(ClientField field) + { + int player = Duel.IsFirst ? 0 : 1; + if (field == Bot) + { + return player; + } + if (field == Enemy) + { + return 1 - player; + } + return 2; + } + } } \ No newline at end of file diff --git a/Game/ClientCard.cs b/Game/ClientCard.cs index 1eec6b7b..b6e4f308 100644 --- a/Game/ClientCard.cs +++ b/Game/ClientCard.cs @@ -85,6 +85,21 @@ public void SetId(int id) } } + public void SetLocation(CardLocation location) + { + Location = location; + } + + public void SetController(int controller) + { + Controller = controller; + } + + public void SetSequence(int sequence) + { + Sequence = sequence; + } + public void Update(BinaryReader packet, Duel duel) { int flag = packet.ReadInt32(); diff --git a/Game/GameAI.cs b/Game/GameAI.cs index 1c120915..7771023c 100644 --- a/Game/GameAI.cs +++ b/Game/GameAI.cs @@ -9,6 +9,7 @@ public class GameAI { public GameClient Game { get; private set; } public Duel Duel { get; private set; } + public CoreFunction CoreFunction { get; private set; } public Executor Executor { get; set; } private Dialogs _dialogs; @@ -16,11 +17,11 @@ public class GameAI // record activated count to prevent infinite actions private Dictionary _activatedCards; - public GameAI(GameClient game, Duel duel) + public GameAI(GameClient game, Duel duel, CoreFunction coreFunction) { Game = game; Duel = duel; - + CoreFunction = coreFunction; _dialogs = new Dialogs(game); _activatedCards = new Dictionary(); } diff --git a/Game/GameBehavior.cs b/Game/GameBehavior.cs index ff2cc939..9b198544 100644 --- a/Game/GameBehavior.cs +++ b/Game/GameBehavior.cs @@ -19,6 +19,7 @@ public class GameBehavior public Deck Deck { get; private set; } private GameAI _ai; + private CoreFunction _coreFunction; private IDictionary> _packets; private IDictionary> _messages; @@ -43,7 +44,8 @@ public GameBehavior(GameClient game) _room = new Room(); _duel = new Duel(); - _ai = new GameAI(Game, _duel); + _coreFunction = new CoreFunction(_duel, Connection); + _ai = new GameAI(Game, _duel, _coreFunction); _ai.Executor = DecksManager.Instantiate(_ai, _duel); Deck = Deck.Load(Game.DeckFile ?? _ai.Executor.Deck); @@ -84,6 +86,7 @@ private void RegisterPackets() _packets.Add(StocMessage.Chat, OnChat); _packets.Add(StocMessage.ChangeSide, OnChangeSide); _packets.Add(StocMessage.ErrorMsg, OnErrorMsg); + _packets.Add(StocMessage.AiReceive, OnAiReceive); _messages.Add(GameMessage.Retry, OnRetry); _messages.Add(GameMessage.Start, OnStart); @@ -146,6 +149,11 @@ private void RegisterPackets() _messages.Add(GameMessage.FlipSummoned, OnSummoned); } + private void OnAiReceive(BinaryReader packet) + { + _coreFunction.Data = packet.ReadBytes((int)packet.BaseStream.Length); + } + private void OnJoinGame(BinaryReader packet) { /*int lflist = (int)*/ packet.ReadUInt32(); diff --git a/WindBot.csproj b/WindBot.csproj index c40a8c76..d392fad1 100644 --- a/WindBot.csproj +++ b/WindBot.csproj @@ -67,6 +67,7 @@ + diff --git a/YGOSharp.Network.dll b/YGOSharp.Network.dll index 1df1f9c0..71535441 100644 Binary files a/YGOSharp.Network.dll and b/YGOSharp.Network.dll differ diff --git a/YGOSharp.OCGWrapper.Enums.dll b/YGOSharp.OCGWrapper.Enums.dll index 199ff7e6..422fe6e2 100644 Binary files a/YGOSharp.OCGWrapper.Enums.dll and b/YGOSharp.OCGWrapper.Enums.dll differ diff --git a/YGOSharp.OCGWrapper.dll b/YGOSharp.OCGWrapper.dll index 2d38e5ac..50425d8f 100644 Binary files a/YGOSharp.OCGWrapper.dll and b/YGOSharp.OCGWrapper.dll differ diff --git a/sqlite3.dll b/sqlite3.dll index f4fb34d3..0f219ebe 100644 Binary files a/sqlite3.dll and b/sqlite3.dll differ