Террария вики
Террария вики

TModLoader-Logo1
Всем привет, с вами Makkei, и я научу вас создавать моды для такой замечательной игры, как Террария!
[]

Рекомендую использовать Notepad++

  • Скелет мода
  • Первый предмет
  • Верстак
  • НПС
  • Кирка
  • Молот
  • Меч

1) Скелет мода.[]

Скелет мода, где и как его получить?[]

Чтобы любой мод работал, ему необходимы исполнительные файлы, чтобы получить их переходите по этой ссылке: javid.ddns.net/tModLoader/generator/ModSkeletonGenerator.html (Скопировать и вставить в адресную строку браузера). Эта ссылка на генератор, здесь вы указываете : 1) ID мода в системе БЕЗ ПРОБЕЛОВ , пример :

ExampleMod. 2) Отображаемое имя мода, пример: Example Mod. 3) Внимание! Первый предмет, без пробелов, это предмет с которого начинает загружаться мод, ЕГО НЕ УДАЛЯТЬ!!! , пример: ExampleItem. 4) Имя автора, ну тут как хотите!

Screenshot-1

Со скелетом пожалуй всё, нажимаете Generate Mod Skeleton, Profit! Ваш мод скачивается, позже вы кидаете его по пути : C:\Users\Ваш пользователь\Documents\My Games\Terraria\ModLoader\Mod Sources

Из архива кидаете туда файл, должно получиться так:

Bandicam 2016-09-20 16-13-49-730

В папке Документы\My Games\Terraria\ModLoader\Mod Sources и там в папке с вашим модом есть некое кол-во файлов, которые мы и будем разбирать, в папке Items лежат предметы мода, остальные файлы я создам позже, файл: Имя Мода:cs - файл конфигурации и регистрации вашего мода. А файл build.txt служит для указания видимого названия мода, его версии и автора.

Bandicam 2016-09-20 16-13-57-514

Внутри папки Items лежит ваш первый предмет: ExampleItem. Любой предмет требует 2 файла: 1)Файл кода предмета: пример: ExampleItem.cs 2)Файл-спрайт*, должен называться как и предмет. пример: ExampleItem.png

Bandicam 2016-09-20 16-14-06-450

* Спрайт здесь и далее означает рисунок или картинку.

Файлы настройки[]

Коротко о файлах настройки:

Главный файл: Имя мода.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)Есть нашальника или как сделать верстак.[]

Код[]

Bandicam 2016-09-20 18-16-37-982

Для начала, поговорим о том, что нам понадобится новая папка, Tiles, создаём ей в папке с нашим модом. После заходим в нее и там надо создать 2 файла: Спрайт и название вашего верстака, БЕЗ ПРОБЕЛОВ, с расширением файла-кода .сs Это размещаемый объект и его спрайт.

Bandicam 2016-09-20 18-20-55-227

Далее в папке Items создаём папку Placeable, в ней будут лежать размещаемые предметы в виде картинки в инвентаре, следовательно там также будет файл-код и спрайт.

Файл-код ПРЕДМЕТА, а не объекта 


Bandicam 2016-09-20 18-19-18-975
Bandicam 2016-09-20 18-21-00-232
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();           //Конец рецепта
    }
  }
}

Спрайт
ExampleWorkbench
[]

Теперь о объекте.[]

Объект это файл-код и спрайт, которые можно установить в мир. Они находятся в папке 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"));
    }
  }
}

                                                                                                                                                             Спрайт

ExampleWorkbench3

Учтите, что розовыми линиями обозначаются границы блока, они не видны!!! Это и есть Frame.

Вывод: Мы научились создавать верстак, и его тайл

4) NPC[]

   Файл кода.[]

С НПС будет чуть сложнее, поскольку требуется анимация но приступим!

Bandicam 2016-09-20 21-20-08-682

Для начала создаём в папке нашего мода новую папку: 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;
      }
    }
  }
}

                                                                                             И его спрайт:

PartyZombie


Как видно из картинки его анимация состоит из 3-х частей, и по поваду спавна строчка:                            return spawnInfo.spawnTileY < Main.rockLayer && !Main.dayTime ? 0.5f : 0f; означает что, его спавн выше каменного слоя и НЕ днём, с шансом 0.5 и бонусом 0

Прут_пачками!!!-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();                          //Конец рецепта
    }
  }
}

 Если хотите разобраться с редкостью то вот:

http://ru.terraria.wikia.com/wiki/%D0%A0%D0%B5%D0%B4%D0%BA%D0%BE%D1%81%D1%82%D1%8C

Эфекты к оружию будут позже!!!

Спрайт[]

Glim
[]

Дополнение 1."Библиотеки"[]

В модлоадере есть куча разных библиотек. Наиболее полный список здесь:

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;

Дополнение 2."Свойства предметов"[]

item.name (Отображаемое имя)
item.height (Высота)
item.width (Ширина)
item.damage (Урон)
item.melee (Ближний)
item.noMelee (Не ближний)
item.ranged (Стрелковый)
item.consumable (Расходуемый)
item.noUseGraphic (Использует графику)
item.useAnimation (Анимация)
item.useStyle (Стиль)
item.useTime (Скорость использования)
item.knockBack (Отбрасывание)
item.useSound (Звук использования)
item.autoReuse (Авто использование)
item.shoot (Стреляет?)
item.rare (Редкость)
item.shootSpeed (Скорость использования)
item.mana (Потребление маны за использование)
item.magic (Магический)
item.toolTip (Описание)
item.toolTip2 (Описание 2)
item.useAmmo (Какие патроны использует)
item.value (Цена в медных монетах)
item.crit (Шанс крита)
item.accessory (Аксесуар?)
item.lifeRegen (Реген ХП в секунду)