泰拉瑞亚模组学习笔记-#1

声明:本笔记为朋友写时装总结的一些经验。

重要提示:
在阅读本篇文章之前你应该优先掌握裙子博客的前置教程:

传送门:裙中世界

TML源码阅读技巧教程源视频(来自裙子的哔哩哔哩):

视频高清传送门:TML源码阅读技巧教程源视频

以下是笔记区域


No.1——委托说明:

因为朋友本身想制作一个时装Mod,但是自己并没有看懂时装代码。因此委托我进行该任务……

No.2——任务分析:

在早期,我尝试直接套用原版的护甲素材标准来套。
但是,经过实验证明,此方法并不适用于该时装。
因为该时装并没有参照护甲素材的标准。
而是摩蝎座尾巴的标准,因此,我需要调整代码。

No.3——问题解决:

经过一段时间的分析和探索以及大台风的指点,我找到了解决的方案。
即在ModPlayer里面进行校正。使用的重写函数为“FrameEffects”

class FixedLeg : ModPlayer 

        {
            public override void PostUpdate()
            {

                {
                    //检查12或者2的插槽栏是否为DragonLeg物品,如果是,则进行角度重新校正(注:12是时装栏的腿饰部分,2是装备栏的护腿部分)
                    if (Player.armor[Player.extraAccessorySlots=12].type == ModContent.ItemType<DragonLeg>()||Player.armor[Player.extraAccessorySlots = 2].type == ModContent.ItemType<DragonLeg>())
                    {
                        //调用LegPosition 使用玩家的位置与-6f进行套用
                        Player.legPosition = new Vector2(-6f * Player.direction, 0f);
                    } else {
                        //如果条件无法满足,则恢复默认腿位置
                        Player.legPosition = new Vector2(0f, 0f);
                    }
                }

            }
        }

No.4——移动粒子效果(锦上添花)

粒子效果我最开始写的时候以为只有一行代码,因此中间吃了很多弯路。
但通过阅读源代码后,我清楚了移动粒子效果的特点。 只需要将源代码的移植过来并import即可实现。

需要的引导:
using Terraria.GameContent.Drawing;

/*火焰特效*/
public bool DragonLeg_Effect(int X, int Y)
{
    //绘制在底部
    Tile tile = Main.tile[X, Y + 1];
    if (!(tile != null && tile.LiquidType <= 0 && WorldGen.SolidTileAllowBottomSlope(X, Y + 1)))
    return false;

    //粒子特效渲染 以及粒子类型
    ParticleOrchestrator.RequestParticleSpawn(clientOnly: true, ParticleOrchestraType.FlameWaders, new ParticleOrchestraSettings
    {
    PositionInWorld = new Vector2(X * 16 + 8, Y * 16 + 16)
    //位置绘制
    });
    return true;
}

//引用它则应该进行逻辑判定,1和2是恶魔之心一个判断,因为恶魔之心会扩展一个槽位
```cs
public override void FrameEffects()
{
    if (Player.armor[Player.extraAccessorySlots = 1].type == ModContent.ItemType<DragonLeg>() || Player.armor[Player.extraAccessorySlots = 2].type == ModContent.ItemType<DragonLeg>())
    {
    Player.DoBootsEffect(DragonLeg_Effect);
    }

    if (Player.armor[Player.extraAccessorySlots = 1].type == ModContent.ItemType<EgFoxLegs>() || Player.armor[Player.extraAccessorySlots = 2].type == ModContent.ItemType<EgFoxLegs>())
    {
    Player.DoBootsEffect(EgLeg_Effect);
    }
}

No.5——动态图像物品的实现方案

ExampleMod实际有这个方法的实列,但是我这里单独提出是为了保证大家能尽快的了解。 方法其实很简单,在物品的SetStaticDefaults重写函数添加

public override void SetStaticDefaults() {
    DisplayName.SetDefault("xxx");
    Tooltip.SetDefault("xxxxxxx")

    //定义一个动画 4帧 每秒持续5刻(1/12)
    Main.RegisterItemAnimation(Item.type, neDrawAnimationVertical(10, 4));
}

然后贴图的话使用与源代码的多帧竖图那样,比如肉后的灵魂,当然,EXMOD也有该说明。

No.6——制作一个虚假的宝藏袋

什么是虚假的宝藏袋,就是说,它拥有宝藏袋的一些特性。但其实却不是真正的宝藏袋,而且右键开启它也不会获得开发者时装。这是朋友委托这样做的,所以我也单独提出来。

1.方案确定

明确一点,宝藏袋右键可以打开东西。但是我们这里的虚假的宝藏袋。我们希望打开的东西完全固定,并且没有开发者时装(类似于宝匣),并且我们还要让标题颜色是彩色渲染,并且有类似于宝藏袋的特效。

2.代码实现

    public override void SetDefaults() {
        Item.rare = ItemRarityID.Expert;
        Item.expert = true;
        //专家稀有品质以及专家类型物品
        //彩色文本渲染并且为专家物品
    }

    //PostUpdate 和 PreDrawInWorld为宝藏袋的特效
    public override void PostUpdate() {
            Lighting.AddLight(Item.Center, Color.Orange.ToVector3() * 0.4f);

            if (Item.timeSinceItemSpawned % 12 == 0) {
                Vector2 center = Item.Center + new Vector2(0f, Item.height * -0.1f);
                Vector2 direction = Main.rand.NextVector2CircularEdge(Item.width * 0.6f, Item.height * 0.6f);
                float distance = 0.3f + Main.rand.NextFloat() * 0.5f;
                Vector2 velocity = new Vector2(0f, -Main.rand.NextFloat() * 0.3f - 1.5f);
                Dust dust = Dust.NewDustPerfect(center + direction * distance, DustID.SilverFlame, velocity);
                dust.scale = 0.5f;
                dust.fadeIn = 1.1f;
                dust.noGravity = true;
                dust.noLight = true;
                dust.alpha = 0;
            }
        }

        public override bool PreDrawInWorld(SpriteBatch spriteBatch, Color lightColor, Color alphaColor, ref float rotation, ref float scale, int whoAmI) {
            Texture2D texture = TextureAssets.Item[Item.type].Value;

            Rectangle frame;

            if (Main.itemAnimations[Item.type] != null) {
                frame = Main.itemAnimations[Item.type].GetFrame(texture, Main.itemFrameCounter[whoAmI]);
            }
            else {
                frame = texture.Frame();
            }

            Vector2 frameOrigin = frame.Size() / 2f;
            Vector2 offset = new Vector2(Item.width / 2 - frameOrigin.X, Item.height - frame.Height);
            Vector2 drawPos = Item.position - Main.screenPosition + frameOrigin + offset;

            float time = Main.GlobalTimeWrappedHourly;
            float timer = Item.timeSinceItemSpawned / 240f + time * 0.04f;

            time %= 4f;
            time /= 2f;

            if (time >= 1f) {
                time = 2f - time;
            }

            time = time * 0.5f + 0.5f;

            for (float i = 0f; i < 1f; i += 0.25f) {
                float radians = (i + timer) * MathHelper.TwoPi;

                spriteBatch.Draw(texture, drawPos + new Vector2(0f, 8f).RotatedBy(radians) * time, frame, new Color(255, 165, 0, 50), rotation, frameOrigin, scale, SpriteEffects.None, 0);
            }

            for (float i = 0f; i < 1f; i += 0.34f) {
                float radians = (i + timer) * MathHelper.TwoPi;

                spriteBatch.Draw(texture, drawPos + new Vector2(0f, 4f).RotatedBy(radians) * time, frame, new Color(205, 115, 0, 77), rotation, frameOrigin, scale, SpriteEffects.None, 0);
            }

            return true;
        }


    //定义右键可以工作
    public override bool CanRightClick()
    {
        return true;
    }
    //玩家点击右键会发生什么事情?
    public override void RightClick(Player player)
    {
        var entitySource = player.GetSource_OpenItem(Type);
        /*
        立刻给予玩家指定物品,这里是使用的MOD物品
        原版物品获取:
        # 生命水晶的给予,9代表获取数量
        player.QuickSpawnItem(entitySource, ItemID.LifeCrystal,9);
        # 同理 Mod物品则在后面加数量即可批量获取
        player.QuickSpawnItem(entitySource, ModContentItemType<DragonEar>(),5);
        # 获取5个MOD物品
        */
        player.QuickSpawnItem(entitySource, ModContentItemType<DragonArmor>());
        player.QuickSpawnItem(entitySource, ModContentItemType<DragonEar>());
        player.QuickSpawnItem(entitySource, ModContentItemType<EgDragonFront>());
        player.QuickSpawnItem(entitySource, ModContentItemType<DragonLeg>());
        player.QuickSpawnItem(entitySource, ModContentItemType<EgDragonNeck>());
    }
`

本文总结:

本篇记载关于制作时装MOD的心得体会,在此特别感谢大台风的帮助。 文章可能会有一些小问题,若有请发送评论对我批评指正。
希望这篇文章能帮助到需要帮助的人,感谢你的阅读。
下一期见。

By JDSA Ling-Ling Book Blog

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注