zoukankan      html  css  js  c++  java
  • HearthBuddy卡牌无法识别

    界面上无法识别,提示是

    [Unidentified card ID :DAL_010]
    [Unidentified card ID :DAL_415]

    Unidentified card ID :HERO_02c

    首先使用卡牌工具,查询卡牌id对应的卡牌名字

    https://github.com/ChuckHearthstone/CardQuery

     1.添加卡牌id的枚举

    https://github.com/ChuckHearthstone/SilverFish/blob/89ca9e06327f1bd4271c5ebb2ece268530fc194e/DefaultRoutine/Chuck.SilverFish/Enums/CardIdEnum.cs#L1184

    2.添加卡牌的Sim

    最新的处理方案是,直接引用第三方的类库来做卡牌的数据解析

    https://www.nuget.org/packages/Chuck-HearthDb/   HearthBuddy的exe文件,引用这个类库

    然后修改卡牌代码的解析 https://github.com/ChuckHearthstone/SilverFish/blob/master/DefaultRoutine/Chuck.SilverFish/ai/CardDB.cs#L137

      private CardDB()
            {
                CardList.Clear();
                cardidToCardList.Clear();
    
                //placeholdercard
                Card plchldr = new Card {name = CardName.unknown, cost = 1000};
                namelist.Add("unknown");
                CardList.Add(plchldr);
                unknownCard = CardList[0];
    
                string name = "";
                var cards = Cards.All;
                foreach (var item in cards.Keys)
                {
                    var card = new Card();
                    allCardIDS.Add(item);
                    card.cardIDenum = ConvertHelper.cardIdstringToEnum(item);
                    var dbCard = cards[item];
                    card.EnglishName = dbCard.GetLocName(Locale.enUS);
                    card.ChineseName = dbCard.GetLocName(Locale.zhCN);
                    card.Health = dbCard.Health;
                    card.Class = (int) dbCard.Class;
                    card.Attack.Value = dbCard.Attack;
                    card.race = (int) dbCard.Race;
                    card.rarity = (int) dbCard.Rarity;
                    card.cost = dbCard.Cost;
                    card.type = (CardType) dbCard.Type;
                    if (card.type == CardType.Token)
                    {
                        card.isToken = true;
                    }
                    if (card.type == CardType.ENCHANTMENT)
                    {
                        continue;
                    }
    
                    var trimmedCardName = TrimHelper.TrimEnglishName(dbCard.Name);
                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        namelist.Add(trimmedCardName);
                    }
                    card.name = ConvertHelper.cardNamestringToEnum(trimmedCardName);
    
                    card.poisonous = dbCard.Entity.GetTag(GameTag.POISONOUS) == 1;
                    card.Enrage = dbCard.Entity.GetTag(GameTag.ENRAGED) == 1;
                    card.Aura = dbCard.Entity.GetTag(GameTag.AURA) == 1;
                    card.tank = dbCard.Entity.GetTag(GameTag.TAUNT) == 1;
                    card.battlecry= dbCard.Entity.GetTag(GameTag.BATTLECRY) == 1;
                    card.discover = dbCard.Entity.GetTag(GameTag.DISCOVER) == 1;
                    card.windfury = dbCard.Entity.GetTag(GameTag.WINDFURY) == 1;
                    card.deathrattle = dbCard.Entity.GetTag(GameTag.DEATHRATTLE) == 1;
                    card.Reborn = dbCard.Entity.GetTag(GameTag.REBORN) == 1;
                    card.Inspire = dbCard.Entity.GetTag(GameTag.INSPIRE) == 1;
                    card.Durability = dbCard.Entity.GetTag(GameTag.DURABILITY);
                    card.Elite = dbCard.Entity.GetTag(GameTag.ELITE) == 1;
                    card.Combo = dbCard.Entity.GetTag(GameTag.COMBO) == 1;
                    card.oneTurnEffect = dbCard.Entity.GetTag(GameTag.TAG_ONE_TURN_EFFECT) == 1;
                    card.overload = dbCard.Entity.GetTag(GameTag.OVERLOAD);
                    card.lifesteal = dbCard.Entity.GetTag(GameTag.LIFESTEAL) == 1;
                    card.untouchable = dbCard.Entity.GetTag(GameTag.UNTOUCHABLE) == 1;
                    card.Stealth = dbCard.Entity.GetTag(GameTag.STEALTH)==1;
                    card.Secret = dbCard.Entity.GetTag(GameTag.SECRET) == 1;
                    card.Quest = dbCard.Entity.GetTag(GameTag.QUEST) == 1;
                    card.Freeze = dbCard.Entity.GetTag(GameTag.FREEZE) == 1;
                    card.AdjacentBuff = dbCard.Entity.GetTag(GameTag.ADJACENT_BUFF) == 1;
                    card.DivineShield = dbCard.Entity.GetTag(GameTag.DIVINE_SHIELD) == 1;
                    card.Charge = dbCard.Entity.GetTag(GameTag.CHARGE) == 1;
                    card.Rush.Value = dbCard.Entity.GetTag(GameTag.RUSH) == 1;
                    card.Silence = dbCard.Entity.GetTag(GameTag.SILENCE) == 1;
                    card.Morph = dbCard.Entity.GetTag(GameTag.MORPH) == 1;
                    card.Spellpower = dbCard.Entity.GetTag(GameTag.SPELLPOWER) > 0;
                    card.spellpowervalue = dbCard.Entity.GetTag(GameTag.SPELLPOWER);
                    if (!string.IsNullOrEmpty(dbCard.Text))
                    {
                        if (dbCard.Text.ToLower().Contains("choose one"))
                        {
                            card.choice = true;
                        }
                    }
    
                    var playRequirements = dbCard.Entity.GetPlayRequirements();
                    if (playRequirements != null)
                    {
                        foreach (var playRequirement in playRequirements)
                        {
                            var reqId = Convert.ToInt32(playRequirement.ReqId);
                            var errorType = (ErrorType) Enum.ToObject(typeof(ErrorType), reqId);
                            card.playrequires.Add(errorType);
                        }
                    }
    
                    if (card.name != CardName.unknown)
                    {
                        CardList.Add(card);
                        if (!cardidToCardList.ContainsKey(card.cardIDenum))
                        {
                            cardidToCardList.Add(card.cardIDenum, card);
                        }
                        else
                        {
                            Logger.GetLoggerInstanceForType()
                                .ErrorFormat("[c.cardIDenum:" + card.cardIDenum + "] already exists in cardidToCardList");
                        }
                    }
                }
    
                teacherminion = getCardDataFromID(CardIdEnum.NEW1_026t);
                illidanminion = getCardDataFromID(CardIdEnum.EX1_614t);
                lepergnome = getCardDataFromID(CardIdEnum.EX1_029);
                burlyrockjaw = getCardDataFromID(CardIdEnum.GVG_068);
    
                Helpfunctions.Instance.InfoLog("CardList:" + cardidToCardList.Count);
    
            }

    分析(淘汰)

    搜索getcardid,在所有的相关函数处设置断点,看会进入哪里的断点

    发现是进入了namespace Triton.Game.Mapping

    [Attribute38("EntityBase")]
    public class EntityBase : MonoClass

    这个类

    public string GetCardId()
    {
        return base.method_13("GetCardId", Array.Empty<object>());
    }

    namespace Triton.Game

    public class HSCard

    public string Id
            {
                get
                {
                    return this.Entity_0.GetCardId();
                }
            }

    namespace HREngine.Bots

    public class Silverfish

    // HREngine.Bots.Silverfish
    // Token: 0x06000048 RID: 72 RVA: 0x0000A16C File Offset: 0x0000836C
    private void getDecks()
    {
        Dictionary<string, int> tmpDeck = new Dictionary<string, int>(this.startDeck);
        List<GraveYardItem> graveYard = new List<GraveYardItem>();
        Dictionary<CardDB.cardIDEnum, int> og = new Dictionary<CardDB.cardIDEnum, int>();
        Dictionary<CardDB.cardIDEnum, int> eg = new Dictionary<CardDB.cardIDEnum, int>();
        int owncontroler = TritonHs.OurHero.GetTag(GAME_TAG.CONTROLLER);
        int enemycontroler = TritonHs.EnemyHero.GetTag(GAME_TAG.CONTROLLER);
        this.turnDeck.Clear();
        this.noDuplicates = false;
        List<HSCard> allcards = TritonHs.GetAllCards();
        int allcardscount = allcards.Count;
        for (int i = 0; i < allcardscount; i++)
        {
            HSCard entity = allcards[i];
            if (entity.Id != null && !(entity.Id == ""))
            {
                if (CardDB.Instance.cardIdstringToEnum(entity.Id) == CardDB.cardIDEnum.UNG_116t)
                {
                    this.ownMinionsCost0 = true;
                }
                if (entity.GetZone() == TAG_ZONE.GRAVEYARD)
                {
                    CardDB.cardIDEnum cide = CardDB.Instance.cardIdstringToEnum(entity.Id);
                    GraveYardItem gyi = new GraveYardItem(cide, entity.EntityId, entity.GetTag(GAME_TAG.CONTROLLER) == owncontroler);
                    graveYard.Add(gyi);
                    if (entity.GetTag(GAME_TAG.CONTROLLER) == owncontroler)
                    {
                        if (og.ContainsKey(cide))
                        {
                            Dictionary<CardDB.cardIDEnum, int> dictionary;
                            CardDB.cardIDEnum key;
                            (dictionary = og)[key = cide] = dictionary[key] + 1;
                        }
                        else
                        {
                            og.Add(cide, 1);
                        }
                    }
                    else if (entity.GetTag(GAME_TAG.CONTROLLER) == enemycontroler)
                    {
                        if (eg.ContainsKey(cide))
                        {
                            Dictionary<CardDB.cardIDEnum, int> dictionary;
                            CardDB.cardIDEnum key;
                            (dictionary = eg)[key = cide] = dictionary[key] + 1;
                        }
                        else
                        {
                            eg.Add(cide, 1);
                        }
                    }
                    if (cide == CardDB.cardIDEnum.UNG_067t1)
                    {
                        this.ownCrystalCore = 5;
                    }
                }
                string entityId = entity.Id;
                TAG_ZONE entZone = entity.GetZone();
                if (i < 30)
                {
                    if (entityId != "")
                    {
                        if (entZone != TAG_ZONE.DECK)
                        {
                            if (tmpDeck.ContainsKey(entityId))
                            {
                                Dictionary<string, int> dictionary2;
                                string key2;
                                (dictionary2 = tmpDeck)[key2 = entityId] = dictionary2[key2] - 1;
                            }
                        }
                    }
                }
                else if (i >= 60 && entity.ControllerId == owncontroler)
                {
                    if (this.extraDeck.ContainsKey(i))
                    {
                        if (entityId != "" && entityId != this.extraDeck[i].id)
                        {
                            this.extraDeck[i].setId(entityId);
                        }
                        if (entZone == TAG_ZONE.DECK != this.extraDeck[i].isindeck)
                        {
                            this.extraDeck[i].setisindeck(entZone == TAG_ZONE.DECK);
                        }
                    }
                    else if (entZone == TAG_ZONE.DECK)
                    {
                        this.extraDeck.Add(i, new Silverfish.extraCard(entityId, true));
                    }
                }
            }
        }
        Action a = Ai.Instance.bestmove;
        foreach (KeyValuePair<int, Silverfish.extraCard> c in this.extraDeck)
        {
            if (c.Value.isindeck)
            {
                string entityId = c.Value.id;
                if (entityId == "")
                {
                    if (a != null)
                    {
                        actionEnum actionType = a.actionType;
                        if (actionType == actionEnum.playcard)
                        {
                            CardDB.cardIDEnum cardIDEnum = a.card.card.cardIDenum;
                            if (cardIDEnum <= CardDB.cardIDEnum.LOE_019t)
                            {
                                if (cardIDEnum == CardDB.cardIDEnum.BRM_007)
                                {
                                    goto IL_42B;
                                }
                                if (cardIDEnum != CardDB.cardIDEnum.LOE_002)
                                {
                                    if (cardIDEnum == CardDB.cardIDEnum.LOE_019t)
                                    {
                                        entityId = "LOE_019t2";
                                    }
                                }
                                else
                                {
                                    entityId = "LOE_002t";
                                }
                            }
                            else if (cardIDEnum != CardDB.cardIDEnum.LOE_079)
                            {
                                if (cardIDEnum == CardDB.cardIDEnum.LOE_104)
                                {
                                    goto IL_42B;
                                }
                                if (cardIDEnum == CardDB.cardIDEnum.LOE_110)
                                {
                                    entityId = "LOE_110t";
                                }
                            }
                            else
                            {
                                entityId = "LOE_019t";
                            }
                            goto IL_485;
                            IL_42B:
                            if (a.target != null)
                            {
                                entityId = a.target.handcard.card.cardIDenum.ToString();
                            }
                        }
                        IL_485:;
                    }
                    if (entityId == "")
                    {
                        Dictionary<CardDB.cardIDEnum, int> oldCardsOut = Probabilitymaker.Instance.enemyCardsOut;
                        foreach (KeyValuePair<CardDB.cardIDEnum, int> tmp in eg)
                        {
                            if (!oldCardsOut.ContainsKey(tmp.Key) || tmp.Value != oldCardsOut[tmp.Key])
                            {
                                CardDB.cardIDEnum cardIDEnum = tmp.Key;
                                if (cardIDEnum != CardDB.cardIDEnum.AT_035)
                                {
                                    if (cardIDEnum != CardDB.cardIDEnum.GVG_031)
                                    {
                                        if (cardIDEnum == CardDB.cardIDEnum.LOE_111)
                                        {
                                            entityId = "LOE_111";
                                        }
                                    }
                                    else
                                    {
                                        entityId = "aiextra1";
                                    }
                                }
                                else
                                {
                                    entityId = "AT_035t";
                                }
                            }
                        }
                        if (entityId == "" && this.lastpf != null)
                        {
                            int num = 0;
                            foreach (Minion j in this.enemyMinions)
                            {
                                if (j.handcard.card.cardIDenum == CardDB.cardIDEnum.GVG_056)
                                {
                                    num++;
                                }
                            }
                            if (num > 0)
                            {
                                foreach (Minion j in this.lastpf.enemyMinions)
                                {
                                    if (j.handcard.card.cardIDenum == CardDB.cardIDEnum.GVG_056)
                                    {
                                        num--;
                                    }
                                }
                            }
                            if (num > 0)
                            {
                                entityId = "GVG_056t";
                            }
                            else
                            {
                                num = 0;
                                foreach (Minion j in this.lastpf.ownMinions)
                                {
                                    if (j.handcard.card.cardIDenum == CardDB.cardIDEnum.GVG_035)
                                    {
                                        num++;
                                    }
                                }
                                if (num > 0)
                                {
                                    foreach (Minion j in this.ownMinions)
                                    {
                                        if (j.handcard.card.cardIDenum == CardDB.cardIDEnum.GVG_035)
                                        {
                                            num--;
                                        }
                                    }
                                }
                                if (num > 0)
                                {
                                    entityId = "GVG_035";
                                }
                            }
                        }
                    }
                    if (entityId == "")
                    {
                        entityId = "aiextra1";
                    }
                }
                c.Value.setId(entityId);
                CardDB.cardIDEnum ce = CardDB.Instance.cardIdstringToEnum(entityId);
                if (this.turnDeck.ContainsKey(ce))
                {
                    Dictionary<CardDB.cardIDEnum, int> dictionary;
                    CardDB.cardIDEnum key;
                    (dictionary = this.turnDeck)[key = ce] = dictionary[key] + 1;
                }
                else
                {
                    this.turnDeck.Add(ce, 1);
                }
            }
        }
        foreach (KeyValuePair<string, int> c2 in tmpDeck)
        {
            if (c2.Value >= 1)
            {
                CardDB.cardIDEnum ce = CardDB.Instance.cardIdstringToEnum(c2.Key);
                if (ce != CardDB.cardIDEnum.None)
                {
                    if (this.turnDeck.ContainsKey(ce))
                    {
                        Dictionary<CardDB.cardIDEnum, int> dictionary;
                        CardDB.cardIDEnum key;
                        (dictionary = this.turnDeck)[key = ce] = dictionary[key] + c2.Value;
                    }
                    else
                    {
                        this.turnDeck.Add(ce, c2.Value);
                    }
                }
            }
        }
        Probabilitymaker.Instance.setOwnCardsOut(og);
        Probabilitymaker.Instance.setEnemyCardsOut(eg);
        bool isTurnStart = false;
        if (Ai.Instance.nextMoveGuess.mana == -100)
        {
            isTurnStart = true;
            Ai.Instance.updateTwoTurnSim();
        }
        Probabilitymaker.Instance.setGraveYard(graveYard, isTurnStart);
        if (this.startDeck.Count != 0)
        {
            this.noDuplicates = true;
            foreach (int i in this.turnDeck.Values)
            {
                if (i > 1)
                {
                    this.noDuplicates = false;
                    break;
                }
            }
        }
    }

    在updateEverything函数里面的this.getDecks();的下一行设置断点,发现这个执行完,就看到卡牌错误提示

    // HREngine.Bots.Silverfish
    // Token: 0x06000044 RID: 68 RVA: 0x00008154 File Offset: 0x00006354
    public bool updateEverything(Behavior botbase, int numcal, out bool sleepRetry)
    {
        this.needSleep = false;
        this.updateBehaveString(botbase);
        this.ownPlayerController = TritonHs.OurHero.ControllerId;
        Hrtprozis.Instance.clearAllRecalc();
        Handmanager.Instance.clearAllRecalc();
        this.getHerostuff();
        this.getMinions();
        this.getHandcards();
        this.getDecks();
        Hrtprozis.Instance.updateTurnDeck(this.turnDeck, this.noDuplicates);
        Hrtprozis.Instance.setOwnPlayer(this.ownPlayerController);
        Handmanager.Instance.setOwnPlayer(this.ownPlayerController);
        this.numOptionPlayedThisTurn = 0;
        this.numOptionPlayedThisTurn += this.cardsPlayedThisTurn + this.ownHero.numAttacksThisTurn;
        foreach (Minion i in this.ownMinions)
        {
            if (i.Hp >= 1)
            {
                this.numOptionPlayedThisTurn += i.numAttacksThisTurn;
            }
        }
        List<HSCard> list = TritonHs.GetCards(CardZone.Graveyard, true);
        foreach (GraveYardItem gi in Probabilitymaker.Instance.turngraveyard)
        {
            if (gi.own)
            {
                foreach (HSCard entiti in list)
                {
                    if (gi.entity == entiti.EntityId)
                    {
                        this.numOptionPlayedThisTurn += entiti.NumAttackThisTurn;
                        break;
                    }
                }
            }
        }
        Hrtprozis.Instance.updatePlayer(this.ownMaxMana, this.currentMana, this.cardsPlayedThisTurn, this.numMinionsPlayedThisTurn, this.numOptionPlayedThisTurn, this.ueberladung, this.lockedMana, TritonHs.OurHero.EntityId, TritonHs.EnemyHero.EntityId);
        Hrtprozis.Instance.updateSecretStuff(this.ownSecretList, this.enemySecretList.Count);
        Hrtprozis.Instance.updateHero(this.ownWeapon, this.heroname, this.heroAbility, this.ownAbilityisReady, this.ownHeroPowerCost, this.ownHero, 10);
        Hrtprozis.Instance.updateHero(this.enemyWeapon, this.enemyHeroname, this.enemyAbility, false, this.enemyHeroPowerCost, this.enemyHero, this.enemyMaxMana);
        Questmanager.Instance.updatePlayedMobs(this.gTurnStep);
        Hrtprozis.Instance.updateMinions(this.ownMinions, this.enemyMinions);
        Hrtprozis.Instance.updateLurkersDB(this.LurkersDB);
        Handmanager.Instance.setHandcards(this.handCards, this.anzcards, this.enemyAnzCards);
        Hrtprozis.Instance.updateFatigueStats(this.ownDecksize, this.ownHeroFatigue, this.enemyDecksize, this.enemyHeroFatigue);
        Hrtprozis.Instance.updateJadeGolemsInfo(GameState.Get().GetFriendlySidePlayer().GetTag(GAME_TAG.JADE_GOLEM), GameState.Get().GetOpposingSidePlayer().GetTag(GAME_TAG.JADE_GOLEM));
        Hrtprozis.Instance.updateTurnInfo(this.gTurn, this.gTurnStep);
        this.updateCThunInfobyCThun();
        Hrtprozis.Instance.updateCThunInfo(this.anzOgOwnCThunAngrBonus, this.anzOgOwnCThunHpBonus, this.anzOgOwnCThunTaunt);
        Hrtprozis.Instance.updateCrystalCore(this.ownCrystalCore);
        Hrtprozis.Instance.updateOwnMinionsInDeckCost0(this.ownMinionsCost0);
        Probabilitymaker.Instance.setEnemySecretGuesses(this.enemySecretList);
        sleepRetry = this.needSleep;
        bool result;
        if (sleepRetry && numcal == 0)
        {
            result = false;
        }
        else
        {
            if (!Hrtprozis.Instance.setGameRule)
            {
                RulesEngine.Instance.setCardIdRulesGame(this.ownHero.cardClass, this.enemyHero.cardClass);
                Hrtprozis.Instance.setGameRule = true;
            }
            Playfield p = new Playfield();
            p.enemyCardsOut = new Dictionary<CardDB.cardIDEnum, int>(Probabilitymaker.Instance.enemyCardsOut);
            if (this.lastpf != null)
            {
                if (this.lastpf.isEqualf(p))
                {
                    return false;
                }
                if (p.gTurnStep > 0 && Ai.Instance.nextMoveGuess.ownMinions.Count == p.ownMinions.Count)
                {
                    if (Ai.Instance.nextMoveGuess.ownHero.Ready != p.ownHero.Ready && !p.ownHero.Ready)
                    {
                        sleepRetry = true;
                        Helpfunctions.Instance.ErrorLog("[AI] Hero ready = " + p.ownHero.Ready + ". Attempting recover....");
                        Ai.Instance.nextMoveGuess = new Playfield
                        {
                            mana = -100
                        };
                        return false;
                    }
                    for (int j = 0; j < p.ownMinions.Count; j++)
                    {
                        if (Ai.Instance.nextMoveGuess.ownMinions[j].Ready != p.ownMinions[j].Ready && !p.ownMinions[j].Ready)
                        {
                            sleepRetry = true;
                            Helpfunctions.Instance.ErrorLog(string.Concat(new object[]
                            {
                                "[AI] Minion ready = ",
                                p.ownMinions[j].Ready,
                                " (",
                                p.ownMinions[j].entitiyID,
                                " ",
                                p.ownMinions[j].handcard.card.cardIDenum,
                                " ",
                                p.ownMinions[j].name,
                                "). Attempting recover...."
                            }));
                            Ai.Instance.nextMoveGuess = new Playfield
                            {
                                mana = -100
                            };
                            return false;
                        }
                    }
                }
                Probabilitymaker.Instance.updateSecretList(p, this.lastpf);
                this.lastpf = p;
            }
            else
            {
                this.lastpf = p;
            }
            p = new Playfield();
            Helpfunctions.Instance.ErrorLog("calculating stuff... " + DateTime.Now.ToString("HH:mm:ss.ffff"));
            using (TritonHs.Memory.ReleaseFrame(true))
            {
                this.printstuff();
                Ai.Instance.dosomethingclever(botbase);
            }
            Helpfunctions.Instance.ErrorLog("calculating ended! " + DateTime.Now.ToString("HH:mm:ss.ffff"));
            if (this.sttngs.printRules > 0)
            {
                string[] rulesStr = Ai.Instance.bestplay.rulesUsed.Split(new char[]
                {
                    '@'
                });
                if (rulesStr.Count<string>() > 0 && rulesStr[0] != "")
                {
                    Helpfunctions.Instance.ErrorLog("ruleWeight " + Ai.Instance.bestplay.ruleWeight * -1);
                    foreach (string rs in rulesStr)
                    {
                        if (!(rs == ""))
                        {
                            Helpfunctions.Instance.ErrorLog("rule: " + rs);
                        }
                    }
                }
            }
            result = true;
        }
        return result;
    }

    namespace HREngine.Bots

    public class DefaultRoutine : IRoutine, IRunnable, IAuthored, IBase, IConfigurable

    在update everything函数调用的地方设置断点,发现执行pdate everything函数,就有错误提示。

    所以卡牌的错误,是在update everything里面出来的。

    // HREngine.Bots.DefaultRoutine
    // Token: 0x06000017 RID: 23 RVA: 0x00005A54 File Offset: 0x00003C54
    public async Task OurTurnLogic()
    {
        if (this.behave.BehaviorName() != DefaultRoutineSettings.Instance.DefaultBehavior)
        {
            this.behave = this.sf.getBehaviorByName(DefaultRoutineSettings.Instance.DefaultBehavior);
            Silverfish.Instance.lastpf = null;
        }
        if (this.learnmode && (TritonHs.IsInTargetMode() || TritonHs.IsInChoiceMode()))
        {
            await Coroutine.Sleep(50);
        }
        else if (TritonHs.IsInTargetMode())
        {
            if (this.dirtytarget >= 0)
            {
                DefaultRoutine.Log.Info("targeting...");
                HSCard source = null;
                if (this.dirtyTargetSource == 9000)
                {
                    source = TritonHs.OurHeroPowerCard;
                }
                else
                {
                    source = this.getEntityWithNumber(this.dirtyTargetSource);
                }
                HSCard target = this.getEntityWithNumber(this.dirtytarget);
                if (target == null)
                {
                    DefaultRoutine.Log.Error("target is null...");
                    TritonHs.CancelTargetingMode();
                }
                else
                {
                    this.dirtytarget = -1;
                    this.dirtyTargetSource = -1;
                    if (source == null)
                    {
                        await TritonHs.DoTarget(target);
                    }
                    else
                    {
                        await source.DoTarget(target);
                    }
                    await Coroutine.Sleep(555);
                }
            }
            else
            {
                DefaultRoutine.Log.Error("target failure...");
                TritonHs.CancelTargetingMode();
            }
        }
        else if (TritonHs.IsInChoiceMode())
        {
            await Coroutine.Sleep(555 + this.makeChoice());
            switch (this.dirtychoice)
            {
            case 0:
                TritonHs.ChooseOneClickMiddle();
                break;
            case 1:
                TritonHs.ChooseOneClickLeft();
                break;
            case 2:
                TritonHs.ChooseOneClickRight();
                break;
            }
            this.dirtychoice = -1;
            await Coroutine.Sleep(555);
        }
        else
        {
            bool sleepRetry = false;
            bool templearn = Silverfish.Instance.updateEverything(this.behave, 0, out sleepRetry);
            if (sleepRetry)
            {
                DefaultRoutine.Log.Error("[AI] Readiness error. Attempting recover...");
                await Coroutine.Sleep(500);
                templearn = Silverfish.Instance.updateEverything(this.behave, 1, out sleepRetry);
            }
            if (templearn)
            {
                this.printlearnmode = true;
            }
            if (this.learnmode)
            {
                if (this.printlearnmode)
                {
                    Ai.Instance.simmulateWholeTurnandPrint();
                }
                this.printlearnmode = false;
                await Coroutine.Sleep(50);
            }
            else
            {
                Action moveTodo = Ai.Instance.bestmove;
                if (moveTodo == null || moveTodo.actionType == actionEnum.endturn || Ai.Instance.bestmoveValue < -9999f)
                {
                    bool doEndTurn = false;
                    bool doConcede = false;
                    if (Ai.Instance.bestmoveValue > -10000f)
                    {
                        doEndTurn = true;
                    }
                    else if (Settings.Instance.concedeMode != 0)
                    {
                        doConcede = true;
                    }
                    else if (new Playfield().ownHeroHasDirectLethal())
                    {
                        Playfield lastChancePl = Ai.Instance.bestplay;
                        bool lastChance = false;
                        if (lastChancePl.owncarddraw > 0)
                        {
                            foreach (Handmanager.Handcard hc in lastChancePl.owncards)
                            {
                                if (hc.card.name == CardDB.cardName.unknown)
                                {
                                    lastChance = true;
                                }
                            }
                            if (!lastChance)
                            {
                                doConcede = true;
                            }
                        }
                        else
                        {
                            doConcede = true;
                        }
                        if (doConcede)
                        {
                            foreach (Minion i in lastChancePl.ownMinions)
                            {
                                if (i.playedThisTurn)
                                {
                                    CardDB.cardName name = i.handcard.card.name;
                                    if (name <= CardDB.cardName.nzoththecorruptor)
                                    {
                                        if (name != CardDB.cardName.barongeddon)
                                        {
                                            if (name != CardDB.cardName.cthun)
                                            {
                                                if (name == CardDB.cardName.nzoththecorruptor)
                                                {
                                                    lastChance = true;
                                                }
                                            }
                                            else
                                            {
                                                lastChance = true;
                                            }
                                        }
                                        else if (lastChancePl.enemyHero.Hp < 3)
                                        {
                                            lastChance = true;
                                        }
                                    }
                                    else if (name != CardDB.cardName.ragnarosthefirelord)
                                    {
                                        if (name != CardDB.cardName.sirfinleymrrgglton)
                                        {
                                            if (name == CardDB.cardName.yoggsaronhopesend)
                                            {
                                                lastChance = true;
                                            }
                                        }
                                        else
                                        {
                                            lastChance = true;
                                        }
                                    }
                                    else if (lastChancePl.enemyHero.Hp < 9)
                                    {
                                        lastChance = true;
                                    }
                                }
                            }
                        }
                        if (lastChance)
                        {
                            doConcede = false;
                        }
                    }
                    else if (moveTodo == null || moveTodo.actionType == actionEnum.endturn)
                    {
                        doEndTurn = true;
                    }
                    if (doEndTurn)
                    {
                        Helpfunctions.Instance.ErrorLog("end turn");
                        await TritonHs.EndTurn();
                        return;
                    }
                    if (doConcede)
                    {
                        Helpfunctions.Instance.ErrorLog("Lethal detected. Concede...");
                        Helpfunctions.Instance.logg("Concede... Lethal detected###############################################");
                        TritonHs.Concede(true);
                        return;
                    }
                }
                Helpfunctions.Instance.ErrorLog("play action");
                if (moveTodo == null)
                {
                    Helpfunctions.Instance.ErrorLog("moveTodo == null. EndTurn");
                    await TritonHs.EndTurn();
                }
                else
                {
                    moveTodo.print(false);
                    if (moveTodo.actionType == actionEnum.playcard)
                    {
                        Questmanager.Instance.updatePlayedCardFromHand(moveTodo.card);
                        HSCard cardtoplay = this.getCardWithNumber(moveTodo.card.entity);
                        if (cardtoplay == null)
                        {
                            Helpfunctions.Instance.ErrorLog("[Tick] cardtoplay == null");
                        }
                        else if (moveTodo.target != null)
                        {
                            HSCard target2 = this.getEntityWithNumber(moveTodo.target.entitiyID);
                            if (target2 != null)
                            {
                                Helpfunctions.Instance.ErrorLog(string.Concat(new object[]
                                {
                                    "play: ",
                                    cardtoplay.Name,
                                    " (",
                                    cardtoplay.EntityId,
                                    ") target: ",
                                    target2.Name,
                                    " (",
                                    target2.EntityId,
                                    ")"
                                }));
                                Helpfunctions.Instance.logg(string.Concat(new object[]
                                {
                                    "play: ",
                                    cardtoplay.Name,
                                    " (",
                                    cardtoplay.EntityId,
                                    ") target: ",
                                    target2.Name,
                                    " (",
                                    target2.EntityId,
                                    ") choice: ",
                                    moveTodo.druidchoice
                                }));
                                if (moveTodo.druidchoice >= 1)
                                {
                                    this.dirtytarget = moveTodo.target.entitiyID;
                                    this.dirtychoice = moveTodo.druidchoice;
                                    this.choiceCardId = moveTodo.card.card.cardIDenum.ToString();
                                }
                                this.dirtyTargetSource = moveTodo.card.entity;
                                this.dirtytarget = moveTodo.target.entitiyID;
                                await cardtoplay.Pickup(500);
                                if (moveTodo.card.card.type == CardDB.cardtype.MOB)
                                {
                                    await cardtoplay.UseAt(moveTodo.place);
                                }
                                else if (moveTodo.card.card.type == CardDB.cardtype.WEAPON)
                                {
                                    await cardtoplay.UseOn(target2.Card);
                                }
                                else if (moveTodo.card.card.type == CardDB.cardtype.SPELL)
                                {
                                    await cardtoplay.UseOn(target2.Card);
                                }
                                else
                                {
                                    await cardtoplay.UseOn(target2.Card);
                                }
                            }
                            else
                            {
                                Helpfunctions.Instance.ErrorLog("[AI] Target is missing. Attempting recover...");
                                Helpfunctions.Instance.logg("[AI] Target " + moveTodo.target.entitiyID + "is missing. Attempting recover...");
                            }
                            await Coroutine.Sleep(500);
                        }
                        else
                        {
                            Helpfunctions.Instance.ErrorLog(string.Concat(new object[]
                            {
                                "play: ",
                                cardtoplay.Name,
                                " (",
                                cardtoplay.EntityId,
                                ") target nothing"
                            }));
                            Helpfunctions.Instance.logg(string.Concat(new object[]
                            {
                                "play: ",
                                cardtoplay.Name,
                                " (",
                                cardtoplay.EntityId,
                                ") choice: ",
                                moveTodo.druidchoice
                            }));
                            if (moveTodo.druidchoice >= 1)
                            {
                                this.dirtychoice = moveTodo.druidchoice;
                                this.choiceCardId = moveTodo.card.card.cardIDenum.ToString();
                            }
                            this.dirtyTargetSource = -1;
                            this.dirtytarget = -1;
                            await cardtoplay.Pickup(500);
                            if (moveTodo.card.card.type == CardDB.cardtype.MOB)
                            {
                                await cardtoplay.UseAt(moveTodo.place);
                            }
                            else
                            {
                                await cardtoplay.Use();
                            }
                            await Coroutine.Sleep(500);
                        }
                    }
                    else if (moveTodo.actionType == actionEnum.attackWithMinion)
                    {
                        HSCard attacker = this.getEntityWithNumber(moveTodo.own.entitiyID);
                        HSCard target3 = this.getEntityWithNumber(moveTodo.target.entitiyID);
                        if (attacker != null)
                        {
                            if (target3 != null)
                            {
                                Helpfunctions.Instance.ErrorLog("minion attack: " + attacker.Name + " target: " + target3.Name);
                                Helpfunctions.Instance.logg("minion attack: " + attacker.Name + " target: " + target3.Name);
                                await attacker.DoAttack(target3);
                            }
                            else
                            {
                                Helpfunctions.Instance.ErrorLog("[AI] Target is missing. Attempting recover...");
                                Helpfunctions.Instance.logg("[AI] Target " + moveTodo.target.entitiyID + "is missing. Attempting recover...");
                            }
                        }
                        else
                        {
                            Helpfunctions.Instance.ErrorLog("[AI] Attacker is missing. Attempting recover...");
                            Helpfunctions.Instance.logg("[AI] Attacker " + moveTodo.own.entitiyID + " is missing. Attempting recover...");
                        }
                        await Coroutine.Sleep(250);
                    }
                    else if (moveTodo.actionType == actionEnum.attackWithHero)
                    {
                        HSCard attacker2 = this.getEntityWithNumber(moveTodo.own.entitiyID);
                        HSCard target4 = this.getEntityWithNumber(moveTodo.target.entitiyID);
                        if (attacker2 != null)
                        {
                            if (target4 != null)
                            {
                                this.dirtytarget = moveTodo.target.entitiyID;
                                Helpfunctions.Instance.ErrorLog("heroattack: " + attacker2.Name + " target: " + target4.Name);
                                Helpfunctions.Instance.logg("heroattack: " + attacker2.Name + " target: " + target4.Name);
                                this.dirtyTargetSource = moveTodo.own.entitiyID;
                                this.dirtytarget = moveTodo.target.entitiyID;
                                await attacker2.DoAttack(target4);
                            }
                            else
                            {
                                Helpfunctions.Instance.ErrorLog("[AI] Target is missing. Attempting recover...");
                                Helpfunctions.Instance.logg("[AI] Target " + moveTodo.target.entitiyID + "is missing (H). Attempting recover...");
                            }
                        }
                        else
                        {
                            Helpfunctions.Instance.ErrorLog("[AI] Attacker is missing. Attempting recover...");
                            Helpfunctions.Instance.logg("[AI] Attacker " + moveTodo.own.entitiyID + " is missing (H). Attempting recover...");
                        }
                        await Coroutine.Sleep(250);
                    }
                    else if (moveTodo.actionType == actionEnum.useHeroPower)
                    {
                        HSCard cardtoplay2 = TritonHs.OurHeroPowerCard;
                        if (moveTodo.target != null)
                        {
                            HSCard target5 = this.getEntityWithNumber(moveTodo.target.entitiyID);
                            if (target5 != null)
                            {
                                Helpfunctions.Instance.ErrorLog("use ablitiy: " + cardtoplay2.Name + " target " + target5.Name);
                                Helpfunctions.Instance.logg(string.Concat(new string[]
                                {
                                    "use ablitiy: ",
                                    cardtoplay2.Name,
                                    " target ",
                                    target5.Name,
                                    (moveTodo.druidchoice > 0) ? (" choice: " + moveTodo.druidchoice) : ""
                                }));
                                if (moveTodo.druidchoice > 0)
                                {
                                    this.dirtytarget = moveTodo.target.entitiyID;
                                    this.dirtychoice = moveTodo.druidchoice;
                                    this.choiceCardId = moveTodo.card.card.cardIDenum.ToString();
                                }
                                this.dirtyTargetSource = 9000;
                                this.dirtytarget = moveTodo.target.entitiyID;
                                await cardtoplay2.Pickup(500);
                                await cardtoplay2.UseOn(target5.Card);
                            }
                            else
                            {
                                Helpfunctions.Instance.ErrorLog("[AI] Target is missing. Attempting recover...");
                                Helpfunctions.Instance.logg("[AI] Target " + moveTodo.target.entitiyID + "is missing. Attempting recover...");
                            }
                            await Coroutine.Sleep(500);
                        }
                        else
                        {
                            Helpfunctions.Instance.ErrorLog("use ablitiy: " + cardtoplay2.Name + " target nothing");
                            Helpfunctions.Instance.logg("use ablitiy: " + cardtoplay2.Name + " target nothing" + ((moveTodo.druidchoice > 0) ? (" choice: " + moveTodo.druidchoice) : ""));
                            if (moveTodo.druidchoice >= 1)
                            {
                                this.dirtychoice = moveTodo.druidchoice;
                                this.choiceCardId = moveTodo.card.card.cardIDenum.ToString();
                            }
                            this.dirtyTargetSource = -1;
                            this.dirtytarget = -1;
                            await cardtoplay2.Pickup(500);
                        }
                    }
                    else
                    {
                        await TritonHs.EndTurn();
                    }
                }
            }
        }
    }

    最后发现错误提示,是从

    namespace HREngine.Bots

    public class CardDB里面报错的

    把cardid的字符串转换为cardIDEnum的时候出错

    public CardDB.cardIDEnum cardIdstringToEnum(string s)
            {
                CardDB.cardIDEnum CardEnum;
                CardDB.cardIDEnum result;
                if (Enum.TryParse<CardDB.cardIDEnum>(s, false, out CardEnum))
                {
                    result = CardEnum;
                }
                else
                {
                    Logger.GetLoggerInstanceForType().ErrorFormat("[Unidentified card ID :" + s + "]", new object[0]);
                    result = CardDB.cardIDEnum.None;
                }
                return result;
            }

    根据我的印象,https://github.com/HearthSim/Hearthdb 这个项目就是用来生成卡牌的。

    1.生成data

    clone项目,编译之后,得到能识别的的CardDefs.xml。然后重命名成_carddb.txt,然后替换掉HearthBuddy里面的

    2.自己实现卡牌

    另外,这个文件不在HearthBuddy的exe里面,是外部加载进来的。HearthbuddyReleaseRoutinesDefaultRoutineSilverfishaiCardDB.cs

    卡牌的实现需要自己写在Silverfishcards文件夹下,并且卡牌在实现的时候,根据需要从Silverfishai的某一个类中继承,实现对应的方法

     github上面尝试找了一下实现https://github.com/search?l=C%23&o=desc&q=getBattlecryEffect&s=indexed&type=Code

    <Entity CardID="DAL_010" ID="51375" version="2">
    <MasterPower>773590e3-24fa-4564-994a-94049b32d3f3</MasterPower>
    <Tag enumID="185" name="CARDNAME" type="LocString">
    <deDE>Togwaggels Plan</deDE>
    <enUS>Togwaggle's Scheme</enUS>
    <esES>Plan de Togafloja</esES>
    <esMX>Complot de Togwaggle</esMX>
    <frFR>Manœuvre de Cire-Pilleur</frFR>
    <itIT>Piano di Cobaldo</itIT>
    <jaJP>トグワグルの計略</jaJP>
    <koKR>토그왜글의 계략</koKR>
    <plPL>Intryga Trzęsibrzucha</plPL>
    <ptBR>Estratagema de Fubalumba</ptBR>
    <ruRU>Козни Вихлепыха</ruRU>
    <thTH>แผนการของท็อกแว็กเกิล</thTH>
    <zhCN>托瓦格尔的阴谋</zhCN>
    <zhTW>托戈瓦哥的陰謀</zhTW>
    </Tag>

    <Entity CardID="DAL_415" ID="52111" version="2">
    <MasterPower>2ef4d4c2-dbdf-4ae4-9f14-079984458f86</MasterPower>
    <Tag enumID="185" name="CARDNAME" type="LocString">
    <deDE>Ü.B.E.L.-Täter</deDE>
    <enUS>EVIL Miscreant</enUS>
    <esES>Malhechor del MAL</esES>
    <esMX>Bellaco del MAL</esMX>
    <frFR>Voyou du M.A.L.</frFR>
    <itIT>Furfante del M.A.L.E.</itIT>
    <jaJP>悪党同盟の悪漢</jaJP>
    <koKR>잔.악.무.도. 악당</koKR>
    <plPL>Szubrawiec Ligi Z.Ł.A.</plPL>
    <ptBR>Mandrião da MAL</ptBR>
    <ruRU>Негодяй ЗЛА</ruRU>
    <thTH>จอมโฉด EVIL</thTH>
    <zhCN>怪盗恶霸</zhCN>
    <zhTW>邪惡陣線無賴</zhTW>
    </Tag>

    对了,貌似贴吧已经有部分教程了。https://tieba.baidu.com/p/5663869359

    偶数萨电鳗狼王添加方法

    ==================================
    1.编写新卡SIM,
    在HearthbuddyRoutinesDefaultRoutineSilverfishcards,
    在目录下新建一个Sim_扩展包缩写+卡牌编号.cs文件,
    编写SIM后保存。
    ==================================
    2.编写并增加新卡识别信息,
    HearthbuddyRoutinesDefaultRoutineSilverfishdata 下的 _carddb.txt 文件,
    其中存储所有卡牌信息。
    含:185、184等等。
    注意特效卡牌后面添加playRequirement,
    每个节点后退两个字符。
    (上述是新卡描述)
    ==================================
    3.增加新卡编号及英文名称
    在RoutinesDefaultRoutineSilverfishai的CardDB.cs中的3550行后增加新卡
    扩展包简称_卡牌编号,
    如:
    LOOT_149,
    LOOT_149e,
    扩展包简称均为大写,可以联想GVG,
    ==================================
    在RoutinesDefaultRoutineSilverfishai的CardDB.cs中的6303行后,增加新增卡牌英文名称。
    注意卡牌英文名称没有空格且奇数偶数卡牌需添加两个名字,编写两个卡牌信息。
    2费电鳗murksparkeel
    6费偶数狼王geengreymane
    战斗号角calltoarms
    5费吵吵gigglingInventor
    5费菌菇fungalmancer
    3费荆棘Hench-ClanThug
    刺杀花vilespineslayer
    9费奇数bakuthemooneater

     实际操作

    发现阴燃电鳗无法识别

    https://github.com/chucklu/HearthBuddyAnalyze/tree/master/CardQuery

    使用工具,查询

    阴燃电鳗的战吼效果和火元素类似,查找火元素的编号CS2_042,

    然后在solution explorer搜索这个编号,找到

     注释居然是法语

        class Sim_CS2_042 : SimTemplate //fireelemental
        {
    
    //    kampfschrei:/ verursacht 3 schaden.
            public override void getBattlecryEffect(Playfield p, Minion own, Minion target, int choice)
            {
                int dmg = 3;
                p.minionGetDamageOrHeal(target, dmg);
               
            }
    
        }

     public enum cardIDEnum 里面需要新加一个卡牌枚举

    可能还需要加一个类似Pen_CS2_042.cs的 

    在整个解决方案搜火元素的名字fireelemental

     public enum cardName需要添加一个枚举,这里的cardName就是在下面记录伤害和记录血量的地方使用

    public Dictionary<CardDB.cardName, int> DamageTargetDatabase = new Dictionary<CardDB.cardName, int>();  记录伤害的

    Dictionary<CardDB.cardName, int> GangUpDatabase = new Dictionary<CardDB.cardName, int>(); 这个应该是卡牌的评分

     

    GangUpDatabase.Add(CardDB.cardName.emperorthaurissan, 5);

    {
    "Id": "BRM_028",
    "DbfId": 2262,
    "Name": "索瑞森大帝",
    "Text": "在你的回合结束时,你所有手牌的法力值消耗减少(1)点。",
    "FlavorText": "把一个邪恶的炎魔之王召唤到这个世界上,然后看着这个家伙奴役了他所有的子民并非是他最为后悔的事情。",
    "Class": "NEUTRAL",
    "Rarity": "LEGENDARY",
    "Type": "MINION",
    "Race": "INVALID",
    "Set": "BRM",
    "Faction": "INVALID",
    "Cost": 6,
    "Attack": 5,
    "Health": 5,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "Wayne Reynolds",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }


    GangUpDatabase.Add(CardDB.cardName.etherealpeddler, 3);

    {
    "Id": "KAR_070",
    "DbfId": 39700,
    "Name": "虚灵商人",
    "Text": "<b>战吼:</b>如果你的手牌中有其他职业的卡牌,则其法力值消耗减少(2)点。",
    "FlavorText": "虚灵以热衷收集和买卖各种魔法物品和神器而著称,比那些贪婪的地精靠谱多了。",
    "Class": "ROGUE",
    "Rarity": "RARE",
    "Type": "MINION",
    "Race": "INVALID",
    "Set": "KARA",
    "Faction": "INVALID",
    "Cost": 5,
    "Attack": 5,
    "Health": 6,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [
    "Battlecry"
    ],
    "ArtistName": "Alex Horley Orlandelli",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }


    GangUpDatabase.Add(CardDB.cardName.felcannon, 0);

    {
    "Id": "GVG_020",
    "DbfId": 1997,
    "Name": "邪能火炮",
    "Text": "在你的回合结束时,对一个非机械随从造成2点伤害。",
    "FlavorText": "包装盒上写着:全新改良,比旧款更邪门!",
    "Class": "WARLOCK",
    "Rarity": "RARE",
    "Type": "MINION",
    "Race": "MECHANICAL",
    "Set": "GVG",
    "Faction": "INVALID",
    "Cost": 4,
    "Attack": 3,
    "Health": 5,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "Matt Gaser",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }


    GangUpDatabase.Add(CardDB.cardName.fireelemental, 5);

    {
    "Id": "CS2_042",
    "DbfId": 189,
    "Name": "火元素",
    "Text": "<b>战吼:</b>造成3点伤害。",
    "FlavorText": "他从来不洗澡。嗯...",
    "Class": "SHAMAN",
    "Rarity": "FREE",
    "Type": "MINION",
    "Race": "ELEMENTAL",
    "Set": "CORE",
    "Faction": "NEUTRAL",
    "Cost": 6,
    "Attack": 6,
    "Health": 5,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [
    "Battlecry"
    ],
    "ArtistName": "Ralph Horsley",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": false
    }


    GangUpDatabase.Add(CardDB.cardName.fireguarddestroyer, 4);

    {
    "Id": "BRM_012",
    "DbfId": 2290,
    "Name": "火焰驱逐者",
    "Text": "<b>战吼:</b>获得1-4点攻击力。<b>过载:</b>(1)",
    "FlavorText": "很多火元素竞相面试“火焰驱逐者”的职位,但拉格纳罗斯认为只有极少数火元素能够胜任。",
    "Class": "SHAMAN",
    "Rarity": "COMMON",
    "Type": "MINION",
    "Race": "ELEMENTAL",
    "Set": "BRM",
    "Faction": "INVALID",
    "Cost": 4,
    "Attack": 3,
    "Health": 6,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [
    "Battlecry"
    ],
    "ArtistName": "Paul Mafayon",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }


    GangUpDatabase.Add(CardDB.cardName.flametonguetotem, 4);

    {
    "Id": "EX1_565",
    "DbfId": 1008,
    "Name": "火舌图腾",
    "Text": "相邻的随从获得+2攻击力。",
    "FlavorText": "图腾制造师喜欢用最稀有的木材来打造图腾。甚至有传言说,这些图腾是由埃隆巴克保护者身上的树皮做的。",
    "Class": "SHAMAN",
    "Rarity": "FREE",
    "Type": "MINION",
    "Race": "TOTEM",
    "Set": "CORE",
    "Faction": "NEUTRAL",
    "Cost": 3,
    "Attack": 0,
    "Health": 3,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "Jonathan Ryder",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": false
    }


    GangUpDatabase.Add(CardDB.cardName.flamewaker, 4);

    {
    "Id": "BRM_002",
    "DbfId": 2275,
    "Name": "火妖",
    "Text": "在你施放一个法术后,造成2点伤害,随机分配到所有敌人身上。",
    "FlavorText": "他们深居于炎热的洞窟之中,听候管理者的命令:消灭一切胆敢打扰炎魔之王的敌人。",
    "Class": "MAGE",
    "Rarity": "RARE",
    "Type": "MINION",
    "Race": "INVALID",
    "Set": "BRM",
    "Faction": "INVALID",
    "Cost": 3,
    "Attack": 2,
    "Health": 4,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "Alex Horley Orlandelli",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }


    GangUpDatabase.Add(CardDB.cardName.flesheatingghoul, 0);

    {
    "Id": "tt_004",
    "DbfId": 397,
    "Name": "腐肉食尸鬼",
    "Text": "每当一个随从死亡,便获得+1攻击力。",
    "FlavorText": "诟病食尸鬼吃“腐肉”其实对它们并不公平,它们只是没有别的可吃了而已。",
    "Class": "NEUTRAL",
    "Rarity": "COMMON",
    "Type": "MINION",
    "Race": "INVALID",
    "Set": "EXPERT1",
    "Faction": "NEUTRAL",
    "Cost": 3,
    "Attack": 2,
    "Health": 3,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "Alex Horley Orlandelli",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": false
    }


    GangUpDatabase.Add(CardDB.cardName.floatingwatcher, 0);  漂浮观察者,术士卡,544

    {
    "Id": "GVG_100",
    "DbfId": 2068,
    "Name": "漂浮观察者",
    "Text": "每当你的英雄在你的回合受到伤害,便获得+2/+2。",
    "FlavorText": "和他对话时,你很难与之进行眼神交流。",
    "Class": "WARLOCK",
    "Rarity": "COMMON",
    "Type": "MINION",
    "Race": "DEMON",
    "Set": "GVG",
    "Faction": "INVALID",
    "Cost": 5,
    "Attack": 4,
    "Health": 4,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "Todd Lockwood",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }


    GangUpDatabase.Add(CardDB.cardName.foereaper4000, 1);   死神4000型,中立卡

    {
    "Id": "GVG_113",
    "DbfId": 2081,
    "Name": "死神4000型",
    "Text": "同时对其攻击目标相邻的随从造成伤害。",
    "FlavorText": "对于田里的庄稼来说,所有的收割机都是死神。",
    "Class": "NEUTRAL",
    "Rarity": "LEGENDARY",
    "Type": "MINION",
    "Race": "MECHANICAL",
    "Set": "GVG",
    "Faction": "INVALID",
    "Cost": 8,
    "Attack": 6,
    "Health": 9,
    "Durability": 0,
    "Armor": 0,
    "Mechanics": [],
    "ArtistName": "James Ryman",
    "EntourageCardIds": [],
    "DefaultLanguage": "zhCN",
    "Collectible": true,
    "IsWild": true
    }

  • 相关阅读:
    ansible
    爬虫框架之scrapy
    Mongodb
    xml 创建 添加节点或属性(自定义,复制)
    web站点崩溃的原因总结
    C# 关闭正在执行的文件
    254. Factor Combinations
    256. Paint House
    156. Binary Tree Upside Down
    170. Two Sum III
  • 原文地址:https://www.cnblogs.com/chucklu/p/11192069.html
Copyright © 2011-2022 走看看