Всем привет, с вами Makkei, и я научу вас создавать моды для такой замечательной игры, как Террария![]
Рекомендую использовать Notepad++
Скелет мода
Первый предмет
Верстак
НПС
Кирка
Молот
Меч
1) Скелет мода.[]
Скелет мода, где и как его получить?[]
Чтобы любой мод работал, ему необходимы исполнительные файлы, чтобы получить их переходите по этой ссылке: javid.ddns.net/tModLoader/generator/ModSkeletonGenerator.html (Скопировать и вставить в адресную строку браузера).
Эта ссылка на генератор, здесь вы указываете : 1) ID мода в системе БЕЗ ПРОБЕЛОВ , пример :
ExampleMod. 2) Отображаемое имя мода, пример: Example Mod. 3) Внимание! Первый предмет, без пробелов, это предмет с которого начинает загружаться мод, ЕГО НЕ УДАЛЯТЬ!!! , пример: ExampleItem. 4) Имя автора, ну тут как хотите!
Со скелетом пожалуй всё, нажимаете Generate Mod Skeleton, Profit! Ваш мод скачивается, позже вы кидаете его по пути : C:\Users\Ваш пользователь\Documents\My Games\Terraria\ModLoader\Mod Sources
Из архива кидаете туда файл, должно получиться так:
В папке Документы\My Games\Terraria\ModLoader\Mod Sources и там в папке с вашим модом есть некое кол-во файлов, которые мы и будем разбирать, в папке Items лежат предметы мода, остальные файлы я создам позже, файл: Имя Мода:cs - файл конфигурации и регистрации вашего мода. А файл build.txt служит для указания видимого названия мода, его версии и автора.
Внутри папки Items лежит ваш первый предмет: ExampleItem. Любой предмет требует 2 файла: 1)Файл кода предмета: пример: ExampleItem.cs 2)Файл-спрайт*, должен называться как и предмет. пример: ExampleItem.png
* Спрайт здесь и далее означает рисунок или картинку.
Файлы настройки[]
Коротко о файлах настройки:
Главный файл: Имя мода.cs
using Terraria.ModLoader; //То, что мы используем (Библиотеки)
namespace ModA
{
class ModA : Mod //Создание класса мода
{
public ModA()
{
Properties = new ModProperties()
{
Autoload = true, //Автозагрузка мода, True - Да
AutoloadGores = true, //Автозагрузка Эфектов, True - Да
AutoloadSounds = true //Автозагрузка Звуков, True - Да
};
}
}
}
На этом с файлами и скелетом всё! Приступаем к созданию вещи!
2)Ваш первый предмет.[]
Рассмотрим код вашего начального предмета:[]
using Terraria.ID; //То, что мы используем
using Terraria.ModLoader; //То, что мы используем
namespace ModA.Items //Какому моду принадлежит предмет
{
public class ExampleItem : ModItem //"Класс" предмета и название файла-кода
{
public override void SetDefaults() //Обычные данные
{
item.name = "ExampleItem"; //имя предмета в инвентаре
item.damage = 50; //Урон
item.melee = true; //Ближнее? true-Да
item.width = 40; //Размер спрайта:Длинна
item.height = 40; //Размер спрайта:Ширина
item.toolTip = "This is a modded sword."; //Описание предмета
item.useTime = 20; //Время использования
item.useAnimation = 20; //Время использования анимации
item.useStyle = 1; //Стиль
item.knockBack = 6; //Отбрасывание
item.value = 10000; //Стоимость "В медных монетах"
item.rare = 2; //редкость
item.useSound = 1; //Звук при использовании
item.autoReuse = true; //Авто-атака? true-да
}
public override void AddRecipes() //рецепт предмета
{
ModRecipe recipe = new ModRecipe(mod); //Создаём новый рецепт
recipe.AddIngredient(ItemID.DirtBlock, 10); //Добавляем ингредиенты
recipe.AddTile(TileID.WorkBenches); // На чём предмет крафтится
recipe.SetResult(this, 1); //результат крафта
recipe.AddRecipe(); //Заканчиваем рецепт
}
}
}
Вот мы и рассмотрели ваш первый предмет в папке Items , помните: 1)Предмет и Спрайт должны называться одинаково!!! 2) В коде предмета есть строчка: public class ExampleItem : ModItem , так вот, в этой строчке слово ExampleItem является ссылкой на файл и спрайт!
Подведём итог: у вас есть файл который называется ExampleItem, в котором в строчке public class ExampleItem : ModItem слово ExampleItem указывает на файл, в которой эта строчка находится, и слово в строчке и имя спрайта и имя файла-кода должно быть одинаковым!!!
3)Есть нашальника или как сделать верстак.[]
Код[]
Для начала, поговорим о том, что нам понадобится новая папка, Tiles,создаём ей в папке с нашим модом. После заходим в нее и там надо создать 2 файла: Спрайт и название вашего верстака, БЕЗ ПРОБЕЛОВ, с расширением файла-кода .сs Это размещаемый объект и его спрайт.
Далее в папке Items создаём папку Placeable, в ней будут лежать размещаемые предметы в виде картинки в инвентаре, следовательно там также будет файл-код и спрайт.
Файл-код ПРЕДМЕТА, а не объекта
using Terraria.ID; //что мы используем
using Terraria.ModLoader; // что мы используем
namespace ModA.Items.Placeable //Какому моду принадлежит предмет и его путь
{
public class ExampleWorkbench : ModItem //Вид предмета
{
public override void SetDefaults()
{
item.name = "Example Workbench"; //Название
item.width = 28; //Размеры
item.height = 14; //Размеры
item.maxStack = 99; // Макс в Стаке
AddTooltip("This is a modded workbench.");
item.useTurn = true;
item.autoReuse = true; //авто-использование
item.useAnimation = 15; //время использования анимации
item.useTime = 10; //время использования предмета
item.useStyle = 1; //стиль
item.consumable = true; //Можно потратить? true-да
item.value = 150; //Стоимость в медных монетах
item.createTile = mod.TileType("ExampleWorkbench"); //Типо ссылка на предмет в папке Tiles
}
public override void AddRecipes() //рецепт
{
ModRecipe recipe = new ModRecipe(mod); //создаём рецепт
recipe.AddIngredient(ItemID.WorkBench); //из чего?
recipe.AddIngredient(null, "ExampleItem", 2); //из чего, ВНИМАНИЕ, если стоит (null, "Имя предмета", кол-во) то это предмет из нашего мода
recipe.AddTile(TileID.WorkBenches); //На чём крафтится
recipe.SetResult(this, 1); //что получим при крафте
recipe.AddRecipe(); //Конец рецепта
}
}
}
Спрайт[]
Теперь о объекте.[]
Объект это файл-код и спрайт, которые можно установить в мир. Они находятся в папке Placeble
Вот код ОБЪЕКТА:
using Microsoft.Xna.Framework; //Что мы используем
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Terraria.ObjectData;
namespace ModA.Tiles //Какому моду принадлежит и где находится
{
public class ExampleWorkbench : ModTile //Класс предмети и ссылка на код-файл
{
public override void SetDefaults() //свойства
{
Main.tileSolidTop[Type] = true; //Твёрдый блок?
Main.tileFrameImportant[Type] = true; //Ипморт рамки
Main.tileNoAttach[Type] = true; //Можно ставить на него объекты
Main.tileTable[Type] = true; //Стол?
Main.tileLavaDeath[Type] = true; //Сгорает в лаве?
TileObjectData.newTile.CopyFrom(TileObjectData.Style2x1); //Синтез тайла
TileObjectData.newTile.CoordinateHeights = new int[]{ 18 }; //Синтез тайла
TileObjectData.addTile(Type); //Синтез тайла
AddToArray(ref TileID.Sets.RoomNeeds.CountsAsTable);
AddMapEntry(new Color(200, 200, 200), "Example Workbench"); //Место на карте
//dustType = mod.DustType("Sparkle"); пыль не используется
disableSmartCursor = true; //Отключает смарт-курсор?
adjTiles = new int[]{ TileID.WorkBenches }; //Функция стола
}
public override void NumDust(int i, int j, bool fail, ref int num)
{
num = fail ? 1 : 3;
}
public override void KillMultiTile(int i, int j, int frameX, int frameY)
{
Item.NewItem(i * 16, j * 16, 32, 16, mod.ItemType("ExampleWorkbench"));
}
}
}
Спрайт
Учтите, что розовыми линиями обозначаются границы блока, они не видны!!! Это и есть Frame.
Вывод: Мы научились создавать верстак, и его тайл
4) NPC[]
Файл кода.[]
С НПС будет чуть сложнее, поскольку требуется анимация но приступим!
Для начала создаём в папке нашего мода новую папку: NPCs . В ней будут все нипы и жители. Там два файла: 1)Спрайт с анимацией, ExampleNPC.png 2)Файл-код ExampleNPC.cs
A теперь, КОД, этот НИП будет в виде зомби:
using Terraria;
using Terraria.ID; //что используем
using Terraria.ModLoader;
namespace ModA.NPCs //кому и где принадлежит
{
public class ExampleNPC : ModNPC //Что это
{
public override void SetDefaults() //Параметры
{
npc.name = "Party Zombie"; //Ник монстра
npc.displayName = "Zombie"; //как отображается на карте
npc.width = 18; //размер
npc.height = 40; //размер
npc.damage = 14; //урон
npc.defense = 6; //Защита
npc.lifeMax = 200; //HP
npc.soundHit = 1; //Звук при получени урона
npc.soundKilled = 2; //Звук при смерти
npc.value = 60f; //дроп денег при смерти
npc.knockBackResist = 0.5f; //Защита к отбрасыванию
npc.aiStyle = 3; // Его ИИ
Main.npcFrameCount[npc.type] = Main.npcFrameCount[NPCID.Zombie]; //Фрейм
aiType = NPCID.Zombie; //тип ИИ
animationType = NPCID.Zombie; //тип анимации
}
public override float CanSpawn(NPCSpawnInfo spawnInfo) // параметры спавна
{
return spawnInfo.spawnTileY < Main.rockLayer && !Main.dayTime ? 0.5f : 0f; //Его спавн(выше каменного слоя, НЕ днём)
}
public override void HitEffect(int hitDirection, double damage) //Оставляет пыль при смерти
{
for (int i = 0; i < 10; i++)
{
int dustType = Main.rand.Next(139, 143);
int dustIndex = Dust.NewDust(npc.position, npc.width, npc.height, dustType);
Dust dust = Main.dust[dustIndex];
dust.velocity.X = dust.velocity.X + Main.rand.Next(-50, 51) * 0.01f;
dust.velocity.Y = dust.velocity.Y + Main.rand.Next(-50, 51) * 0.01f;
dust.scale *= 1f + Main.rand.Next(-30, 31) * 0.01f;
}
}
}
}
И его спрайт:
Как видно из картинки его анимация состоит из 3-х частей, и по поваду спавна строчка: return spawnInfo.spawnTileY < Main.rockLayer && !Main.dayTime ? 0.5f : 0f; означает что, его спавн выше каменного слоя и НЕ днём, с шансом 0.5 и бонусом 0
Прут пачками!!!-0
Торговец.[]
А теперь речь зайдёт о торговцах. Они приходят при достижение определённых условий.
using System.Linq;
using Terraria; //Что используем
using Terraria.ID;
using Terraria.ModLoader;
namespace ModA.NPCs //Что за мод и где НИП
{
public class ExamplePerson : ModNPC //Класс нипа
{
public override bool Autoload(ref string name, ref string texture, ref string[] altTextures)
{
name = "Example Person"; //Имя в системе
altTextures = new string[] { "ModA/NPCs/ExamplePerson_Alt_1" }; //Текстуры
return mod.Properties.Autoload;
}
public override void SetDefaults()
{
npc.name = "Example Person"; //Типа чем он занимается. его класс
npc.townNPC = true; //Может заселяться? true-да
npc.friendly = true; //Дружелюбный? true-да
npc.width = 18; //Размер
npc.height = 40; //Размер
npc.aiStyle = 7; //ИИ
npc.damage = 10; //Дамаг
npc.defense = 15; //Дефенс(Защита)
npc.lifeMax = 250; //HP
npc.soundHit = 1; //Звук при ударе
npc.soundKilled = 1; //звук смерти
npc.knockBackResist = 0.5f; //Устойчивость к отбрасыванию
Main.npcFrameCount[npc.type] = 25;
NPCID.Sets.ExtraFramesCount[npc.type] = 9;
NPCID.Sets.AttackFrameCount[npc.type] = 4;
NPCID.Sets.DangerDetectRange[npc.type] = 700;
NPCID.Sets.AttackType[npc.type] = 0;
NPCID.Sets.AttackTime[npc.type] = 90;
NPCID.Sets.AttackAverageChance[npc.type] = 30;
NPCID.Sets.HatOffsetY[npc.type] = 4; //Положение головы
NPCID.Sets.ExtraTextureCount[npc.type] = 1; //Екстра текстуринг
animationType = NPCID.Guide; //Анимация
}
public override bool CanTownNPCSpawn(int numTownNPCs, int money) //Условия ризыва НИПА
{
for (int k = 0; k < 255; k++)
{
Player player = Main.player[k];
if (player.active)
{
for (int j = 0; j < player.inventory.Length; j++)
{
if (player.inventory[j].type == mod.ItemType("ExampleItem")); //При каких условия он приходит
{
return true;
}
}
}
}
return false;
}
public override string TownNPCName()
{
switch (WorldGen.genRand.Next(4))
{
case 0:
return "Someone"; //Как он может называться
case 1:
return "Somebody";
case 2:
return "Blocky";
default:
return "Colorless";
}
}
public override void FindFrame(int frameHeight) //Фреймы
{
/*npc.frame.Width = 40;
if (((int)Main.time / 10) % 2 == 0)
{
npc.frame.X = 40;
}
else
{
npc.frame.X = 0;
}*/
}
public override string GetChat() //Общение с ним, его ответы
{
int partyGirl = NPC.FindFirstNPC(NPCID.PartyGirl);
if (partyGirl >= 0 && Main.rand.Next(4) == 0)
{
return "Can you please tell " + Main.npc[partyGirl].displayName + " to stop decorating my house with colors?";
}
switch (Main.rand.Next(3))
{
case 0:
return "Sometimes I feel like I'm different from everyone else here.";
case 1:
return "What's your favorite color? My favorite colors are white and black.";
default:
return "What? I don't have any arms or legs? Oh, don't be ridiculous!";
}
}
public override void SetChatButtons(ref string button, ref string button2)
{
button = Lang.inter[28]; //Кнопки ответа
}
public override void OnChatButtonClicked(bool firstButton, ref bool shop)
{
if (firstButton)
{
shop = true; //Торговец? True-да
}
}
public override void SetupShop(Chest shop, ref int nextSlot)
{
shop.item[nextSlot].SetDefaults(mod.ItemType("ExampleItem")); //Что продаёт
nextSlot++;
//shop.item[nextSlot].SetDefaults(mod.ItemType("EquipMaterial"));
//nextSlot++;
//shop.item[nextSlot].SetDefaults(mod.ItemType("BossItem"));
//nextSlot++;
//if (Main.player[Main.myPlayer].GetModPlayer<ExamplePlayer>(mod).ZoneExample)
//{
// shop.item[nextSlot].SetDefaults(mod.ItemType("ExampleWings"));
// nextSlot++;
//}
//if (Main.moonPhase < 2)
//{
// shop.item[nextSlot].SetDefaults(mod.ItemType("ExampleSword"));
// nextSlot++;
//}
//else if (Main.moonPhase < 4)
//{
// shop.item[nextSlot].SetDefaults(mod.ItemType("ExampleGun"));
// nextSlot++;
// shop.item[nextSlot].SetDefaults(mod.ItemType("ExampleBullet"));
// nextSlot++;
//}
//else if (Main.moonPhase < 6)
//{
// shop.item[nextSlot].SetDefaults(mod.ItemType("ExampleStaff"));
// nextSlot++;
//}
//else
//{
//}
// Here is an example of how your npc can sell items from other mods.
//if (ModLoader.GetLoadedMods().Contains("SummonersAssociation"))
//{
// shop.item[nextSlot].SetDefaults(ModLoader.GetMod("SummonersAssociation").ItemType("BloodTalisman"));
// nextSlot++;
//}
}
public override void TownNPCAttackStrength(ref int damage, ref float knockback)
{
damage = 20; //Урон
knockback = 4f; //Отбрасывание
}
public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
{
cooldown = 30; //Перезарядка
randExtraCooldown = 30; //Перезарядка крита
}
//public override void TownNPCAttackProj(ref int projType, ref int attackDelay)
// {
// projType = mod.ProjectileType("SparklingBall"); //Чем атакует
// attackDelay = 1; //Частота атак
// }
public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
{
multiplier = 12f; //Мултиплексор
randomOffset = 2f; //Крит при атаке
}
}
}
5)Майне катанен махайте или делаем меч.[]
Код.[]
Меч будет строиться так-же как и простая вещь!
using Terraria.ID;
using Terraria.ModLoader; //что используем
using Microsoft.Xna.Framework;
using Terraria;
namespace ModA.Items //Имя мода и путь предмета
{
public class Sword : ModItem //Что это за предмет
{
public override void SetDefaults() //Свойства предмета
{
item.name = "Example Sword"; //Имя предмета
item.damage = 50; //Урон
item.melee = true; //Ближний? true-да
item.width = 40; //размер
item.height = 40; //размер
item.toolTip = "This is a sword!!!"; //Описание предмета
item.useTime = 20; //время использования
item.useAnimation = 20; //Время использования анимации
item.useStyle = 1; //Стиль
item.knockBack = 6; //Отбрасывание
item.value = 10000; //Цена продажи в медных монетах
item.rare = -12; //Редкость
item.useSound = 1; //Звук использования
item.autoReuse = true; //авто использование? true-да
}
public override void AddRecipes() //Рецепт
{
ModRecipe recipe = new ModRecipe(mod); //Добавлени нового рецепта
recipe.AddIngredient(ItemID.DirtBlock); //Добавляем в крафт блок земли
recipe.AddIngredient(ItemID.WoodenSword); //Добавляем в крафт деревянный меч
recipe.AddTile(TileID.WorkBenches); //На чём крафтится?
recipe.SetResult(this,1); //Что получим в итоге
recipe.AddRecipe(); //Конец рецепта
}
}
}
В модлоадере есть куча разных библиотек. Наиболее полный список здесь:
using Microsoft.Win32;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using Terraria.Achievements;
using Terraria.DataStructures;
using Terraria.GameContent;
using Terraria.GameContent.Achievements;
using Terraria.GameContent.Events;
using Terraria.GameContent.Liquid;
using Terraria.GameContent.Skies;
using Terraria.GameContent.Tile_Entities;
using Terraria.GameContent.UI;
using Terraria.GameContent.UI.Chat;
using Terraria.GameContent.UI.States;
using Terraria.GameInput;
using Terraria.Graphics;
using Terraria.Graphics.Capture;
using Terraria.Graphics.Effects;
using Terraria.Graphics.Shaders;
using Terraria.ID;
using Terraria.Initializers;
using Terraria.IO;
using Terraria.Map;
using Terraria.Net;
using Terraria.ObjectData;
using Terraria.Social;
using Terraria.UI;
using Terraria.UI.Chat;
using Terraria.UI.Gamepad;
using Terraria.Utilities;
using Terraria.World.Generation;