便捷建造模組開發(fā)詳細過程
EasyBuildMod是一個便捷建造模組,它包含了三個物品:物塊放置助手可以快速將物塊或墻壁放置在一個矩形區(qū)域、物塊摧毀助手可以快速摧毀矩形區(qū)域內(nèi)的物塊或墻壁、物品拾取磁鐵則可用于快速拾取摧毀后掉落的物品。
制作這個模組主要是因為自己在游戲中想挖空或建造地形進行建造戰(zhàn)斗場地時,直接手動挖空或放置非常耗時,而自己嘗試過某些模組但都不太能滿足自己需要,比如Fargo的“城市克星”,摧毀范圍大但是墻壁無法破壞,還有“更好的體驗”模組,放置和摧毀物塊的效率并不算太高。暫時也沒找到其他模組(如果有歡迎提出)。所以就自己動手寫了一個。
2.模組物品制作
本模組包含三個物品,物品拾取磁鐵、物塊放置助手和物塊摧毀助手。定義了一個全局的EasyBuildModPlayer
類繼承自ModPlayer
,來控制使用某些物品或擁有某些效果時玩家的行為改變。
2.1物品拾取磁鐵
ItemGrabMagnet,該物品借鑒了懶人模組中的戰(zhàn)利品磁鐵和ItemMagnetPlus模組。希望達到的效果是使用后玩家擁有“物品拾取”的Buff,可以擴大拾取范圍,再次使用則可以關(guān)閉。
首先是ItemGrabMagnet的代碼。這部分的代碼比較簡單,就是在玩家使用物品時判斷是否已經(jīng)擁有Buff,如果沒有則添加Buff,如果有則移除Buff。
有幾個細節(jié)的地方:由于想要的是使用磁鐵后buff時間無限長,在Buff中設(shè)置剩余時間不可見,在給Buff時設(shè)置足夠長的時間即可。
還有一個要注意的地方就是CombatText.NewText
會默認對所有玩家觸發(fā),也就是玩家A在使用時,玩家B也能看到CombatText.NewText
的訊息,所以CombatText.NewText
的第一個參數(shù)不能用Main.LocalPlayer,否則其他人使用時也會顯示在自己這里。
? ?public class ItemGrabBuff : ModBuff
? ?{ ? ? ? ?public override void SetStaticDefaults()
? ? ? ?{
? ? ? ? ? ?Main.buffNoTimeDisplay[Type] = true;
? ? ? ? ? ?Main.debuff[Type] = false;
? ? ? ?} ? ? ? ?public override void Update(Player player, ref int buffIndex)
? ? ? ?{
? ? ? ? ? ?player.GetModPlayer<EasyBuildModPlayer>().ItemGrabBuff = true;
? ? ? ?}
? ?}
? ?public class ItemGrabMagnet : ModItem
? ?{ ? ? ? ?internal static string GetText(string str, params object[] args)
? ? ? ?{ ? ? ? ? ? ?return Language.GetTextValue($"Mods.EasyBuildMod.Content.Items.ItemGrabMagnet.{str}", args);
? ? ? ?} ? ? ? ?public override string Texture => "EasyBuildMod/Content/Items/ItemGrabMagnet"; ? ? ? ?public bool IsMagnetOn; ? ? ? ?public override void SetStaticDefaults()
? ? ? ?{
? ? ? ? ? ?CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1;
? ? ? ?} ? ? ? ?public override void SetDefaults()
? ? ? ?{
? ? ? ? ? ?Item.width = 30;
? ? ? ? ? ?Item.height = 30;
? ? ? ? ? ?Item.maxStack = 1;
? ? ? ? ? ?Item.value = Item.sellPrice(gold: 1);
? ? ? ? ? ?Item.rare = ItemRarityID.Blue;
? ? ? ? ? ?Item.useAnimation = 15;
? ? ? ? ? ?Item.useTime = 20;
? ? ? ? ? ?Item.useStyle = ItemUseStyleID.HoldUp;
? ? ? ? ? ?Item.consumable = false;
? ? ? ? ? ?IsMagnetOn = false;
? ? ? ?} ? ? ? ?public override void AddRecipes()
? ? ? ?{ ? ? ? ? ? ?// 20個鐵錠/鉛錠
? ? ? ? ? ?CreateRecipe()
? ? ? ? ? ? ? ?.AddRecipeGroup("IronBar", 20)
? ? ? ? ? ? ? ?.AddTile(TileID.Anvils)
? ? ? ? ? ? ? ?.Register();
? ? ? ?} ? ? ? ?public override bool? UseItem(Player player)
? ? ? ?{
? ? ? ? ? ?IsMagnetOn = !player.HasBuff(ModContent.BuffType<Buffs.ItemGrabBuff>()); ? ? ? ? ? ?if (IsMagnetOn)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?CombatText.NewText(player.Hitbox, Color.Green, GetText("OnTooltip"));
? ? ? ? ? ? ? ?player.AddBuff(ModContent.BuffType<Buffs.ItemGrabBuff>(), 2592000);
? ? ? ? ? ? ? ?SoundEngine.PlaySound(SoundID.MenuTick);
? ? ? ? ? ?} ? ? ? ? ? ?else
? ? ? ? ? ?{
? ? ? ? ? ? ? ?CombatText.NewText(player.Hitbox, Color.Red, GetText("OffTooltip"));
? ? ? ? ? ? ? ?player.ClearBuff(ModContent.BuffType<Buffs.ItemGrabBuff>());
? ? ? ? ? ? ? ?SoundEngine.PlaySound(SoundID.MenuClose);
? ? ? ? ? ?} ? ? ? ? ? ?return true;
? ? ? ?} ? ? ? ?public override void ModifyTooltips(List<TooltipLine> tooltips)
? ? ? ?{ ? ? ? ? ? ?string color = IsMagnetOn ? "00FF00" : "FF0000"; ? ? ? ? ? ?string tooltop = IsMagnetOn ? GetText("OnTooltip") : GetText("OffTooltip"); ? ? ? ? ? ?var line = new TooltipLine(Mod, GetText("StatusName"), $"[c/{color}:{tooltop}]");
? ? ? ? ? ?tooltips.Add(line);
? ? ? ?}
? ?}
然后是物品拾取范圍擴大的實現(xiàn)。新定義EasyBuildModGlobalItem
繼承自GlobalItem
,重寫其中的GrabRange方法。注意格子數(shù)與游戲?qū)嶋H距離的換算是乘除16。
? ?public class EasyBuildModGlobalItem : GlobalItem
? ?{ ? ? ? ?public override void GrabRange(Item item, Player player, ref int grabRange)
? ? ? ?{ ? ? ? ? ? ?if (player.GetModPlayer<EasyBuildModPlayer>().ItemGrabBuff)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?grabRange = ModContent.GetInstance<EasyBuildModConfig>().MagnetRange * 16;
? ? ? ? ? ?}
? ? ? ?}
? ?}
至此便基本實現(xiàn)了ItemGrabMagnet的功能。效果如下:


2.2物塊放置與摧毀助手基類
ItemPlaceHelper與ItemDestroyHelper二者都有共同的特點,一個是可以通過右鍵調(diào)出菜單進行選擇,一個是左鍵可以框選區(qū)域進行放置或破壞。自己最開始是先寫了ItemPlaceHelper,而后寫另一個的時候才意識到有大量重復的邏輯。為了避免過多重復代碼,這里就二者的共同特點提取出一個抽象基類。
這里分成了三部分,物品自身、菜單和區(qū)域選擇。
2.2.1Item實現(xiàn)
主要就是定義了物品的基本行為,如右鍵調(diào)出菜單,左鍵進行框選。調(diào)出菜單在重寫CanUseItem
中進行實現(xiàn),選擇區(qū)域則是在UseItem
,這樣處理更為方便。這種情況下,ItemPlaceHelper
與ItemDestroyHelper
只需重寫StartAction
方法即可。