Ejemplo n.º 1
0
        private void PrintInfo(ConvertError overallError, ConvertResult source, ConvertResult destination)
        {
            string prefix = "ERROR";

            if (overallError == ConvertError.Warning)
            {
                prefix = "WARNING";
            }
            Console.WriteLine($"{prefix}: \"{source.File}\" to\"{destination.File}\"");

            if (!string.IsNullOrWhiteSpace(source.Message))
            {
                Console.WriteLine($"Source Msg: {source.Message}");
            }
            if (!string.IsNullOrWhiteSpace(destination.Message))
            {
                Console.WriteLine($"Destination Msg: {destination.Message}");
            }
        }
Ejemplo n.º 2
0
        //用Socket方式发送给UR一个字符串,该字符串已经是一个六维向量,UR可以直接拿来用,就是走这个坐标值就行了,在UR上面不需要做任何设置
        //采用socket纯主机的方式优点是代码都藏在上位机中,方便调试和实现复杂应用,而且别人不好抄袭或者模仿,因为UR的程序是很好破解的
        private void btn_TriggerSocket_Click(object sender, EventArgs e)
        {
            try
            {
                //1 把当前的特征的XY像素坐标计算出相对于O点的差值(注意这里对我填到文本框里的结果要*2,因为实际确实是他的两倍
                double PixelDiff_X = (Convert.ToDouble(label_X.Text) - (Convert.ToDouble(txt_O_X.Text) * 2));
                double PixelDiff_Y = (Convert.ToDouble(label_Y.Text) - (Convert.ToDouble(txt_O_Y.Text) * 2));

                //2 把这个差值转换为实际的mm差值(我们在前面已经得到了像素精度),最后再转换成M做向量合成
                double RealDiff_X = Convert.ToDouble(label_Accurary.Text) * PixelDiff_X / 1000;
                double RealDiff_Y = Convert.ToDouble(label_Accurary.Text) * PixelDiff_Y / 1000;
                //角度值和弧度值都取出来,想用哪个用哪个
                double PixelDiff_R_Angle  = Convert.ToDouble(label_R_Angle.Text);
                double PixelDiff_R_Radius = Convert.ToDouble(label_R_Radius.Text);

                //3 把得到的两个差值放射到OA和OB两个方向向量中(只关心XYZ,不关心UVW)
                ObjectVectorOA[0] = CurrentActiveOA[0] * RealDiff_X;
                ObjectVectorOA[1] = CurrentActiveOA[1] * RealDiff_X;
                ObjectVectorOA[2] = CurrentActiveOA[2] * RealDiff_X;
                ObjectVectorOA[3] = 0;
                ObjectVectorOA[4] = 0;
                ObjectVectorOA[5] = 0;

                ObjectVectorOB[0] = CurrentActiveOB[0] * RealDiff_Y;
                ObjectVectorOB[1] = CurrentActiveOB[1] * RealDiff_Y;
                ObjectVectorOB[2] = CurrentActiveOB[2] * RealDiff_Y;
                ObjectVectorOB[3] = 0;
                ObjectVectorOB[4] = 0;
                ObjectVectorOB[5] = 0;

                //4 得到最终的向量

                ObjectVectorTotal[0] = ObjectVectorOA[0] + ObjectVectorOB[0];
                ObjectVectorTotal[1] = ObjectVectorOA[1] + ObjectVectorOB[1];
                ObjectVectorTotal[2] = ObjectVectorOA[2] + ObjectVectorOB[2];
                ObjectVectorTotal[3] = 0;
                ObjectVectorTotal[4] = 0;
                ObjectVectorTotal[5] = 0;

                //5 向目标UR发送指定向量(注意UR从拍照位置SnapPos就不需要再去这个O点,再用get_forward_kin()获取一遍数值,这样反而麻烦,所以直接和实际的O点坐标合成即可)
                ObjectVectorFinal[0] = ObjectVectorTotal[0] + PosInt1[0];
                ObjectVectorFinal[1] = ObjectVectorTotal[1] + PosInt1[1];
                ObjectVectorFinal[2] = ObjectVectorTotal[2] + PosInt1[2];
                ObjectVectorFinal[3] = PosInt1[3];
                ObjectVectorFinal[4] = PosInt1[4];
                ObjectVectorFinal[5] = PosInt1[5];

                //string OriginalPos = GetPoseString(PosInt1);
                string NewPos = GetPoseString(ObjectVectorFinal);

                //注意这里就通过纯上位机控制了,UR上不写任何程序了
                if (ifConnected)
                {
                    //注意虽然发送的只是一个movel指令,里面有一个表示UR位置的六维向量,我们仍然无法把角度值直接传递过去
                    //比如movel(p[x,y,z,u,v,w])跟movel(p[x,y,z,u,v,w+3.14])的区别,并不是最后一个轴旋转180度的效果
                    //movej[A,B,C,D,E,F,G]跟movej[A,B,C,D,E,F,G+3.14]倒是真的这个关系,可惜我们已然要求movel方式移动了
                    //其实解决方法就是直接发送一串函数,让UR自己去用pose_add翻译出到底我要最后一个关节旋转指定角度如何分配到最后三个关节值上

                    /*
                     * //下面的代码如果是单纯的移动,不需要转换关节角度值可以这么干
                     * string CMD = "movel(" + NewPos + ",v = 0.1)";
                     * URController.Send_command(CMD);
                     */

                    string Embed_head      = "def VisionCatch_test():\r\n";
                    string Embed_NewPos    = "NewPos = " + NewPos + "\r\n";
                    string Embed_RotatePos = "RotatePos = p[0,0,0,0,0," + -PixelDiff_R_Radius + "]\r\n";
                    string Embed_TotalPos  = "TotalPos = pose_add(NewPos,RotatePos)\r\n";
                    string Embed_CMD       = "movel(TotalPos,v = 0.1)\r\n";
                    string Embed_Bottom    = "end\r\n";
                    string Embed_Run       = "VisionCatch_test()\r\n";

                    textBoxCommand.Text = "";
                    textBoxCommand.Text = Embed_head + Embed_NewPos + Embed_RotatePos + Embed_TotalPos + Embed_CMD + Embed_Bottom + Embed_Run;

                    string CMD = textBoxCommand.Text;
                    URController.Send_command(CMD);
                }
                else
                {
                    MessageBox.Show("请确认目标UR已连接");
                }

                //把每次比对的差值放到listBox中方便查看
                this.listBox_Debug.Items.Clear();
                this.listBox_Debug.Items.Add("特征像素差(px):X" + PixelDiff_X.ToString("0.0"));
                this.listBox_Debug.Items.Add("特征像素差(px):Y" + PixelDiff_Y.ToString("0.0"));
                this.listBox_Debug.Items.Add("特征实际差(mm):X" + RealDiff_X.ToString("0.0000"));
                this.listBox_Debug.Items.Add("特征实际差(mm):Y" + RealDiff_Y.ToString("0.0000"));

                this.listBox_Debug.Items.Add("基准向量OA:" + GetPoseString(CurrentActiveOA));
                this.listBox_Debug.Items.Add("基准向量OB:" + GetPoseString(CurrentActiveOB));

                this.listBox_Debug.Items.Add("差异向量OA:" + GetPoseString(ObjectVectorOA));
                this.listBox_Debug.Items.Add("差异向量OB:" + GetPoseString(ObjectVectorOB));

                this.listBox_Debug.Items.Add("参考基准向量:" + GetPoseString(PosInt1));
                this.listBox_Debug.Items.Add("差异向量整体:" + GetPoseString(ObjectVectorTotal));

                this.listBox_Debug.Items.Add("合成向量整体:" + GetPoseString(ObjectVectorFinal));
            }
            catch (Exception ConvertError)
            {
                MessageBox.Show("数据转换出错" + ConvertError.ToString());
            }
        }
        /// <summary>
        /// Converts an ability from a generic format to TFS rev script system spell format
        /// </summary>
        /// <param name="spell"></param>
        /// <returns>ConvertError, attack in string format OR error message</returns>
        public Tuple <ConvertError, string> GenericToTfsRevScriptSysSpells(ref Spell spell)
        {
            ConvertError error  = ConvertError.Success;
            string       attack = "";

            if (spell.DefinitionStyle == SpellDefinition.TfsLuaScript)
            {
                attack = $"	{{script =\"{spell.Name}\", interval = {spell.Interval}, chance = {spell.Chance * 100:0}";

                if ((spell.MinDamage != null) && (spell.MaxDamage != null))
                {
                    attack += $", minDamage = {spell.MinDamage}, maxDamage = {spell.MaxDamage}";
                }
                else if (spell.MaxDamage != null)
                {
                    attack += $", maxDamage = {spell.MaxDamage}";
                }
                if (spell.OnTarget != null)
                {
                    attack += $", target = { spell.OnTarget.ToString().ToLower()}";
                }
                if (spell.IsDirectional != null)
                {
                    attack += $", direction = { spell.IsDirectional.ToString().ToLower()}";
                }
                attack += "}";
            }
            else if (spell.DefinitionStyle == SpellDefinition.Raw)
            {
                attack = $"	{{name =\"{spell.Name}\", interval = {spell.Interval}, chance = {spell.Chance * 100:0}";


                if (spell.Name == "melee")
                {
                    if ((spell.MinDamage != null) && (spell.MaxDamage != null))
                    {
                        attack += $", minDamage = {spell.MinDamage}, maxDamage = {spell.MaxDamage}";
                    }
                    else if (spell.MaxDamage != null)
                    {
                        attack += $", maxDamage = {spell.MaxDamage}";
                    }
                    else if ((spell.AttackValue != null) && (spell.Skill != null))
                    {
                        attack += $", skill = {spell.Skill}, attack = {spell.AttackValue}";
                    }
                    //else continue which we should never hit?

                    attack += $", effect = {magicEffectNames[Effect.DrawBlood]}";

                    if (spell.Condition != ConditionType.None)
                    {
                        attack += $", condition = {{type = {ConditionToTfsConstant[spell.Condition]}, startDamage = {spell.StartDamage}, interval = {spell.Tick}}}";
                    }
                }
                else
                {
                    if (spell.Name == "speed")
                    {
                        attack += $", speed = {{min = {spell.MinSpeedChange}, max = {spell.MaxSpeedChange}}}";
                    }
                    else if (spell.Name == "condition")
                    {
                        attack += $", type = {ConditionToTfsConstant[spell.Condition]}, startDamage = {spell.StartDamage}, tick = {spell.Tick}";
                    }
                    else if (spell.Name == "outfit")
                    {
                        if (!string.IsNullOrEmpty(spell.MonsterName))
                        {
                            attack += $", monster = \"{spell.MonsterName}\"";
                        }
                        else if (spell.ItemId != null)
                        {
                            attack += $", item = {spell.ItemId}";
                        }
                    }
                    else if ((spell.Name == "combat") && (spell.DamageElement != null))
                    {
                        attack += $", type = {CombatDamageNames[(CombatDamage)spell.DamageElement]}";
                    }
                    else if (spell.Name == "drunk")
                    {
                        attack += $", drunkenness = {spell.Drunkenness * 100:0}";
                    }

                    if ((spell.MinDamage != null) && (spell.MaxDamage != null))
                    {
                        attack += $", minDamage = {spell.MinDamage}, maxDamage = {spell.MaxDamage}";
                    }
                    else if (spell.MaxDamage != null)
                    {
                        attack += $", minDamage = {spell.MinDamage}";
                    }
                    if (spell.Duration != null)
                    {
                        attack += $", duration = {spell.Duration}";
                    }
                    if (spell.Range != null)
                    {
                        attack += $", range = {spell.Range}";
                    }
                    if (spell.Radius != null)
                    {
                        attack += $", radius = {spell.Radius}, target = {spell.OnTarget.ToString().ToLower()}";
                    }
                    if (spell.Length != null)
                    {
                        attack += $", length = {spell.Length}";
                    }
                    if (spell.Spread != null)
                    {
                        attack += $", spread = {spell.Spread}";
                    }
                    if (spell.ShootEffect != Animation.None)
                    {
                        attack += $", ShootEffect = {shootTypeNames[spell.ShootEffect]}";
                    }
                    if (spell.AreaEffect != Effect.None)
                    {
                        attack += $", effect = {magicEffectNames[spell.AreaEffect]}";
                    }
                }
                attack += "}";
            }
            else
            {
                error  = ConvertError.Warning;
                attack = $"Can't convert abilitiy name {spell.Name} with DefinitionStyles {spell.DefinitionStyle}";
            }

            return(new(error, attack));
        }
        public override ConvertResult WriteMonster(string directory, ref Monster monster)
        {
            ConvertError code     = ConvertError.Success;
            string       message  = "";
            string       fileName = Path.Combine(directory, monster.FileName + "." + FileExt);

            using (var fstream = File.OpenWrite(fileName))
                using (var dest = new StreamWriter(fstream))
                {
                    fstream.SetLength(0);

                    dest.WriteLine($"local mType = Game.createMonsterType(\"{monster.RegisteredName}\")");
                    dest.WriteLine("local monster = {}");
                    dest.WriteLine("");

                    dest.WriteLine($"monster.name = \"{monster.Name}\"");
                    dest.WriteLine($"monster.description = \"{monster.Description}\"");
                    dest.WriteLine($"monster.experience = {monster.Experience}");
                    dest.WriteLine("monster.outfit = {");
                    if (monster.ItemIdLookType != 0)
                    {
                        dest.WriteLine($"	lookTypeEx = {monster.ItemIdLookType}");
                    }
                    else
                    {
                        dest.WriteLine($"	lookType = {monster.OutfitIdLookType},");
                        dest.WriteLine($"	lookHead = {monster.LookTypeDetails.Head},");
                        dest.WriteLine($"	lookBody = {monster.LookTypeDetails.Body},");
                        dest.WriteLine($"	lookLegs = {monster.LookTypeDetails.Legs},");
                        dest.WriteLine($"	lookFeet = {monster.LookTypeDetails.Feet},");
                        dest.WriteLine($"	lookAddons = {monster.LookTypeDetails.Addons},");
                        dest.WriteLine($"	lookMount = {monster.LookTypeDetails.Mount}");
                    }
                    dest.WriteLine("}");
                    dest.WriteLine("");
                    dest.WriteLine($"monster.health = {monster.Health}");
                    dest.WriteLine($"monster.maxHealth = {monster.Health}");
                    dest.WriteLine($"monster.runHealth = {monster.RunOnHealth}");
                    dest.WriteLine($"monster.race = \"{monster.Race}\""); // TODO check if mapping is neeeded
                    dest.WriteLine($"monster.corpse = {monster.CorpseId}");
                    dest.WriteLine($"monster.speed = {monster.Speed}");
                    dest.WriteLine($"monster.summonCost = {monster.SummonCost}");
                    dest.WriteLine($"monster.maxSummons = {monster.MaxSummons}");
                    dest.WriteLine("");

                    dest.WriteLine("monster.changeTarget = {");
                    dest.WriteLine($"	interval = {monster.RetargetInterval},");
                    dest.WriteLine($"	chance = {monster.RetargetChance * 100:0}");
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    // Flags
                    dest.WriteLine("monster.flags = {");
                    dest.WriteLine($"	summonable = {(monster.SummonCost > 0).ToString().ToLower()},");
                    dest.WriteLine($"	attackable = {monster.Attackable.ToString().ToLower()},");
                    dest.WriteLine($"	hostile = {monster.Hostile.ToString().ToLower()},");
                    dest.WriteLine($"	convinceable = {(monster.ConvinceCost > 0).ToString().ToLower()},");
                    dest.WriteLine($"	pushable = {monster.Pushable.ToString().ToLower()},");
                    dest.WriteLine($"	boss = {monster.IsBoss.ToString().ToLower()},");
                    dest.WriteLine($"	illusionable = {monster.Illusionable.ToString().ToLower()},");
                    dest.WriteLine($"	canPushItems = {monster.PushItems.ToString().ToLower()},");
                    dest.WriteLine($"	canPushCreatures = {monster.PushCreatures.ToString().ToLower()},");
                    dest.WriteLine($"	staticAttackChance = {monster.StaticAttack},");
                    dest.WriteLine($"	targetDistance = {monster.TargetDistance},");
                    dest.WriteLine($"	healthHidden = {monster.HideHealth.ToString().ToLower()},");
                    dest.WriteLine($"	canWalkOnEnergy = {(!monster.AvoidEnergy).ToString().ToLower()},");
                    dest.WriteLine($"	canWalkOnFire = {(!monster.AvoidFire).ToString().ToLower()},");
                    dest.WriteLine($"	canWalkOnPoison = {(!monster.AvoidPoison).ToString().ToLower()}");
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    // Light
                    dest.WriteLine("monster.light = {");
                    dest.WriteLine($"	level = {monster.LightLevel},");
                    dest.WriteLine($"	color = {monster.LightColor}");
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    // Voices
                    dest.WriteLine("monster.voices = {");
                    dest.WriteLine("	interval = 5000,");
                    dest.WriteLine("	chance = 10,");
                    string voice;
                    for (int i = 0; i < monster.Voices.Count; i++)
                    {
                        bool yell = false;
                        if (monster.Voices[i].SoundLevel == SoundLevel.Yell)
                        {
                            yell = true;
                        }
                        voice = $"	{{text = \"{monster.Voices[i].Sound}\", yell = {yell.ToString().ToLower()}}},";
                        if (i == monster.Voices.Count - 1)
                        {
                            voice = voice.TrimEnd(',');
                        }
                        dest.WriteLine(voice);
                    }
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    dest.WriteLine("monster.immunities = {");
                    dest.WriteLine($"	{{type = \"paralyze\", condition = {monster.IgnoreParalyze.ToString().ToLower()}}},");
                    dest.WriteLine($"	{{type = \"outfit\", condition = {monster.IgnoreOutfit.ToString().ToLower()}}},");
                    dest.WriteLine($"	{{type = \"invisible\", condition = {monster.IgnoreInvisible.ToString().ToLower()}}},");
                    dest.WriteLine($"	{{type = \"bleed\", condition = {monster.IgnoreBleed.ToString().ToLower()}}}");
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    dest.WriteLine("monster.elements = {");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Physical]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.Physical)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Energy]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.Energy)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Earth]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.Earth)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Fire]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.Fire)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.LifeDrain]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.LifeDrain)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.ManaDrain]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.ManaDrain)}}},");
                    //dest.WriteLine($"	{{type = { CombatDamageNames[CombatDamage.Healing]}, percent = {GenericToTfsElemementPercent(monster.XXXX)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Drown]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.Drown)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Ice]}, percent = {GenericToTfsRevScriptSysElemementPercent(monster.Ice)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Holy]} , percent = {GenericToTfsRevScriptSysElemementPercent(monster.Holy)}}},");
                    dest.WriteLine($"	{{type = {CombatDamageNames[CombatDamage.Death]} , percent = {GenericToTfsRevScriptSysElemementPercent(monster.Death)}}}");
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    // Offensive abilities
                    if (monster.Attacks.Count > 0)
                    {
                        IList <string> attacks = new List <string>();
                        foreach (var spell in monster.Attacks)
                        {
                            if (spell.SpellCategory == SpellCategory.Offensive)
                            {
                                Spell s      = spell;
                                var   result = GenericToTfsRevScriptSysSpells(ref s);
                                if (result.Item1 != ConvertError.Success)
                                {
                                    if (code != ConvertError.Error)
                                    {
                                        code     = ConvertError.Warning;
                                        message += result.Item2;
                                    }
                                    continue;
                                }
                                attacks.Add(result.Item2);
                            }
                        }

                        dest.WriteLine("monster.attacks = {");
                        for (int i = 0; i < attacks.Count; i++)
                        {
                            if (i == attacks.Count - 1)
                            {
                                dest.WriteLine($"{attacks[i]}");
                            }
                            else
                            {
                                dest.WriteLine($"{attacks[i]},");
                            }
                        }
                        dest.WriteLine("}");
                        dest.WriteLine("");
                    }

                    // Defensive abilities
                    IList <string> defenses = new List <string>();
                    foreach (var spell in monster.Attacks)
                    {
                        if (spell.SpellCategory == SpellCategory.Defensive)
                        {
                            Spell s      = spell;
                            var   result = GenericToTfsRevScriptSysSpells(ref s);
                            if (result.Item1 != ConvertError.Success)
                            {
                                if (code != ConvertError.Error)
                                {
                                    code     = ConvertError.Warning;
                                    message += result.Item2;
                                }
                                continue;
                            }
                            defenses.Add(result.Item2);
                        }
                    }
                    dest.WriteLine("monster.defenses = {");
                    dest.WriteLine($"	defense = {monster.Shielding},");
                    if (defenses.Count > 0)
                    {
                        dest.WriteLine($"	armor = {monster.TotalArmor},");
                    }
                    else
                    {
                        dest.WriteLine($"	armor = {monster.TotalArmor}");
                    }

                    for (int i = 0; i < defenses.Count; i++)
                    {
                        if (i == defenses.Count - 1)
                        {
                            dest.WriteLine($"{defenses[i]}");
                        }
                        else
                        {
                            dest.WriteLine($"{defenses[i]},");
                        }
                    }
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    // Summons
                    if (monster.Summons.Count > 0)
                    {
                        dest.WriteLine("monster.summons = {");
                        string summon;
                        for (int i = 0; i < monster.Summons.Count; i++)
                        {
                            summon = $"	{{name = \"{monster.Summons[i].Name}\", chance = {monster.Summons[i].Chance * 100:0}, interval = {monster.Summons[i].Rate}";
                            if (monster.Summons[i].Max > 0)
                            {
                                summon += $", max = {monster.Summons[i].Max}";
                            }

                            if (monster.Summons[i].Force)
                            {
                                summon += $", force = {monster.Summons[i].Force.ToString().ToLower()}";
                            }
                            summon += "}";

                            if (i == monster.Summons.Count - 1)
                            {
                                summon = summon.TrimEnd(',');
                            }
                            else
                            {
                                summon += ",";
                            }
                            dest.WriteLine(summon);
                        }
                        dest.WriteLine("}");
                        dest.WriteLine("");
                    }

                    if (monster.Scripts.Count(s => s.Type != ScriptType.OnDeath) > 0)
                    {
                        code     = ConvertError.Warning;
                        message += "Unable to convert scripts.";
                    }
                    var writableEvents = monster.Scripts.Where(s => s.Type == ScriptType.OnDeath).ToList();
                    if (writableEvents.Count > 0)
                    {
                        dest.WriteLine("monster.events = {");
                        for (int i = 0; i < writableEvents.Count; i++)
                        {
                            if (i == writableEvents.Count - 1)
                            {
                                dest.WriteLine($"	\"{writableEvents[i].Name}\"");
                            }
                            else
                            {
                                dest.WriteLine($"	\"{writableEvents[i].Name}\",");
                            }
                        }
                        dest.WriteLine("}");
                        dest.WriteLine("");
                    }

                    // Loot
                    dest.WriteLine("monster.loot = {");
                    string loot;
                    for (int i = 0; i < monster.Items.Count; i++)
                    {
                        string item;
                        if (int.TryParse(monster.Items[i].Item, out int itemid))
                        {
                            item = itemid.ToString();
                        }
                        else
                        {
                            item = $"\"{monster.Items[i].Item}\"";
                        }

                        decimal chance = monster.Items[i].Chance * MAX_LOOTCHANCE;
                        loot = $"	{{id = {item}, chance = {chance:0}";

                        if (monster.Items[i].Count > 1)
                        {
                            loot += $", maxCount = {monster.Items[i].Count}";
                        }

                        if (monster.Items[i].SubType > 0)
                        {
                            loot += $", subType = {monster.Items[i].SubType}";
                        }

                        if (monster.Items[i].ActionId > 0)
                        {
                            loot += $", actionId = {monster.Items[i].ActionId}";
                        }

                        if (!string.IsNullOrWhiteSpace(monster.Items[i].Text))
                        {
                            loot += $", text = {monster.Items[i].Text}";
                        }

                        loot += "},";

                        if (i == monster.Items.Count - 1)
                        {
                            loot = loot.TrimEnd(',');
                        }
                        dest.WriteLine(loot);
                    }
                    dest.WriteLine("}");
                    dest.WriteLine("");

                    dest.WriteLine("mType:register(monster)");
                }

            return(new ConvertResult(fileName, code, message));
        }