https://ru.stardewvalleywiki.com/mediawiki/api.php?action=feedcontributions&user=GIDMYRT&feedformat=atomStardew Valley Wiki - Вклад участника [ru]2024-03-29T13:07:16ZВклад участникаMediaWiki 1.35.1https://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5862Модификации:Основные возможности2018-08-14T10:07:05Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для параметра в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле], и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Предметами являются инструменты, семена, урожай и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на клетке===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Локации==<br />
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)<br />
<br />
''Game1.currentLocation'' является ссылкой на текущую локацию в которой находится игрок.<br />
<br />
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.<br />
<br />
===Свойства карты===<br />
Многие свойства карты, а также клеток на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]<br />
<br />
===Обработка клетки===<br />
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора клеток (земля, трава, грядка). <br />
<br />
Ниже приведен фрагмент для обработки клетки с [[Культуры|культурой]]:<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!<br />
<br />
===Обработка объектов на клетке===<br />
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах (семена, камень, древесина).<br />
<br />
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.<br />
<br />
==Игрок==<br />
<br />
===Местоположение===<br />
Позиция персонажа указывает координаты персонажа в текущей локации.<br />
<br />
====Позиция игрока в локации====<br />
Каждая локация представлена ''xTile'' картой, где левый верхний угол имеет координаты ''(0, 0)'', а правый нижний - ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' пикселей. <br />
<br />
Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам клетки.<br />
<br />
<code>Position.X</code> и <code>Position.Y</code> вернут координаты XY в пикселях.<br />
<br />
<code>getTileX()</code> и <code>getTileY()</code> вернут координаты XY клетки в сетке тайл-листа.<br />
<br />
Согласно <code>Game1.tileSize</code> клетка имеет размер 64x64 пикселей, что дает возможность конвертировать абсолютную и относительную позиции:<br />
<br />
<source lang='c#'><br />
// Абсолютная позиция => Позиция клетки<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Позиция клетки => Абсолютная позиция<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Размеры клетки<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Позиция игрока в видимой области====<br />
Размеры видимой области экрана можно узнать используя <code>Game1.viewport.Width</code> и <code>Game1.viewport.Height</code>. Размеры указаны в пикселях и соответствуют разрешению экрана игры.<br />
<br />
Также видимая область имеет абсолютную позицию относительно карты, где левый верхний угол находится в ''(Game1.viewport.X, Game1.viewport.Y)''.<br />
<br />
Позиция игрока относительно видимой области вычисляется следующим образом:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==Неигровые персонажи==<br />
===Создание пользовательского НИПа===<br />
Добавление нового НИПа включает в себя редактирование нескольких файлов:<br />
<br />
* Создание файла: Characters\Dialogue\<имя><br />
* Создание файла: Characters\schedules\<имя><br />
* Создание файла: Portraits\<имя><br />
* Создание файла: Characters\<имя><br />
* Добавление записей Data\EngagementDialogue для НИПов, с которыми можно заключить брак<br />
* Добавление записи в Data\NPCDispositions<br />
* Добавление записи в Data\NPCGiftTastes<br />
* Добавление записей в Characters\Dialogue\rainy<br />
* Добавление записей в Data\animationDescriptions (если нужны пользовательские анимации в расписании)<br />
<br />
Все это можно сделать с помощью IAssetLoaders/IAssetEditors или Content Patcher. В завершении, создается НИП, используя конструкторы SMAPI:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
Для спавна:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==Пользовательский интерфейс==<br />
<br />
Пользовательский интерфейс представляет собой набор отдельных элементов, которые составляют [https://ru.wikipedia.org/wiki/Head-Up_Display_(игры) HUD] и всплывающие окна.<br />
<br />
//необходимо дополнить раздел.<br />
<br />
<br />
===Всплывающие сообщения===<br />
HUDMessage - это всплывающие сообщения в нижнем левом углу экрана. У них есть несколько конструкторов, которые указаны ниже (несколько не релевантных были пропущены):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
Ниже даны описания основных аргументов, которые требуются для создания сообщения. (Для полного описания рекомендуется читать информацию о классе, но в большинстве ситуации информации ниже достаточно)<br />
<br />
WhatType:<br />
*1 - Достижение<br />
*2 - Новый квест<br />
*3 - Ошибка<br />
*4 - Выносливость<br />
*5 - Здоровье<br />
<br />
<br />
Color: Цвет. В первых двух конструкторах используется цвет по умолчанию (''Color:OrangeRed''), а в четвертом - параметр 'leaveMeNull' отображается тем же цветом, что и текст игры.<br />
<br />
<br />
Для примера:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - Подходит для кастомизации сообщения. Чаще всего используется для денег.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Сообщение без иконки.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Выводит сообщение, которое исчезает в течении установленного времени.<br />
<br />
<br />
Примечание:<br />
- Все переменные являются публичными, кроме messageSubject, поэтому не стесняйтесь кастомизировать!<br />
<br />
<br />
Пример: Всплывающее сообщение об [[Файл:error-image-ingame.png]] ошибке: <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Меню==<br />
//добавить описание раздела<br />
<br />
===Получение информации о активной вкладки меню===<br />
Используйте ''Reflection'', чтобы узнать какая вкладка ''GameMenu'' сейчас активна. ''GameMenu'' содержит вкладки Инвентарь, Навыки, Светское, Карта, Изготовление предметов, Коллекции, и Настройки в указанном порядке. То есть вкладка ''inventoryTab'' имеет индекс 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Получение вкладки Карта<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Два примера проверки, что вкладка Карта открыта<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Установка активной вкладки меню===<br />
Game1.activeClickableMenu = <Menu><br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] позволяет напрямую использовать методы игры. Это очень мощный инструмент, но есть серьезные оговорки:<br />
<br />
* Очень легко вызвать сбои, ошибки или неотлавливаемые баги.<br />
* Это может привести к затруднению диагностики ошибок повреждения памяти.<br />
* Кроссплатформенная совместимость не гарантируется и должна быть протестирована на всех трех платформах.<br />
* Может конфликтовать с другими модами Harmony (например, если два мода используют один и тот же метод, или два мода пытаются загрузить разные версии Harmony).<br />
* Патчи Harmony могут иметь непредсказуемые эффекты для других модов, которые не используют Harmony.<br />
<br />
Использование Harmony должно быть последним средством, и поэтому намеренно не документировано.<br />
<br />
==Другое==<br />
===Добавление небольшой анимации===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
Смотрите ''TemporaryAnimatedSprite'' для детальной информации<br />
<br />
===Воспроизведение звука===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Отправка письма===<br />
<br />
Используйте IAssetEditor, чтобы добавить новое письмо в Data\Mail.xnb. Затем вызывайте метод Game1.addMailForTomorrow, чтобы отправить его игроку.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Где mailName ключ в Mail.xnb. Если использовать строку '''wizard''' где угодно в ключе, то письмо будет иметь волшебный фон[?] (начиная с 1.3) автоматически.<br />
<br />
==Исходные коды==<br />
Если что-то не получается, в большинстве случаев есть возможность подсмотреть реализацию в исходном коде другого мода. Смотрите столбец 'Исходный коды' в [[Modding:SMAPI compatibility|списке совместимых модификаций]].<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5861Модификации:Основные возможности2018-08-14T10:06:23Z<p>GIDMYRT: Выполнен основной перевод статьи</p>
<hr />
<div>← [[Модификации]]<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для параметра в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле], и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Предметами являются инструменты, семена, урожай и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на клетке===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Локации==<br />
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)<br />
<br />
''Game1.currentLocation'' является ссылкой на текущую локацию в которой находится игрок.<br />
<br />
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.<br />
<br />
===Свойства карты===<br />
Многие свойства карты, а также клеток на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]<br />
<br />
===Обработка клетки===<br />
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора клеток (земля, трава, грядка). <br />
<br />
Ниже приведен фрагмент для обработки клетки с [[Культуры|культурой]]:<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!<br />
<br />
===Обработка объектов на клетке===<br />
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах (семена, камень, древесина).<br />
<br />
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.<br />
<br />
==Игрок==<br />
<br />
===Местоположение===<br />
Позиция персонажа указывает координаты персонажа в текущей локации.<br />
<br />
====Позиция игрока в локации====<br />
Каждая локация представлена ''xTile'' картой, где левый верхний угол имеет координаты ''(0, 0)'', а правый нижний - ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' пикселей. <br />
<br />
Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам клетки.<br />
<br />
<code>Position.X</code> и <code>Position.Y</code> вернут координаты XY в пикселях.<br />
<br />
<code>getTileX()</code> и <code>getTileY()</code> вернут координаты XY клетки в сетке тайл-листа.<br />
<br />
Согласно <code>Game1.tileSize</code> клетка имеет размер 64x64 пикселей, что дает возможность конвертировать абсолютную и относительную позиции:<br />
<br />
<source lang='c#'><br />
// Абсолютная позиция => Позиция клетки<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Позиция клетки => Абсолютная позиция<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Размеры клетки<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Позиция игрока в видимой области====<br />
Размеры видимой области экрана можно узнать используя <code>Game1.viewport.Width</code> и <code>Game1.viewport.Height</code>. Размеры указаны в пикселях и соответствуют разрешению экрана игры.<br />
<br />
Также видимая область имеет абсолютную позицию относительно карты, где левый верхний угол находится в ''(Game1.viewport.X, Game1.viewport.Y)''.<br />
<br />
Позиция игрока относительно видимой области вычисляется следующим образом:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==Неигровые персонажи==<br />
===Создание пользовательского НИПа===<br />
Добавление нового НИПа включает в себя редактирование нескольких файлов:<br />
<br />
* Создание файла: Characters\Dialogue\<имя><br />
* Создание файла: Characters\schedules\<имя><br />
* Создание файла: Portraits\<имя><br />
* Создание файла: Characters\<имя><br />
* Добавление записей Data\EngagementDialogue для НИПов, с которыми можно заключить брак<br />
* Добавление записи в Data\NPCDispositions<br />
* Добавление записи в Data\NPCGiftTastes<br />
* Добавление записей в Characters\Dialogue\rainy<br />
* Добавление записей в Data\animationDescriptions (если нужны пользовательские анимации в расписании)<br />
<br />
Все это можно сделать с помощью IAssetLoaders/IAssetEditors или Content Patcher. В завершении, создается НИП, используя конструкторы SMAPI:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
Для спавна:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==Пользовательский интерфейс==<br />
<br />
Пользовательский интерфейс представляет собой набор отдельных элементов, которые составляют [https://ru.wikipedia.org/wiki/Head-Up_Display_(игры) HUD] и всплывающие окна.<br />
<br />
//необходимо дополнить раздел.<br />
<br />
<br />
===Всплывающие сообщения===<br />
HUDMessage - это всплывающие сообщения в нижнем левом углу экрана. У них есть несколько конструкторов, которые указаны ниже (несколько не релевантных были пропущены):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
Ниже даны описания основных аргументов, которые требуются для создания сообщения. (Для полного описания рекомендуется читать информацию о классе, но в большинстве ситуации информации ниже достаточно)<br />
<br />
WhatType:<br />
*1 - Достижение<br />
*2 - Новый квест<br />
*3 - Ошибка<br />
*4 - Выносливость<br />
*5 - Здоровье<br />
<br />
<br />
Color: Цвет. В первых двух конструкторах используется цвет по умолчанию (''Color:OrangeRed''), а в четвертом - параметр 'leaveMeNull' отображается тем же цветом, что и текст игры.<br />
<br />
<br />
Для примера:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - Подходит для кастомизации сообщения. Чаще всего используется для денег.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Сообщение без иконки.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Выводит сообщение, которое исчезает в течении установленного времени.<br />
<br />
<br />
Примечание:<br />
- Все переменные являются публичными, кроме messageSubject, поэтому не стесняйтесь кастомизировать!<br />
<br />
<br />
Пример: Всплывающее сообщение об [[Файл:error-image-ingame.png]] ошибке: <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==МЕню==<br />
//добавить описание раздела<br />
<br />
===Получение информации о активной вкладки меню===<br />
Используйте ''Reflection'', чтобы узнать какая вкладка ''GameMenu'' сейчас активна. ''GameMenu'' содержит вкладки Инвентарь, Навыки, Светское, Карта, Изготовление предметов, Коллекции, и Настройки в указанном порядке. То есть вкладка ''inventoryTab'' имеет индекс 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Получение вкладки Карта<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Два примера проверки, что вкладка Карта открыта<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Установка активной вкладки меню===<br />
Game1.activeClickableMenu = <Menu><br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] позволяет напрямую использовать методы игры. Это очень мощный инструмент, но есть серьезные оговорки:<br />
<br />
* Очень легко вызвать сбои, ошибки или неотлавливаемые баги.<br />
* Это может привести к затруднению диагностики ошибок повреждения памяти.<br />
* Кроссплатформенная совместимость не гарантируется и должна быть протестирована на всех трех платформах.<br />
* Может конфликтовать с другими модами Harmony (например, если два мода используют один и тот же метод, или два мода пытаются загрузить разные версии Harmony).<br />
* Патчи Harmony могут иметь непредсказуемые эффекты для других модов, которые не используют Harmony.<br />
<br />
Использование Harmony должно быть последним средством, и поэтому намеренно не документировано.<br />
<br />
==Другое==<br />
===Добавление небольшой анимации===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
Смотрите ''TemporaryAnimatedSprite'' для детальной информации<br />
<br />
===Воспроизведение звука===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Отправка письма===<br />
<br />
Используйте IAssetEditor, чтобы добавить новое письмо в Data\Mail.xnb. Затем вызывайте метод Game1.addMailForTomorrow, чтобы отправить его игроку.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Где mailName ключ в Mail.xnb. Если использовать строку '''wizard''' где угодно в ключе, то письмо будет иметь волшебный фон[?] (начиная с 1.3) автоматически.<br />
<br />
==Исходные коды==<br />
Если что-то не получается, в большинстве случаев есть возможность подсмотреть реализацию в исходном коде другого мода. Смотрите столбец 'Исходный коды' в [[Modding:SMAPI compatibility|списке совместимых модификаций]].<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5858Модификации:Основные возможности2018-08-13T14:41:48Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
{{Переведите}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на поверхности===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Локации==<br />
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)<br />
<br />
''Game1.currentLocation'' является ссылкой на локацию в которой находится игрок.<br />
<br />
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.<br />
<br />
===Свойства карты===<br />
Многие свойства карты, а также тайлов на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]<br />
<br />
===Обработка тайлов===<br />
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора тайлов (земля, трава, грядка). <br />
<br />
Ниже приведен фрагмент для обработки тайла с [[Культуры|культурой]]:<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!<br />
<br />
===Обработка объектов на тайле===<br />
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах на тайле (семена, камень, древесина).<br />
<br />
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.<br />
<br />
==Игрок==<br />
//добавить описание<br />
===Местоположение===<br />
Позиция персонажа указывает координаты персонажа в текущей локации.<br />
====Позиция игрока на карте====<br />
Каждая локация представлена ``xTile`` картой, где левых верхний угол имеет координаты ''(0, 0)'' пикселей, а правый нижний - ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' пикселей. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам тайла.<br />
<br />
<code>Position.X</code> и <code>Position.Y</code> вернут координаты XY в пикселях.<br />
<br />
<code>getTileX()</code> и <code>getTileY()</code> вернут координаты XY тайла в сетке тайл-листа.<br />
<br />
Согласно <code>Game1.tileSize</code> тайл имеет размер 64x64 пикселей. Это дает возможность конвертировать абсолютную и относительную позиции:<br />
<br />
<source lang='c#'><br />
// Абсолютная позиция => Позиция тайла<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Позиция тайла => Абсолютная позиция<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Размеры тайла<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Позиция игрока в видимой области====<br />
Размеры видимой области экрана можно узнать используя <code>Game1.viewport.Width</code> и <code>Game1.viewport.Height</code>. Размеры указаны в пикселях и соответствуют разрешению экрана игры.<br />
<br />
Также видимая область имеет абсолютную позицию относительно карты, где левый верхний угол находится в ''(Game1.viewport.X, Game1.viewport.Y)''.<br />
<br />
Позиция игрока относительно видимой области вычисляется следующим образом:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5857Модификации:Основные возможности2018-08-13T14:40:49Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
{{Переведите}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на поверхности===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Локации==<br />
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)<br />
<br />
''Game1.currentLocation'' является ссылкой на локацию в которой находится игрок.<br />
<br />
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.<br />
<br />
===Свойства карты===<br />
Многие свойства карты, а также тайлов на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]<br />
<br />
===Обработка тайлов===<br />
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора тайлов (земля, трава, грядка). <br />
<br />
Ниже приведен фрагмент для обработки тайла с [[Культуры|культурой]]:<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!<br />
<br />
===Обработка объектов на тайле===<br />
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах на тайле (семена, камень, древесина).<br />
<br />
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.<br />
<br />
==Игрок==<br />
//todo describe section<br />
===Местоположение===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
Позиция персонажа указывает координаты персонажа в текущей локации.<br />
====Позиция игрока на карте====<br />
Каждая локация представлена ``xTile`` картой, где левых верхний угол имеет координаты ''(0, 0)'' пикселей, а правый нижний - ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' пикселей. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам тайла.<br />
<br />
<code>Position.X</code> и <code>Position.Y</code> вернут координаты XY в пикселях.<br />
<br />
<code>getTileX()</code> и <code>getTileY()</code> вернут координаты XY тайла в сетке тайл-листа.<br />
<br />
Согласно <code>Game1.tileSize</code> тайл имеет размер 64x64 пикселей. Это дает возможность конвертировать абсолютную и относительную позиции:<br />
<br />
<source lang='c#'><br />
// Абсолютная позиция => Позиция тайла<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Позиция тайла => Абсолютная позиция<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Размеры тайла<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Позиция игрока в видимой области====<br />
Размеры видимой области экрана можно узнать используя <code>Game1.viewport.Width</code> и <code>Game1.viewport.Height</code>. Размеры указаны в пикселях и соответствуют разрешению экрана игры.<br />
<br />
Также видимая область имеет абсолютную позицию относительно карты, где левый верхний угол находится в ''(Game1.viewport.X, Game1.viewport.Y)''.<br />
<br />
Позиция игрока относительно видимой области вычисляется следующим образом:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5856Модификации:Основные возможности2018-08-13T10:55:19Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
{{Переведите}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на поверхности===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Локации==<br />
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)<br />
<br />
''Game1.currentLocation'' является ссылкой на локацию в которой находится игрок.<br />
<br />
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.<br />
<br />
===Свойства карты===<br />
Многие свойства карты, а также тайлов на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]<br />
<br />
===Обработка тайлов===<br />
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора тайлов (земля, трава, грядка). <br />
<br />
Ниже приведен фрагмент для обработки тайла с [[Культуры|культурой]]:<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!<br />
<br />
===Обработка объектов на тайле===<br />
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах на тайле (семена, камень, древесина).<br />
<br />
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5853Модификации:Основные возможности2018-08-12T16:03:20Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
{{Переведите}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на поверхности===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Локации==<br />
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)<br />
<br />
В ''Game1.currentLocation'' содержится ссылка на локацию в которой находится игрок.<br />
<br />
'''Важное предупреждение''': Начиная с версии 1.3, ''Game1.currentLocation'' лучше не использовать в мультиплеере.<br />
<br />
===Свойства карты===<br />
Многие свойства карты, а также тайлов на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]<br />
<br />
===Тайлы===<br />
''terrainFeatures'' содержит информацию о тайлах (земля, трава, посев)<br />
<br />
''objects'' содержит информацию об объектах на тайле (семена, камень, древесина)<br />
<br />
===Handling TerrainFeatures===<br />
<br />
As ''terrainFeatures'' is a NetField, always use .Pairs to access it for enumeration. The .Key value of this stores the location, and the .Value contains the terrainFeature itself. As a note, this includes items spawned off the map, which is usually cleared at end of day. <br />
<br />
If you need to access just crops, this snippet will be of use:<br />
<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
If you need some other location, sub that out for Game1.getFarm(). Note this doesn't null check Farm! Make sure Farm is loaded.<br />
<br />
===Handling Objects===<br />
<br />
There are several fields that handle objects, but always use the .objects one. The same rules apply as in TerrainFeatures, except that you really can't place objects beyond the edge of the map.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5852Модификации:Основные возможности2018-08-12T15:07:33Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
{{Переведите}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на поверхности===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Locations==<br />
The ''GameLocation'' is a representation of any place in the game (e.g. Farm, Town)<br />
<br />
The list of current locations is stored in ''Game1.currentLocations''<br />
<br />
'''Important Caveat''': In 1.3 onwards, the ''Game1.currentLocations'' is not reliable for farmhands in MP.<br />
<br />
===Map Properties===<br />
You can edit many properties of the current map and the tiles in the map. This is already documented here [[Modding:Maps#Map_properties | Map Properties]]<br />
<br />
===Tiles===<br />
''terrainFeatures'' contains information about the tiles. (e.g. dirt, grass, crops, etc.)<br />
<br />
''objects'' contains information about objects on top of tiles. (e.g. crops, stones)<br />
<br />
===Handling TerrainFeatures===<br />
<br />
As ''terrainFeatures'' is a NetField, always use .Pairs to access it for enumeration. The .Key value of this stores the location, and the .Value contains the terrainFeature itself. As a note, this includes items spawned off the map, which is usually cleared at end of day. <br />
<br />
If you need to access just crops, this snippet will be of use:<br />
<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
If you need some other location, sub that out for Game1.getFarm(). Note this doesn't null check Farm! Make sure Farm is loaded.<br />
<br />
===Handling Objects===<br />
<br />
There are several fields that handle objects, but always use the .objects one. The same rules apply as in TerrainFeatures, except that you really can't place objects beyond the edge of the map.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5844Модификации:Основные возможности2018-08-12T13:41:24Z<p>GIDMYRT: /* Items */</p>
<hr />
<div>← [[Модификации]]<br />
{{stub}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Предметы== <br />
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.<br />
<br />
===Создание предмета (Объекта)===<br />
Конструкторы класса для создания предмета:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).<br />
<br />
===Создание предмета на поверхности===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Спавн предмета в локации:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Добавление предмета в инвентарь===<br />
//todo<br />
<br />
===Удаление предмета из инвентаря===<br />
<br />
Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.<br />
<br />
Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)<br />
<br />
==Locations==<br />
The ''GameLocation'' is a representation of any place in the game (e.g. Farm, Town)<br />
<br />
The list of current locations is stored in ''Game1.currentLocations''<br />
<br />
'''Important Caveat''': In 1.3 onwards, the ''Game1.currentLocations'' is not reliable for farmhands in MP.<br />
<br />
===Map Properties===<br />
You can edit many properties of the current map and the tiles in the map. This is already documented here [[Modding:Maps#Map_properties | Map Properties]]<br />
<br />
===Tiles===<br />
''terrainFeatures'' contains information about the tiles. (e.g. dirt, grass, crops, etc.)<br />
<br />
''objects'' contains information about objects on top of tiles. (e.g. crops, stones)<br />
<br />
===Handling TerrainFeatures===<br />
<br />
As ''terrainFeatures'' is a NetField, always use .Pairs to access it for enumeration. The .Key value of this stores the location, and the .Value contains the terrainFeature itself. As a note, this includes items spawned off the map, which is usually cleared at end of day. <br />
<br />
If you need to access just crops, this snippet will be of use:<br />
<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
If you need some other location, sub that out for Game1.getFarm(). Note this doesn't null check Farm! Make sure Farm is loaded.<br />
<br />
===Handling Objects===<br />
<br />
There are several fields that handle objects, but always use the .objects one. The same rules apply as in TerrainFeatures, except that you really can't place objects beyond the edge of the map.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5842Модификации:Основные возможности2018-08-12T13:26:56Z<p>GIDMYRT: /* Basic techniques */</p>
<hr />
<div>← [[Модификации]]<br />
{{stub}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Основы==<br />
===Отслеживание изменений переменной===<br />
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:<br />
<br />
<source lang="c#"><br />
/// <summary>Входная точка мода.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Свойства<br />
*********/<br />
/// <summary>Последнее значение выносливости игрока.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Публичные методы<br />
*********/<br />
/// <summary>При первой загрузке мода вызывается метод Entry</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Приватные методы<br />
*********/<br />
/// <summary>Метод вызываемый при загрузке сохранения.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// выходим, если сохранение еще не загружено<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// выходим, если значение выносливости не изменилось<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// выводим сообщение и обновляем значение свойства LastStamina <br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Items==<br />
Items are objects which represent things which can be put in an inventory. Tools, Crops, etc. <br />
<br />
===Create an Item (Object)===<br />
All constructors for Object:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Where '''parentSheetIndex''' is the ID of the item (can be found in ObjectInformation.xnb).<br />
<br />
===Spawn an item on the ground===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Concrete code for spawning:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Add an item to an inventory===<br />
//todo<br />
<br />
===Remove an item from an inventory===<br />
<br />
This is dependent on the inventory - rarely will you be calling this directly, as the game has functions for this for the Player, located in Farmer (in the main namespace).<br />
<br />
To do so, in most situations, just call .removeItemFromInventory(Item)<br />
<br />
==Locations==<br />
The ''GameLocation'' is a representation of any place in the game (e.g. Farm, Town)<br />
<br />
The list of current locations is stored in ''Game1.currentLocations''<br />
<br />
'''Important Caveat''': In 1.3 onwards, the ''Game1.currentLocations'' is not reliable for farmhands in MP.<br />
<br />
===Map Properties===<br />
You can edit many properties of the current map and the tiles in the map. This is already documented here [[Modding:Maps#Map_properties | Map Properties]]<br />
<br />
===Tiles===<br />
''terrainFeatures'' contains information about the tiles. (e.g. dirt, grass, crops, etc.)<br />
<br />
''objects'' contains information about objects on top of tiles. (e.g. crops, stones)<br />
<br />
===Handling TerrainFeatures===<br />
<br />
As ''terrainFeatures'' is a NetField, always use .Pairs to access it for enumeration. The .Key value of this stores the location, and the .Value contains the terrainFeature itself. As a note, this includes items spawned off the map, which is usually cleared at end of day. <br />
<br />
If you need to access just crops, this snippet will be of use:<br />
<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
If you need some other location, sub that out for Game1.getFarm(). Note this doesn't null check Farm! Make sure Farm is loaded.<br />
<br />
===Handling Objects===<br />
<br />
There are several fields that handle objects, but always use the .objects one. The same rules apply as in TerrainFeatures, except that you really can't place objects beyond the edge of the map.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5841Модификации:Основные возможности2018-08-12T13:05:18Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
{{stub}}<br />
<br />
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Basic techniques==<br />
===Tracking changes to a value===<br />
Mods often need to know when a value changed. If there's no SMAPI event for the value, you can create a private [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/fields field] to track the value, and update it using the update tick event. For example, here's a fully functional mod which prints a console message when the player's stamina changes:<br />
<br />
<source lang="c#"><br />
/// <summary>The mod entry point.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Properties<br />
*********/<br />
/// <summary>The player's last stamina value.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Public methods<br />
*********/<br />
/// <summary>The mod entry point, called after the mod is first loaded.</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Private methods<br />
*********/<br />
/// <summary>The method invoked when the player loads a save.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>The method invoked after the game updates (roughly 60 times per second).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// skip if save not loaded yet<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// skip if stamina not changed<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// print message & update stamina<br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Items==<br />
Items are objects which represent things which can be put in an inventory. Tools, Crops, etc. <br />
<br />
===Create an Item (Object)===<br />
All constructors for Object:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Where '''parentSheetIndex''' is the ID of the item (can be found in ObjectInformation.xnb).<br />
<br />
===Spawn an item on the ground===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Concrete code for spawning:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Add an item to an inventory===<br />
//todo<br />
<br />
===Remove an item from an inventory===<br />
<br />
This is dependent on the inventory - rarely will you be calling this directly, as the game has functions for this for the Player, located in Farmer (in the main namespace).<br />
<br />
To do so, in most situations, just call .removeItemFromInventory(Item)<br />
<br />
==Locations==<br />
The ''GameLocation'' is a representation of any place in the game (e.g. Farm, Town)<br />
<br />
The list of current locations is stored in ''Game1.currentLocations''<br />
<br />
'''Important Caveat''': In 1.3 onwards, the ''Game1.currentLocations'' is not reliable for farmhands in MP.<br />
<br />
===Map Properties===<br />
You can edit many properties of the current map and the tiles in the map. This is already documented here [[Modding:Maps#Map_properties | Map Properties]]<br />
<br />
===Tiles===<br />
''terrainFeatures'' contains information about the tiles. (e.g. dirt, grass, crops, etc.)<br />
<br />
''objects'' contains information about objects on top of tiles. (e.g. crops, stones)<br />
<br />
===Handling TerrainFeatures===<br />
<br />
As ''terrainFeatures'' is a NetField, always use .Pairs to access it for enumeration. The .Key value of this stores the location, and the .Value contains the terrainFeature itself. As a note, this includes items spawned off the map, which is usually cleared at end of day. <br />
<br />
If you need to access just crops, this snippet will be of use:<br />
<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
If you need some other location, sub that out for Game1.getFarm(). Note this doesn't null check Farm! Make sure Farm is loaded.<br />
<br />
===Handling Objects===<br />
<br />
There are several fields that handle objects, but always use the .objects one. The same rules apply as in TerrainFeatures, except that you really can't place objects beyond the edge of the map.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5_%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8&diff=5840Модификации:Основные возможности2018-08-12T13:01:33Z<p>GIDMYRT: Новая страница: «← Index {{stub}} This page covers how to do common tasks in SMAPI mods. '''Before reading this page, see the Modding:Modder Guide|Modder Gu…»</p>
<hr />
<div>← [[Modding:Index|Index]]<br />
{{stub}}<br />
<br />
This page covers how to do common tasks in SMAPI mods. '''Before reading this page, see the [[Modding:Modder Guide|Modder Guide]] and [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''<br />
<br />
==Basic techniques==<br />
===Tracking changes to a value===<br />
Mods often need to know when a value changed. If there's no SMAPI event for the value, you can create a private [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/fields field] to track the value, and update it using the update tick event. For example, here's a fully functional mod which prints a console message when the player's stamina changes:<br />
<br />
<source lang="c#"><br />
/// <summary>The mod entry point.</summary><br />
internal class ModEntry : Mod<br />
{<br />
/*********<br />
** Properties<br />
*********/<br />
/// <summary>The player's last stamina value.</summary><br />
private float LastStamina;<br />
<br />
<br />
/*********<br />
** Public methods<br />
*********/<br />
/// <summary>The mod entry point, called after the mod is first loaded.</summary><br />
/// <param name="helper">Provides simplified APIs for writing mods.</param><br />
public override void Entry(IModHelper helper)<br />
{<br />
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;<br />
GameEvents.UpdateTick += this.GameEvents_UpdateTick;<br />
}<br />
<br />
<br />
/*********<br />
** Private methods<br />
*********/<br />
/// <summary>The method invoked when the player loads a save.</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void SaveEvents_AfterLoad(object sender, EventArgs e)<br />
{<br />
this.LastStamina = Game1.player.Stamina;<br />
}<br />
<br />
/// <summary>The method invoked after the game updates (roughly 60 times per second).</summary><br />
/// <param name="sender">The event sender.</param><br />
/// <param name="e">The event arguments.</param><br />
private void GameEvents_UpdateTick(object sender, EventArgs e)<br />
{<br />
// skip if save not loaded yet<br />
if (!Context.IsWorldReady)<br />
return;<br />
<br />
// skip if stamina not changed<br />
float currentStamina = Game1.player.Stamina;<br />
if (currentStamina == this.LastStamina)<br />
return;<br />
<br />
// print message & update stamina<br />
this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");<br />
this.LastStamina = currentStamina;<br />
}<br />
}<br />
</source><br />
<br />
==Items==<br />
Items are objects which represent things which can be put in an inventory. Tools, Crops, etc. <br />
<br />
===Create an Item (Object)===<br />
All constructors for Object:<br />
<br />
<source lang='c#'><br />
public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);<br />
public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);<br />
public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);<br />
</source><br />
<br />
Where '''parentSheetIndex''' is the ID of the item (can be found in ObjectInformation.xnb).<br />
<br />
===Spawn an item on the ground===<br />
<br />
<source lang='c#'><br />
public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);<br />
<br />
// Concrete code for spawning:<br />
Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);<br />
</source><br />
<br />
===Add an item to an inventory===<br />
//todo<br />
<br />
===Remove an item from an inventory===<br />
<br />
This is dependent on the inventory - rarely will you be calling this directly, as the game has functions for this for the Player, located in Farmer (in the main namespace).<br />
<br />
To do so, in most situations, just call .removeItemFromInventory(Item)<br />
<br />
==Locations==<br />
The ''GameLocation'' is a representation of any place in the game (e.g. Farm, Town)<br />
<br />
The list of current locations is stored in ''Game1.currentLocations''<br />
<br />
'''Important Caveat''': In 1.3 onwards, the ''Game1.currentLocations'' is not reliable for farmhands in MP.<br />
<br />
===Map Properties===<br />
You can edit many properties of the current map and the tiles in the map. This is already documented here [[Modding:Maps#Map_properties | Map Properties]]<br />
<br />
===Tiles===<br />
''terrainFeatures'' contains information about the tiles. (e.g. dirt, grass, crops, etc.)<br />
<br />
''objects'' contains information about objects on top of tiles. (e.g. crops, stones)<br />
<br />
===Handling TerrainFeatures===<br />
<br />
As ''terrainFeatures'' is a NetField, always use .Pairs to access it for enumeration. The .Key value of this stores the location, and the .Value contains the terrainFeature itself. As a note, this includes items spawned off the map, which is usually cleared at end of day. <br />
<br />
If you need to access just crops, this snippet will be of use:<br />
<br />
<source lang="c#"><br />
<br />
foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)<br />
{<br />
if ((tf.Value is HoeDirt hd) && hd.crop != null)<br />
{<br />
// do crop like things here.<br />
}<br />
}<br />
</source><br />
<br />
If you need some other location, sub that out for Game1.getFarm(). Note this doesn't null check Farm! Make sure Farm is loaded.<br />
<br />
===Handling Objects===<br />
<br />
There are several fields that handle objects, but always use the .objects one. The same rules apply as in TerrainFeatures, except that you really can't place objects beyond the edge of the map.<br />
<br />
==Player==<br />
//todo describe section<br />
===Position===<br />
A Character's position indicates the Character's coordinates in the current location. <br />
<br />
====Position Relative to the Map====<br />
Each location has an ``xTile`` map where the top-left corner of the map is ''(0, 0)'' and the bottom-right corner of the map is ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' in pixels. <br />
<br />
There are two ways to get a Character's position in the current location: by absolute position and by tile position.<br />
<br />
<code>Position.X</code> and <code>Position.Y</code> will give the XY coordinates in pixels.<br />
<br />
<code>getTileX()</code> and <code>getTileY()</code> will give the XY coordinates in tiles.<br />
<br />
Each tile is 64x64 pixels as specified by <code>Game1.tileSize</code>. The conversion between absolute and tile is as follows:<br />
<source lang='c#'><br />
// Absolute position => Tile position<br />
Math.Floor(Game1.player.Position.X / Game1.tileSize)<br />
Math.Floor(Game1.player.Position.Y / Game1.tileSize)<br />
<br />
// Tile position => Absolute position<br />
Game1.player.getTileX() * Game1.tileSize<br />
Game1.player.getTileY() * Game1.tileSize<br />
<br />
// Tilemap dimensions<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)<br />
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)<br />
</source><br />
<br />
====Position Relative to the Viewport====<br />
The viewport represents the visible area on the screen. Its dimensions are <code>Game1.viewport.Width</code> by <code>Game1.viewport.Height</code> in pixels; this is the same as the game's screen resolution.<br />
<br />
The viewport also has an absolute position relative to the map, where the top-left corner of the viewport is at ''(Game1.viewport.X, Game1.viewport.Y)''. <br />
<br />
<br />
The player's position in pixels relative to the viewport is as follows:<br />
<source lang='c#'><br />
Game1.player.Position.X - Game1.viewport.X<br />
Game1.player.Position.Y - Game1.viewport.Y<br />
</source><br />
<br />
==NPC==<br />
===Creating Custom NPCs===<br />
Adding new NPCs involves editing a number of files:<br />
<br />
* New file: Characters\Dialogue\<name><br />
* New file: Characters\schedules\<name><br />
* New file: Portraits\<name><br />
* New file: Characters\<name><br />
* Add entries Data\EngagementDialogue for NPCs that are marriable<br />
* Add entry to Data\NPCDispositions<br />
* Add entry to Data\NPCGiftTastes<br />
* Add entries to Characters\Dialogue\rainy<br />
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)<br />
<br />
All of the above can be done with IAssetLoaders/IAssetEditors or Content Patcher. Finally, spawn the NPC with a SMAPI mod. The different constructors are:<br />
<br />
<source lang='c#'><br />
public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);<br />
public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);<br />
</source><br />
<br />
For spawning:<br />
<br />
<source lang='c#'><br />
Game1.getLocationFromName("Town").addCharacter(npc);<br />
</source><br />
<br />
==UI==<br />
<br />
The UI is a collection of separate elements which make up the HUD and occasional popups.<br />
<br />
//todo expand section.<br />
<br />
<br />
===Banner Message===<br />
HUDMessage are those popups in the lower left hand screen. They have several constructors, which we will briefly go over here (a few non relevant ones have been snipped):<br />
<br />
<source lang="c#"><br />
public HUDMessage(string message);<br />
public HUDMessage(string message, int whatType);<br />
public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);<br />
public HUDMessage(string message, string leaveMeNull)<br />
public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)<br />
</source><br />
<br />
<br />
So before we go over when you'd use them, I'm going to briefly note how the class HUDMessage uses these. (I encourage people to read the class if they have further questions, but I doubt most of us will need to know more than this)<br />
<br />
<br />
WhatType:<br />
*1 - Achievement<br />
*2 - New Quest<br />
*3 - Error<br />
*4 - Stamina<br />
*5 - Health<br />
<br />
<br />
Color: Fairly obvious. It should be noted that while the first two don't give an option (they default to ''Color:OrangeRed''), the fourth with the param 'leaveMeNull' displays as the same color as the game text.<br />
<br />
<br />
For specifics:<br />
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - This allows for expanded customization of the message. More often used for money.<br />
*'' public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.<br />
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.<br />
<br />
<br />
Note: For those of you who want a custom HUDMessage: <br />
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!<br />
<br />
<br />
<br />
For example: add a new HUDMessage to show [insert image] toaster popup. <br />
<source lang="c#"><br />
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));<br />
</source><br />
<br />
==Menus==<br />
//todo describe section<br />
===Get the Active Menu===<br />
You can use ''Reflection'' to get the current active menu in ''GameMenu''. The ''GameMenu'' contains the Inventory, Skills, Social, Map, Crafting, Collections, and Options pages in this respective order, accessed by the tab index with ''inventoryTab'' at 0.<br />
<br />
<source lang="c#"><br />
if (Game1.activeClickableMenu is GameMenu menu) {<br />
IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();<br />
IClickableMenu page = pages[menu.currentTab];<br />
<br />
// Example for getting the MapPage<br />
MapPage mapPage = (MapPage) pages[menu.currentTab];<br />
<br />
// Two examples of checking if MapPage is open<br />
pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;<br />
}<br />
</source><br />
<br />
===Set the Active Menu===<br />
Game1.activeClickableMenu = <Menu><br />
===Simple Menu===<br />
Copy the menu you want from the game and make it your own<br />
<br />
==Harmony==<br />
{{quote|Here be dragons. Thou art forewarned.}}<br />
<br />
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:<br />
<br />
* It's very easy to cause crashes, errors, or subtle bugs.<br />
* It may cause difficult-to-diagnose memory corruption errors.<br />
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.<br />
* May conflict with other Harmony mods (e.g. if two mods patch the same method, or two mods try to load different versions of Harmony).<br />
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.<br />
<br />
Using Harmony should be a last resort, and is deliberately not documented.<br />
<br />
==Other==<br />
===Add a small animation===<br />
<source lang="c#"><br />
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))<br />
</source><br />
See ''TemporaryAnimatedSprite'' for more details<br />
<br />
===Play a sound===<br />
<source lang="c#"><br />
location.playSound("SOUND"); <br />
</source><br />
(e.g. "junimoMeep1")<br />
<br />
===Send a letter===<br />
<br />
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.<br />
<br />
<source lang="c#"><br />
public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);<br />
</source><br />
<br />
Where mailName is the letter key in Mail.xnb. If you use the string '''wizard''' anywhere in the letter key, the letter will have the Wizard's new background (since 1.3) automatically.<br />
<br />
==Open source==<br />
When all else fails, when you've looked at the decompiled source too long and it makes no sense, take a look at some open-source mod code! See the 'source' column in the [[Modding:SMAPI compatibility|mod compatibility list]] for source code.<br />
<br />
[[Category:Modding]]<br />
<br />
[[en:Modding:Common tasks]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%A0%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2&diff=5836Модификации:Редактирование XNB файлов2018-08-12T10:59:18Z<p>GIDMYRT: /* Изображения */</p>
<hr />
<div>← [[Модификации]]<br />
<br />
На этой странице объясняется, как редактировать файлы игры для изменения внутриигровых данных, изображений и карт.<br />
<br />
==Введение==<br />
===Что такое XNB файл?===<br />
Игра хранит свои данные в сжатом контейнере <tt>.xnb</tt> формата в директории <tt>Content</tt>. Например, [[Абигейл#Портреты|портреты Абигейл]], отображаемые во время диалога, упакованы в файл <tt>Content\Portraits\Abigail.xnb</tt>. Каждый <tt>.xnb</tt> файл содержит два файла: файл с данными (например, изображение), и файл с метаданными (информация о файле с данными). К примеру, вот что находится внутри <tt>Content\Portraits\Abigail.xnb</tt>:<br />
<br />
<pre><br />
Abigail.xnb<br />
Abigail.png<br />
Abigail.yaml<br />
</pre><br />
<br />
В примере выше:<br />
<br />
* <tt>Abigail.png</tt> содержит портреты Абигейл. Отредактировав этот файл можно изменить портреты в игре:<br />[[File:Modding - creating an XNB mod - example portraits.png]]<br />
<br />
* <tt>Abigail.yaml</tt> содержит метаданные о файле <tt>Abigail.png</tt> (например, какого он типа). Не нужно беспокоиться об этом файле, так как обычно он не изменяется.<br />
<br />
===Как внести изменения в игру?===<br />
Существуют три способа создания изменений:<br />
<br />
# Создать с помощью [https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] контент пакет. Таким образом можно изменить XNB файл игры без использования программирования (просто отредактировать файл JSON), а также не заменять оригинальный файл игры.<br />
# [[Руководство по созданию модификаций|Создание SMAPI мода]] и использование его [[Modding:Modder_Guide/APIs/Content|Content API]]. Требуются навыки программирования.<br />
# Создание XNB мода и замена оригинальных файлов. Этот метод крайне не рекомендуется; смотрите [[Использование XNB модификаций|использование XNB модификаций]] для получения дополнительной информации.<br />
<br />
===Где получить помощь?===<br />
Сообщество мододелов Stardew Valley дружелюбно. Спросите совета у [[Модификации:Сообщество|других мододелов]].<br />
<br />
==Распаковывание и упаковывание ресурсов==<br />
Файлы формата <tt>.xnb</tt> представляют собой сжатый контейнер и не редактируются. Для редактирования ресурсов игры используется программа xnbcli, позволяющая распаковывать и упаковывать XNB файлы. Она кроссплатформена и имеет [https://github.com/LeonBlade/xnbcli открытый исходный код].<br />
<br />
Как это работает:<br />
<br />
# Скачивается [https://github.com/LeonBlade/xnbcli/releases xnbcli].<br />
# Распаковывается файл для редактирования:<br />
## Находится нужный <tt>.xnb</tt> файл в директории [[Модификации:Директория игры|<tt>Content</tt>]].<br />
##Копируется в директорию <tt>packed</tt> программы xnbcli.<br />
## Двойной клик по <tt>unpack.bat</tt> (Windows) или <tt>unpack.sh</tt> (Linux/Mac).<br />
# Редактирование распакованных данных (смотрите ниже).<br />
# Упаковывание ресурсов назад в файл:<br />
## Двойной клик по <tt>pack.bat</tt> (Windows) или <tt>pack.sh</tt> (Linux/Mac).<br />
## Замена оригинального <tt>.xnb</tt> файла измененным.<br />
<br />
==Редактирование распакованных данных==<br />
===Данные===<br />
XNB данные имеют разные форматы. Для детальной информации смотрите раздел [[Модификации#Дополнительно]].<br />
<br />
===Изображения===<br />
[[File:Modding - creating an XNB mod - example tilesheet.png|thumb|Пример тайл-листа, который состоит из сетки тайлов как этот: [[File:Modding - creating an XNB mod - example tile 1.png]]]]<br />
Несколько определений:<br />
* '''Спрайт-лист''' представляет собой PNG-файл, содержащий небольшие изображения (обычно в виде сетки). Каждый квадрат сетки называется ''спрайтом''. Например, спрайты многих объектов хранятся в <tt>Content\Maps\spring_objects.xnb</tt>.<br />
* '''Тайл-лист''' является синонимом спрайт-листа, который содержит в себе тайлы карты. Каждый квадрат сетки называется ''тайлом'' и имеет размер 16×16 пикселей.<br />
* '''Портрет''' спрайты содержащие портреты персонажей. Находятся в <tt>Content\Characters\*.xnb</tt>.<br />
<br />
Спрайт-листы легко редактируются:<br />
# [[#Распаковывание и упаковывание ресурсов|Распаковывается <tt>.xnb</tt> файл]], ресурсы которого будут редактироваться.<br />
# Открывается <tt>.png</tt> файл в графическом редакторе (например [http://www.getpaint.net/download.html Paint.NET] для Windows, или [https://www.gimp.org/downloads/ GIMP] для Linux/Mac).<br />
# Вносятся изменения в изображение.<br />
# [[#Распаковывание и упаковывание ресурсов|Упаковываются ресурсы]] в <tt>.xnb</tt> файл, и он переносится в исходную директорию.<br />
<br />
Теперь можно запустить игру, и увидеть изменения.<br />
<br />
===Карты===<br />
Смотрите [[Модификации:Карты]].<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Editing XNB files]]<br />
[[zh:使用模组:制作一个XNB模组]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%A0%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2&diff=5835Модификации:Редактирование XNB файлов2018-08-12T10:58:00Z<p>GIDMYRT: </p>
<hr />
<div>← [[Модификации]]<br />
<br />
На этой странице объясняется, как редактировать файлы игры для изменения внутриигровых данных, изображений и карт.<br />
<br />
==Введение==<br />
===Что такое XNB файл?===<br />
Игра хранит свои данные в сжатом контейнере <tt>.xnb</tt> формата в директории <tt>Content</tt>. Например, [[Абигейл#Портреты|портреты Абигейл]], отображаемые во время диалога, упакованы в файл <tt>Content\Portraits\Abigail.xnb</tt>. Каждый <tt>.xnb</tt> файл содержит два файла: файл с данными (например, изображение), и файл с метаданными (информация о файле с данными). К примеру, вот что находится внутри <tt>Content\Portraits\Abigail.xnb</tt>:<br />
<br />
<pre><br />
Abigail.xnb<br />
Abigail.png<br />
Abigail.yaml<br />
</pre><br />
<br />
В примере выше:<br />
<br />
* <tt>Abigail.png</tt> содержит портреты Абигейл. Отредактировав этот файл можно изменить портреты в игре:<br />[[File:Modding - creating an XNB mod - example portraits.png]]<br />
<br />
* <tt>Abigail.yaml</tt> содержит метаданные о файле <tt>Abigail.png</tt> (например, какого он типа). Не нужно беспокоиться об этом файле, так как обычно он не изменяется.<br />
<br />
===Как внести изменения в игру?===<br />
Существуют три способа создания изменений:<br />
<br />
# Создать с помощью [https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] контент пакет. Таким образом можно изменить XNB файл игры без использования программирования (просто отредактировать файл JSON), а также не заменять оригинальный файл игры.<br />
# [[Руководство по созданию модификаций|Создание SMAPI мода]] и использование его [[Modding:Modder_Guide/APIs/Content|Content API]]. Требуются навыки программирования.<br />
# Создание XNB мода и замена оригинальных файлов. Этот метод крайне не рекомендуется; смотрите [[Использование XNB модификаций|использование XNB модификаций]] для получения дополнительной информации.<br />
<br />
===Где получить помощь?===<br />
Сообщество мододелов Stardew Valley дружелюбно. Спросите совета у [[Модификации:Сообщество|других мододелов]].<br />
<br />
==Распаковывание и упаковывание ресурсов==<br />
Файлы формата <tt>.xnb</tt> представляют собой сжатый контейнер и не редактируются. Для редактирования ресурсов игры используется программа xnbcli, позволяющая распаковывать и упаковывать XNB файлы. Она кроссплатформена и имеет [https://github.com/LeonBlade/xnbcli открытый исходный код].<br />
<br />
Как это работает:<br />
<br />
# Скачивается [https://github.com/LeonBlade/xnbcli/releases xnbcli].<br />
# Распаковывается файл для редактирования:<br />
## Находится нужный <tt>.xnb</tt> файл в директории [[Модификации:Директория игры|<tt>Content</tt>]].<br />
##Копируется в директорию <tt>packed</tt> программы xnbcli.<br />
## Двойной клик по <tt>unpack.bat</tt> (Windows) или <tt>unpack.sh</tt> (Linux/Mac).<br />
# Редактирование распакованных данных (смотрите ниже).<br />
# Упаковывание ресурсов назад в файл:<br />
## Двойной клик по <tt>pack.bat</tt> (Windows) или <tt>pack.sh</tt> (Linux/Mac).<br />
## Замена оригинального <tt>.xnb</tt> файла измененным.<br />
<br />
==Редактирование распакованных данных==<br />
===Данные===<br />
XNB данные имеют разные форматы. Для детальной информации смотрите раздел [[Модификации#Дополнительно]].<br />
<br />
===Изображения===<br />
[[File:Modding - creating an XNB mod - example tilesheet.png|thumb|Пример tilesheet, который состоит из сетки тайловgrid of tiles like this: [[File:Modding - creating an XNB mod - example tile 1.png]]]]<br />
Несколько определений:<br />
* '''Спрайт-лист''' представляет собой PNG-файл, содержащий небольшие изображения (обычно в виде сетки). Каждый квадрат сетки называется ''спрайтом''. Например, спрайты многих объектов хранятся в <tt>Content\Maps\spring_objects.xnb</tt>.<br />
* '''Тайл-лист''' является синонимом спрайт-листа, который содержит в себе тайлы карты. Каждый квадрат сетки называется ''тайлом'' и имеет размер 16×16 пикселей.<br />
* '''Портрет''' спрайты содержащие портреты персонажей. Находятся в <tt>Content\Characters\*.xnb</tt>.<br />
<br />
Спрайт-листы легко редактируются:<br />
# [[#Распаковывание и упаковывание ресурсов|Распаковывается <tt>.xnb</tt> файл]], ресурсы которого будут редактироваться.<br />
# Открывается <tt>.png</tt> файл в графическом редакторе (например [http://www.getpaint.net/download.html Paint.NET] для Windows, или [https://www.gimp.org/downloads/ GIMP] для Linux/Mac).<br />
# Вносятся изменения в изображение.<br />
# [[#Распаковывание и упаковывание ресурсов|Упаковываются ресурсы]] в <tt>.xnb</tt> файл, и он переносится в исходную директорию.<br />
<br />
Теперь можно запустить игру, и увидеть изменения.<br />
<br />
===Карты===<br />
Смотрите [[Модификации:Карты]].<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Editing XNB files]]<br />
[[zh:使用模组:制作一个XNB模组]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5834Модификации:Индекс2018-08-12T09:43:23Z<p>GIDMYRT: </p>
<hr />
<div>{{Stub|'Неполный перевод статьи'}}<br />
'''Модификации''' — это дополнения от сторонних разработчиков, которые изменяют или дополняют оригинальный контент Stardew Valley.<br />
<br />
==Руководства==<br />
{|<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по использованию модификаций]]'''</big><br />Установка ядра SMAPI, использование модификаций, и решение возможных проблем.<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по созданию модификаций]]'''</big><br />Создание модификаций, использующих ядро SMAPI. Включает документацию по SMAPI API.<br />
|}<br />
<br />
==Дополнительно==<br />
===Для игроков===<br />
* [[Модификации:Использование XNB модификаций|Использование XNB модификаций]] (не рекомендуется)<br />
<br />
===Для мододелов===<br />
* [[Модификации:Настройка среды разработки|Настройка среды разработки]]<br />
* [[Модификации:Редактирование XNB файлов|Редактирование XNB файлов]]<br />
* [[Модификации:Основные возможности|Основные возможности]]<br />
* [[Модификации:Карты|Создание и редактирование карт]]<br />
* Неигровые персонажы:<br />
** [[Модификации:Диалоги|Диалоги]]<br />
** [[Модификации:События|События]]<br />
** [[Модификации:Подарки|Подарки]]<br />
** [[Модификации:Расписание|Расписание]]<br />
<br />
* Объекты:<br />
** [[Модификации:Изготовляемые предметы|Изготовляемые предметы]]<br />
** [[Модификации:Crop data|Crops]]<br />
** [[Модификации:Furniture data|Furniture]]<br />
** [[Модификации:Hat data|Hats]]<br />
** [[Модификации:Object data|Objects]]<br />
<br />
* Другое:<br />
** [[Модификации:Достижения|Достижения]]<br />
** [[Модификации:Blueprint data|Blueprints]]<br />
** [[Модификации:Команды для отладки|Команды для отладки]]<br />
** [[Модификации:Рыболовство|Рыболовство]]<br />
** [[Модификации:Погодные явления|Погодные явления]]<br />
<br />
===Руководства по переходу на новые версии===<br />
* [[Модификации:Переход на SMAPI 2.0|Переход на SMAPI 2.0]] (Октябрь 2017)<br />
* [[Модификации:Переход на Stardew Valley 1.3|Переход на Stardew Valley 1.3]] (Май 2018)<br />
* [[Модификации:Изменения XNB в Stardew Valley 1.3|Изменения XNB в Stardew Valley 1.3]] (Май 2018)<br />
<br />
===Смотрите также===<br />
* [[Модификации:Сообщество#Discord|Чат в Discord]] — получение помощи, общение с мододелами и разработчиками SMAPI.<br />
<br />
[[File:SMAPI mascot.png|20px]]<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Index]]<br />
[[es:Mods]]<br />
[[pt:Modificações:Índice]]<br />
[[zh:使用模组:目录]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5833Модификации:Индекс2018-08-12T09:42:42Z<p>GIDMYRT: </p>
<hr />
<div>{{Stub|'Неполный перевод статьи'}}<br />
'''Модификации''' — это дополнения от сторонних разработчиков, которые изменяют или дополняют оригинальный контент Stardew Valley.<br />
<br />
==Руководства==<br />
{|<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по использованию модификаций]]'''</big><br />Установка ядра SMAPI, использование модификаций, и решение возможных проблем.<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по созданию модификаций]]'''</big><br />Создание модификаций, использующих ядро SMAPI. Включает документацию по SMAPI API.<br />
|}<br />
<br />
==Дополнительно==<br />
===Для игроков===<br />
* [[Модификации:Использование XNB модификаций]] (не рекомендуется)<br />
===Для мододелов===<br />
* [[Модификации:Настройка среды разработки|Настройка среды разработки]]<br />
* [[Модификации:Редактирование XNB файлов|Редактирование XNB файлов]]<br />
* [[Модификации:Основные возможности|Основные возможности]]<br />
* [[Модификации:Карты|Создание и редактирование карт]]<br />
* Неигровые персонажы:<br />
** [[Модификации:Диалоги|Диалоги]]<br />
** [[Модификации:События|События]]<br />
** [[Модификации:Подарки|Подарки]]<br />
** [[Модификации:Расписание|Расписание]]<br />
<br />
* Объекты:<br />
** [[Модификации:Изготовляемые предметы|Изготовляемые предметы]]<br />
** [[Модификации:Crop data|Crops]]<br />
** [[Модификации:Furniture data|Furniture]]<br />
** [[Модификации:Hat data|Hats]]<br />
** [[Модификации:Object data|Objects]]<br />
<br />
* Другое:<br />
** [[Модификации:Достижения|Достижения]]<br />
** [[Модификации:Blueprint data|Blueprints]]<br />
** [[Модификации:Команды для отладки|Команды для отладки]]<br />
** [[Модификации:Рыболовство|Рыболовство]]<br />
** [[Модификации:Погодные явления|Погодные явления]]<br />
<br />
===Руководства по переходу на новые версии===<br />
* [[Модификации:Переход на SMAPI 2.0|Переход на SMAPI 2.0]] (Октябрь 2017)<br />
* [[Модификации:Переход на Stardew Valley 1.3|Переход на Stardew Valley 1.3]] (Май 2018)<br />
* [[Модификации:Изменения XNB в Stardew Valley 1.3|Изменения XNB в Stardew Valley 1.3]] (Май 2018)<br />
<br />
===Смотрите также===<br />
* [[Модификации:Сообщество#Discord|Чат в Discord]] — получение помощи, общение с мододелами и разработчиками SMAPI.<br />
<br />
[[File:SMAPI mascot.png|20px]]<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Index]]<br />
[[es:Mods]]<br />
[[pt:Modificações:Índice]]<br />
[[zh:使用模组:目录]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5799Модификации:Индекс2018-08-11T15:47:41Z<p>GIDMYRT: </p>
<hr />
<div>{{Stub|'Неполный перевод статьи'}}<br />
'''Модификации''' — это дополнения от сторонних разработчиков, которые изменяют или дополняют оригинальный контент Stardew Valley.<br />
<br />
==Руководства==<br />
{|<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по использованию модификаций]]'''</big><br />Установка ядра SMAPI, использование модификаций, и решение возможных проблем.<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по созданию модификаций]]'''</big><br />Создание модификаций, использующих ядро SMAPI. Включает документацию по SMAPI API.<br />
|}<br />
<br />
==Дополнительно==<br />
===Для игроков===<br />
* [[Использование XNB модификаций]] (не рекомендуется)<br />
===Для мододелов===<br />
* [[Модификации:Настройка среды разработки|Настройка среды разработки]]<br />
* [[Модификации:Редактирование XNB файлов|Редактирование XNB файлов]]<br />
* [[Модификации:Основные возможности|Основные возможности]]<br />
* [[Модификации:Карты|Создание и редактирование карт]]<br />
* Неигровые персонажы:<br />
** [[Модификации:Диалоги|Диалоги]]<br />
** [[Модификации:События|События]]<br />
** [[Модификации:Подарки|Подарки]]<br />
** [[Модификации:Расписание|Расписание]]<br />
<br />
* Объекты:<br />
** [[Модификации:Big Craftables data|Craftable items]]<br />
** [[Модификации:Crop data|Crops]]<br />
** [[Модификации:Furniture data|Furniture]]<br />
** [[Модификации:Hat data|Hats]]<br />
** [[Модификации:Object data|Objects]]<br />
<br />
* Другое:<br />
** [[Модификации:Achievement data|Achievements]]<br />
** [[Модификации:Blueprint data|Blueprints]]<br />
** [[Модификации:Debug commands|Debug commands]]<br />
** [[Модификации:Fish data|Fish]]<br />
** [[Модификации:Weather data|Weather]]<br />
<br />
===Руководства по переходу на новые версии===<br />
* [[Модификации:Переход на SMAPI 2.0|Переход на SMAPI 2.0]] (Октябрь 2017)<br />
* [[Модификации:Переход на Stardew Valley 1.3|Переход на Stardew Valley 1.3]] (Май 2018)<br />
* [[Модификации:Изменения XNB в Stardew Valley 1.3|Изменения XNB в Stardew Valley 1.3]] (Май 2018)<br />
<br />
===Смотрите также===<br />
* [[Модификации:Сообщество#Discord|Чат в Discord]] — получение помощи, общение с мододелами и разработчиками SMAPI.<br />
<br />
[[File:SMAPI mascot.png|20px]]<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Index]]<br />
[[es:Mods]]<br />
[[pt:Modificações:Índice]]<br />
[[zh:使用模组:目录]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B9&diff=5798Модификации:Использование XNB модификаций2018-08-11T15:43:15Z<p>GIDMYRT: </p>
<hr />
<div>←[[Модификации]]<br />
<br />
<div style="border: 1px solid red; background: #FCC; padding: 1em;">'''XNB модификации являются устаревшими и не рекомендуются к использованию. SMAPI не может проверить их на совместимость. Используйте XNB модификации на свой страх и риск.'''</div><br />
<br />
Все '''XNB модификации''' заменяют собой <tt>.xnb</tt> файл для внесения изменений в игру.<br />
<br />
==FAQs==<br />
===Что такое XNB мод?===<br />
XNB мод работает посредством замены файлов игры (которые имеют расширение <tt>.xnb</tt>). Например, чтобы изменить [[Абигейл#Портреты|портреты Абигейл]] необходимо заменить файл <tt>Content/Portraits/Abigail.xnb</tt> его модифицированной версией. (Смотрите [[Модификации:Редактирование XNB файлов|редактирование XNB файлов]] для получения информации о формате XNB.)<br />
<br />
===Почему они не рекомендуются?===<br />
XNB моды имеют множество ограничений, часто конфликтуют друг с другом, обычно перестают работать при обновлении игры, а также сложны в установке и удалении.<br />
<br />
Используйте [[Modding:Player Guide|SMAPI моды и content packs]]. Они имеют определенные преимущества над XNB модами:<br />
{| class="wikitable"<br />
|-<br />
! Возможность<br />
! XNB мод<br />
! SMAPI мод<br />
! SMAPI content packs<br />
|-<br />
| Простота установки<br />
| ✘ отличается для каждого мода<br />
|colspan="2"| ✓ добавить в директорию <tt>Mods</tt><br />
|- <br />
| Простота удаления<br />
| ✘ ручное восстановление оригинальных файлов<br />
|colspan="2"| ✓ удалить из директории <tt>Mods</tt><br />
|-<br />
| Проверка обновлений<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ автоматическое оповещение в консоли SMAPI<br />
|-<br />
| Проверка совместимости<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ несовместимые модификации отключаются. <br />✓ [[Modding:SMAPI compatibility|Список совместимых модификаций]] регулярно обновляется и дополняется<br />
|-<br />
| Совместимость модов<br />
| ✘ каждый файл может быть заменен только один раз<br />
| ✓ почти универсальные<br />
| ✓ высокая<br />
|-<br />
| Поддержка переводов<br />
| ✘ сложны в переводе<br />
| ✓ используется специальное API для переводов<br />
| ''(зависит от содержимого content pack)''<br />
|-<br />
| Игровая совместимость<br />
| ✘ часто не работает после обновления игры<br />
|colspan="2"| ✓ SMAPI автоматически перезаписывает многие моды для совместимости<br />✓ моды с открытым исходным кодом обновляются быстро<br />
|}<br />
<br />
===Работают ли они на Linux, Mac, Windows или игровых консолях?===<br />
XNB моды работают одинаково на Linux, Mac, и Windows. Игровые консоли не поддерживаются.<br />
<br />
===Могут ли они повредить сохранения?===<br />
Да, но это редкость. Перед удалением модификации убедитесь, что были сделаны резервные копии [[Сохранения|файлов сохранений]], а также удален пользовательский контент. В некоторых случаях, возможно восстановить файл [[Saves#Undo the last save|возвратом к предыдущему сохранению]].<br />
<br />
===Они отключают достижения Steam?===<br />
Нет.<br />
<br />
==Модификация Content Patcher==<br />
[https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] - это SMAPI мод, который создает XNB-подобные изменения со всеми преимуществами [[Modding:Content packs|SMAPI контент пакетов]]. Многие XNB моды имеют поддержку Content Patcher, а в некоторые она была добавлена неофициально. По возможности лучше использовать их.<br />
<br />
Смотрите [[Modding:SMAPI compatibility#XNB mods]].<br />
<br />
==Использование XNB модификаций==<br />
===Поиск модификаций===<br />
<br />
Модификации можно найти на следующих порталах:<br />
{| class="wikitable"<br />
|-<br />
! Сайт<br />
! Описание<br />
|-<br />
| '''[http://nexusmods.com/stardewvalley/ Nexus Mods]'''<br />
| Многие моды размещаются здесь.<br /><small>(Регистрация учетной записи является бесплатной, просто не выбирайте пакет при регистрации.)</small><br />
|-<br />
| [http://community.playstarbound.com/resources/categories/stardew-valley.22/ Chucklefish mods]<br />
| Некоторые из размещенных модификаций также присутствуют на Nexus Mods.<br />
|-<br />
| [http://community.playstarbound.com/forums/mods.215/ Stardew Valley forums]<br />
| Некоторые моды размещаются непосредственно на форуме. Определенные "жемчужины" находятся только здесь, но найти их может быть проблемой.<br />
|}<br />
<br />
Прежде чем скачать мод...<br />
* Проверьте работает ли он с последней версией игры? XNB моды могут быть устаревшими и вызывать проблемы. Прочитайте описание или комментарии к нему. Старайтесь избегать XNB модификаций после последнего обновления игры.<br />
* '''Не загружайте''' со stardewvalleymods.net. (Моды здесь, как правило, устарели, поскольку сайт повторно публикует их без разрешения, для получения дохода от рекламы.)<br />
<br />
===Установка модификации===<br />
Установка различается для каждого мода. Прочитайте описание мода для получения точной информации. Но в основном это:<br />
<br />
# Скачивание XNB мода и распаковка его в любую директорию(но не в директорию с игрой!).<br />
# В нем должны находится несколько <tt>.xnb</tt> файлов.<br />
# Найдите вашу [[Модификации:Директория игры|директорию с игрой]].<br />
# Замена существующих <tt>.xnb</tt> файлов в директории <tt>Content</tt> файлами мода. '''Убедитесь, что вы заменили правильные файлы!''' Существуют разные файлы с одинаковым именем (например, <tt>Content/Data/hats.xnb</tt> и <tt>Content/Characters/hats.xnb</tt>), и замена неправильного файла приведет к ошибкам или сбоям в игре.<br />
<br />
===Удаление модификации===<br />
Удаление заключается в восстановлении оригинальных файлов замененных модом (если они были сохранены заранее), или в [[Modding:Player Guide/Troubleshooting#Reset your content files|повторном скачивании файлов игры]].<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Using XNB mods]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%A0%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2&diff=5797Модификации:Редактирование XNB файлов2018-08-11T15:41:46Z<p>GIDMYRT: Новая страница: «← Модификации {{Stub}} На этой странице объясняется, как редактировать файлы игры для из…»</p>
<hr />
<div>← [[Модификации]]<br />
{{Stub}}<br />
<br />
На этой странице объясняется, как редактировать файлы игры для изменения внутриигровых данных, изображений и карт.<br />
<br />
==Введение==<br />
===Что такое XNB файл?===<br />
Игра хранит свои данные в сжатом <tt>.xnb</tt> формате внутри директории <tt>Content</tt>. Например, [[Абигейл#Портреты|портреты Абигейл]], отображаемые во время диалога, упакованы в файл<tt>Content\Portraits\Abigail.xnb</tt>. Каждый <tt>.xnb</tt> файл содержит два файла: файл с данными (например, изображение), и файл с метаданными (информация о файле с данными). К примеру, вот что находится внутри <tt>Content\Portraits\Abigail.xnb</tt>:<br />
<br />
<pre><br />
Abigail.xnb<br />
Abigail.png<br />
Abigail.yaml<br />
</pre><br />
<br />
В примере выше:<br />
<br />
* <tt>Abigail.png</tt> содержит портреты Абигейл. Отредактировав этот файл можно изменить портреты в игре:<br />[[File:Modding - creating an XNB mod - example portraits.png]]<br />
* <tt>Abigail.yaml</tt> содержит метаданные о файле <tt>Abigail.png</tt> (например, какого он типа). Не нужно беспокоиться об этом файле, так как обычно он не изменяется.<br />
<br />
===Как внести изменения в игру?===<br />
Существуют три способа создания изменений:<br />
<br />
# Создать с помощью [https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] контент пакет. Таким образом можно изменить XNB файл игры без использования программирования (просто отредактировать файл JSON), а также не заменять оригинальный файл игры.<br />
# [[Руководство по созданию модификаций|Создание SMAPI мода]] и использование его [[Modding:Modder_Guide/APIs/Content|Content API]]. Требуются навыки программирования.<br />
# Создание XNB мода и замена оригинальных файлов. Этот метод крайне не рекомендуется; смотрите [[Использование XNB модификаций|использование XNB модификаций]] для получения дополнительной информации.<br />
<br />
===Где получить помощь?===<br />
Сообщество мододелов Stardew Valley дружелюбно. Спросите совета у [[Modding:Community|других мододелов]].<br />
<br />
==Начало работы==<br />
===Первоначальная настройка===<br />
Перед началом, необходимо установить:<br />
<br />
:; на Windows<br />
<br />
::* '''[https://www.mediafire.com/?b86xecd27yti6f6 XNB Extract 0.2.2]''' для распаковки и упаковки XNB файлов. <small>(Смотрите [http://community.playstarbound.com/threads/beginners-guide-to-xnb-node-and-graphics-editing.110976/ тему на форуме].)</small><br />
::* '''[http://www.getpaint.net/download.html Paint.NET]''' для редактирования изображений (или другой любимый графический редактор).<br />
<br />
:; на Linux/Mac<br />
<br />
::* '''[https://www.winehq.org/download Wine 1.7 или позднее]''' для запуска XNB Extract.<br />
::* '''[https://www.dropbox.com/s/oj5tch8np74nk4d/XNBExtract0.2.2.zip?dl=0 XNB Extract 0.2.2 for Linux/Mac]''' для распаковки и упаковки XNB файлов.<br />
::* '''[https://www.gimp.org/downloads/ GIMP]''' для редактирования изображений (или другой любимый графический редактор).<br />
<br />
Также необходимо создать резервную копию директорию <tt>Content</tt> вашей игры, чтобы восстановить оригинальные файлы в случае ошибки.<br />
<br />
===Unpack & pack game files===<br />
<span id="unpacking"></span><br />
<br />
You can't edit an <tt>.xnb</tt> file itself, you need to edit the file that's inside it. Pulling out that inner file is called ''unpacking'', and putting it back is called ''packing''. Here's how to do it:<br />
<br />
# Download XNB Extract (see [[#First-time setup]]).<br />
# Unpack the file for editing:<br />
## Find the file you want to edit in the [[Modding:Game folder|game's <tt>Content</tt> folder]].<br />
## Copy it into XNB Extract's <tt>Packed</tt> folder.<br />
## Double-click <tt>UnpackFiles.bat</tt> (Windows) or <tt>UnpackFiles.sh</tt> (Linux/Mac).<br />
# Edit the unpacked file (see below).<br />
# Repack the file for the game:<br />
## Double-click <tt>PackFiles.bat</tt> (Windows) or <tt>PackFiles.sh</tt> (Linux/Mac).<br />
## Move the repacked <tt>.xnb</tt> file back to the original location.<br />
<br />
==Getting started (experimental alternative)==<br />
xnbcli is a new tool for packing and unpacking XNB files. It's [https://github.com/LeonBlade/xnbcli open-source] and natively crossplatform, but still new. Try it out and [[Modding:Community#Discord|let us know]] how it goes!<br />
<br />
<div style="border:2px solid gray; padding:0.5em;"><br />
===Unpack & pack game files===<br />
You can't edit an <tt>.xnb</tt> file itself, you need to edit the file that's inside it. Pulling out that inner file is called ''unpacking'', and putting it back is called ''packing''. Here's how to do it:<br />
<br />
# Download [https://github.com/LeonBlade/xnbcli/releases xnbcli].<br />
# Unpack the file for editing:<br />
## Find the file you want to edit in the [[Modding:Game folder|game's <tt>Content</tt> folder]].<br />
## Copy it into xnbcli's <tt>packed</tt> folder.<br />
## Double-click <tt>unpack.bat</tt> (Windows) or <tt>unpack.sh</tt> (Linux/Mac).<br />
# Edit the unpacked file (see below).<br />
# Repack the file for the game:<br />
## Double-click <tt>pack.bat</tt> (Windows) or <tt>pack.sh</tt> (Linux/Mac).<br />
## Move the repacked <tt>.xnb</tt> file back to the original location.<br />
</div><br />
<br />
==Making changes==<br />
===Data===<br />
Each data XNB has its own format. See the documentation at [[Modding:Index#Advanced topics]].<br />
<br />
===Images===<br />
[[File:Modding - creating an XNB mod - example tilesheet.png|thumb|An example tilesheet, which consists of a grid of tiles like this: [[File:Modding - creating an XNB mod - example tile 1.png]]]]<br />
A few definitions:<br />
* A '''spritesheet''' is a PNG file containing small images (usually in a regular grid pattern). Each square in the spritesheet's grid pattern is called a '''sprite'''. For example, each in-game item has a sprite in <tt>Content\Maps\spring_objects.xnb</tt>.<br />
* A '''tilesheet''' is a synonym for spritesheet when used for map tiles. In a tilesheet, each square is called a ''tile'' and is 16×16 pixels.<br />
* A '''portrait''' is a sprite from the <tt>Content\Characters\*.xnb</tt> spritesheets.<br />
<br />
Spritesheets are easy to edit:<br />
# [[#unpacking|Unpack the file]] you want to change.<br />
# Open the unpacked <tt>.png</tt> file in an image editor (like [http://www.getpaint.net/download.html Paint.NET] on Windows, or [https://www.gimp.org/downloads/ GIMP] on Linux/Mac).<br />
# Make changes directly to the image.<br />
# [[#unpacking|Repack the file]] and copy it back to the original location.<br />
<br />
That's it! You can launch the game to see your changes.<br />
<br />
===Maps===<br />
See [[Модификации:Карты]].<br />
<br />
[[Category:Modding]]<br />
<br />
[[zh:使用模组:制作一个XNB模组]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5796Модификации:Индекс2018-08-11T14:50:26Z<p>GIDMYRT: </p>
<hr />
<div>{{Stub|'Неполный перевод статьи'}}<br />
'''Модификации''' — это дополнения от сторонних разработчиков, которые изменяют или дополняют оригинальный контент Stardew Valley.<br />
<br />
==Руководства==<br />
{|<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по использованию модификаций|Руководство по использованию модификаций]]'''</big><br />Установка ядра SMAPI, использование модификаций, и решение возможных проблем.<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по созданию модификаций|Руководство по созданию модификаций]]'''</big><br />Создание модификаций, использующих ядро SMAPI. Включает документацию по SMAPI API.<br />
|}<br />
<br />
==Дополнительно==<br />
===Для игроков===<br />
* [[Использование XNB модификаций]] (не рекомендуется)<br />
===Для мододелов===<br />
* [[Модификации:Настройка среды разработки|Настройка среды разработки]]<br />
* [[Модификации:Редактирование XNB файлов|Редактирование XNB файлов]]<br />
* [[Модификации:Основные возможности|Основные возможности]]<br />
* [[Модификации:Карты|Создание и редактирование карт]]<br />
* Неигровые персонажы:<br />
** [[Модификации:Диалоги|Диалоги]]<br />
** [[Модификации:События|События]]<br />
** [[Модификации:Подарки|Подарки]]<br />
** [[Модификации:Расписание|Расписание]]<br />
<br />
* Объекты:<br />
** [[Модификации:Big Craftables data|Craftable items]]<br />
** [[Модификации:Crop data|Crops]]<br />
** [[Модификации:Furniture data|Furniture]]<br />
** [[Модификации:Hat data|Hats]]<br />
** [[Модификации:Object data|Objects]]<br />
<br />
* Другое:<br />
** [[Модификации:Achievement data|Achievements]]<br />
** [[Модификации:Blueprint data|Blueprints]]<br />
** [[Модификации:Debug commands|Debug commands]]<br />
** [[Модификации:Fish data|Fish]]<br />
** [[Модификации:Weather data|Weather]]<br />
<br />
===Руководства по переходу на новые версии===<br />
* [[Модификации:Переход на SMAPI 2.0|Переход на SMAPI 2.0]] (Октябрь 2017)<br />
* [[Модификации:Переход на Stardew Valley 1.3|Переход на Stardew Valley 1.3]] (Май 2018)<br />
* [[Модификации:Изменения XNB в Stardew Valley 1.3|Изменения XNB в Stardew Valley 1.3]] (Май 2018)<br />
<br />
===Смотрите также===<br />
* [[Модификации:Сообщество#Discord|Чат в Discord]] — получение помощи, общение с мододелами и разработчиками SMAPI.<br />
<br />
[[File:SMAPI mascot.png|20px]]<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Index]]<br />
[[es:Mods]]<br />
[[pt:Modificações:Índice]]<br />
[[zh:使用模组:目录]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B9&diff=5795Модификации:Использование XNB модификаций2018-08-11T14:49:42Z<p>GIDMYRT: </p>
<hr />
<div>←[[Модификации]]<br />
<br />
<div style="border: 1px solid red; background: #FCC; padding: 1em;">'''XNB модификации являются устаревшими и не рекомендуются к использованию. SMAPI не может проверить их на совместимость. Используйте XNB модификации на свой страх и риск.'''</div><br />
<br />
Все '''XNB модификации''' заменяют собой <tt>.xnb</tt> файл для внесения изменений в игру.<br />
<br />
==FAQs==<br />
===Что такое XNB мод?===<br />
XNB мод работает посредством замены файлов игры (которые имеют расширение <tt>.xnb</tt>). Например, чтобы изменить [[Абигейл#Портреты|портреты Абигейл]] необходимо заменить файл <tt>Content/Portraits/Abigail.xnb</tt> его модифицированной версией. (Смотрите [[Модификации:Редактирование XNB файлов|редактирование XNB файлов]] для получения информации о формате XNB.)<br />
<br />
===Почему они не рекомендуются?===<br />
XNB моды имеют множество ограничений, часто конфликтуют друг с другом, обычно перестают работать при обновлении игры, а также сложны в установке и удалении.<br />
<br />
Используйте [[Modding:Player Guide|SMAPI моды и content packs]]. Они имеют определенные преимущества над XNB модами:<br />
{| class="wikitable"<br />
|-<br />
! Возможность<br />
! XNB мод<br />
! SMAPI мод<br />
! SMAPI content packs<br />
|-<br />
| Простота установки<br />
| ✘ отличается для каждого мода<br />
|colspan="2"| ✓ добавить в директорию <tt>Mods</tt><br />
|- <br />
| Простота удаления<br />
| ✘ ручное восстановление оригинальных файлов<br />
|colspan="2"| ✓ удалить из директории <tt>Mods</tt><br />
|-<br />
| Проверка обновлений<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ автоматическое оповещение в консоли SMAPI<br />
|-<br />
| Проверка совместимости<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ несовместимые модификации отключаются. <br />✓ [[Modding:SMAPI compatibility|Список совместимых модификаций]] регулярно обновляется и дополняется<br />
|-<br />
| Совместимость модов<br />
| ✘ каждый файл может быть заменен только один раз<br />
| ✓ почти универсальные<br />
| ✓ высокая<br />
|-<br />
| Поддержка переводов<br />
| ✘ сложны в переводе<br />
| ✓ используется специальное API для переводов<br />
| ''(зависит от содержимого content pack)''<br />
|-<br />
| Игровая совместимость<br />
| ✘ часто не работает после обновления игры<br />
|colspan="2"| ✓ SMAPI автоматически перезаписывает многие моды для совместимости<br />✓ моды с открытым исходным кодом обновляются быстро<br />
|}<br />
<br />
===Работают ли они на Linux, Mac, Windows или игровых консолях?===<br />
XNB моды работают одинаково на Linux, Mac, и Windows. Игровые консоли не поддерживаются.<br />
<br />
===Могут ли они повредить сохранения?===<br />
Да, но это редкость. Перед удалением модификации убедитесь, что были сделаны резервные копии [[Сохранения|файлов сохранений]], а также удален пользовательский контент. В некоторых случаях, возможно восстановить файл [[Saves#Undo the last save|возвратом к предыдущему сохранению]].<br />
<br />
===Они отключают достижения Steam?===<br />
Нет.<br />
<br />
==Модификация Content Patcher==<br />
[https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] - это SMAPI мод, который создает XNB-подобные изменения со всеми преимуществами [[Modding:Content packs|SMAPI контент пакетов]]. Многие XNB моды имеют поддержку Content Patcher, а в некоторые она была добавлена неофициально. По возможности лучше использовать их.<br />
<br />
Смотрите [[Modding:SMAPI compatibility#XNB mods]].<br />
<br />
==Использование XNB модификаций==<br />
===Поиск модификаций===<br />
<br />
Модификации можно найти на следующих порталах:<br />
{| class="wikitable"<br />
|-<br />
! Сайт<br />
! Описание<br />
|-<br />
| '''[http://nexusmods.com/stardewvalley/ Nexus Mods]'''<br />
| Многие моды размещаются здесь.<br /><small>(Регистрация учетной записи является бесплатной, просто не выбирайте пакет при регистрации.)</small><br />
|-<br />
| [http://community.playstarbound.com/resources/categories/stardew-valley.22/ Chucklefish mods]<br />
| Некоторые из размещенных модификаций также присутствуют на Nexus Mods.<br />
|-<br />
| [http://community.playstarbound.com/forums/mods.215/ Stardew Valley forums]<br />
| Некоторые моды размещаются непосредственно на форуме. Определенные "жемчужины" находятся только здесь, но найти их может быть проблемой.<br />
|}<br />
<br />
Прежде чем скачать мод...<br />
* Проверьте работает ли он с последней версией игры? XNB моды могут быть устаревшими и вызывать проблемы. Прочитайте описание или комментарии к нему. Старайтесь избегать XNB модификаций после последнего обновления игры.<br />
* '''Не загружайте''' со stardewvalleymods.net. (Моды здесь, как правило, устарели, поскольку сайт повторно публикует их без разрешения, для получения дохода от рекламы.)<br />
<br />
===Установка модификации===<br />
Установка различается для каждого мода. Прочитайте описание мода для получения точной информации. Но в основном это:<br />
<br />
# Скачивание XNB мода и распаковка его в любую директорию(но не в директорию с игрой!).<br />
# В нем должны находится несколько <tt>.xnb</tt> файлов.<br />
# Найдите вашу [[Модификации:Директория игры|директорию с игрой]].<br />
# Замена существующих <tt>.xnb</tt> файлов в директории <tt>Content</tt> файлами мода. '''Убедитесь, что вы заменили правильные файлы!''' Существуют разные файлы с одинаковым именем (например, <tt>Content/Data/hats.xnb</tt> и <tt>Content/Characters/hats.xnb</tt>), и замена неправильного файла приведет к ошибкам или сбоям в игре.<br />
<br />
===Удаление модификации===<br />
Удаление заключается в восстановлении оригинальных файлов замененных модом (если они были сохранены заранее), или в [[Modding:Player Guide/Troubleshooting#Reset your content files|повторном скачивании файлов игры]].<br />
<br />
[[Category:Модификации]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B9&diff=5794Модификации:Использование XNB модификаций2018-08-11T14:47:16Z<p>GIDMYRT: /* Поиск модификаций */</p>
<hr />
<div>←[[Modding:Index|Index]]<br />
<br />
<div style="border: 1px solid red; background: #FCC; padding: 1em;">'''XNB модификации являются устаревшими и не рекомендуются к использованию. SMAPI не может проверить их на совместимость. Используйте XNB модификации на свой страх и риск.'''</div><br />
<br />
Все '''XNB модификации''' заменяют собой <tt>.xnb</tt> файл для внесения изменений в игру.<br />
<br />
==FAQs==<br />
===Что такое XNB мод?===<br />
XNB мод работает посредством замены файлов игры (которые имеют расширение <tt>.xnb</tt>). Например, чтобы изменить [[Абигейл#Портреты|портреты Абигейл]] необходимо заменить файл <tt>Content/Portraits/Abigail.xnb</tt> его модифицированной версией. (Смотрите [[Модификации:Редактирование XNB файлов|редактирование XNB файлов]] для получения информации о формате XNB.)<br />
<br />
===Почему они не рекомендуются?===<br />
XNB моды имеют множество ограничений, часто конфликтуют друг с другом, обычно перестают работать при обновлении игры, а также сложны в установке и удалении.<br />
<br />
Используйте [[Modding:Player Guide|SMAPI моды и content packs]]. Они имеют определенные преимущества над XNB модами:<br />
{| class="wikitable"<br />
|-<br />
! Возможность<br />
! XNB мод<br />
! SMAPI мод<br />
! SMAPI content packs<br />
|-<br />
| Простота установки<br />
| ✘ отличается для каждого мода<br />
|colspan="2"| ✓ добавить в директорию <tt>Mods</tt><br />
|- <br />
| Простота удаления<br />
| ✘ ручное восстановление оригинальных файлов<br />
|colspan="2"| ✓ удалить из директории <tt>Mods</tt><br />
|-<br />
| Проверка обновлений<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ автоматическое оповещение в консоли SMAPI<br />
|-<br />
| Проверка совместимости<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ несовместимые модификации отключаются. <br />✓ [[Modding:SMAPI compatibility|Список совместимых модификаций]] регулярно обновляется и дополняется<br />
|-<br />
| Совместимость модов<br />
| ✘ каждый файл может быть заменен только один раз<br />
| ✓ почти универсальные<br />
| ✓ высокая<br />
|-<br />
| Поддержка переводов<br />
| ✘ сложны в переводе<br />
| ✓ используется специальное API для переводов<br />
| ''(зависит от содержимого content pack)''<br />
|-<br />
| Игровая совместимость<br />
| ✘ часто не работает после обновления игры<br />
|colspan="2"| ✓ SMAPI автоматически перезаписывает многие моды для совместимости<br />✓ моды с открытым исходным кодом обновляются быстро<br />
|}<br />
<br />
===Работают ли они на Linux, Mac, Windows или игровых консолях?===<br />
XNB моды работают одинаково на Linux, Mac, и Windows. Игровые консоли не поддерживаются.<br />
<br />
===Могут ли они повредить сохранения?===<br />
Да, но это редкость. Перед удалением модификации убедитесь, что были сделаны резервные копии [[Сохранения|файлов сохранений]], а также удален пользовательский контент. В некоторых случаях, возможно восстановить файл [[Saves#Undo the last save|возвратом к предыдущему сохранению]].<br />
<br />
===Они отключают достижения Steam?===<br />
Нет.<br />
<br />
==Модификация Content Patcher==<br />
[https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] - это SMAPI мод, который создает XNB-подобные изменения со всеми преимуществами [[Modding:Content packs|SMAPI контент пакетов]]. Многие XNB моды имеют поддержку Content Patcher, а в некоторые она была добавлена неофициально. По возможности лучше использовать их.<br />
<br />
Смотрите [[Modding:SMAPI compatibility#XNB mods]].<br />
<br />
==Использование XNB модификаций==<br />
===Поиск модификаций===<br />
<br />
Модификации можно найти на следующих порталах:<br />
{| class="wikitable"<br />
|-<br />
! Сайт<br />
! Описание<br />
|-<br />
| '''[http://nexusmods.com/stardewvalley/ Nexus Mods]'''<br />
| Многие моды размещаются здесь.<br /><small>(Регистрация учетной записи является бесплатной, просто не выбирайте пакет при регистрации.)</small><br />
|-<br />
| [http://community.playstarbound.com/resources/categories/stardew-valley.22/ Chucklefish mods]<br />
| Некоторые из размещенных модификаций также присутствуют на Nexus Mods.<br />
|-<br />
| [http://community.playstarbound.com/forums/mods.215/ Stardew Valley forums]<br />
| Некоторые моды размещаются непосредственно на форуме. Определенные "жемчужины" находятся только здесь, но найти их может быть проблемой.<br />
|}<br />
<br />
Прежде чем скачать мод...<br />
* Проверьте работает ли он с последней версией игры? XNB моды могут быть устаревшими и вызывать проблемы. Прочитайте описание или комментарии к нему. Старайтесь избегать XNB модификаций после последнего обновления игры.<br />
* '''Не загружайте''' со stardewvalleymods.net. (Моды здесь, как правило, устарели, поскольку сайт повторно публикует их без разрешения, для получения дохода от рекламы.)<br />
<br />
===Установка модификации===<br />
Установка различается для каждого мода. Прочитайте описание мода для получения точной информации. Но в основном это:<br />
<br />
# Скачивание XNB мода и распаковка его в любую директорию(но не в директорию с игрой!).<br />
# В нем должны находится несколько <tt>.xnb</tt> файлов.<br />
# Найдите вашу [[Модификации:Директория игры|директорию с игрой]].<br />
# Замена существующих <tt>.xnb</tt> файлов в директории <tt>Content</tt> файлами мода. '''Убедитесь, что вы заменили правильные файлы!''' Существуют разные файлы с одинаковым именем (например, <tt>Content/Data/hats.xnb</tt> и <tt>Content/Characters/hats.xnb</tt>), и замена неправильного файла приведет к ошибкам или сбоям в игре.<br />
<br />
===Удаление модификации===<br />
Удаление заключается в восстановлении оригинальных файлов замененных модом (если они были сохранены заранее), или в [[Modding:Player Guide/Troubleshooting#Reset your content files|повторном скачивании файлов игры]].<br />
<br />
[[Category:Модификации]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B9&diff=5793Модификации:Использование XNB модификаций2018-08-11T14:45:49Z<p>GIDMYRT: </p>
<hr />
<div>←[[Modding:Index|Index]]<br />
<br />
<div style="border: 1px solid red; background: #FCC; padding: 1em;">'''XNB модификации являются устаревшими и не рекомендуются к использованию. SMAPI не может проверить их на совместимость. Используйте XNB модификации на свой страх и риск.'''</div><br />
<br />
Все '''XNB модификации''' заменяют собой <tt>.xnb</tt> файл для внесения изменений в игру.<br />
<br />
==FAQs==<br />
===Что такое XNB мод?===<br />
XNB мод работает посредством замены файлов игры (которые имеют расширение <tt>.xnb</tt>). Например, чтобы изменить [[Абигейл#Портреты|портреты Абигейл]] необходимо заменить файл <tt>Content/Portraits/Abigail.xnb</tt> его модифицированной версией. (Смотрите [[Модификации:Редактирование XNB файлов|редактирование XNB файлов]] для получения информации о формате XNB.)<br />
<br />
===Почему они не рекомендуются?===<br />
XNB моды имеют множество ограничений, часто конфликтуют друг с другом, обычно перестают работать при обновлении игры, а также сложны в установке и удалении.<br />
<br />
Используйте [[Modding:Player Guide|SMAPI моды и content packs]]. Они имеют определенные преимущества над XNB модами:<br />
{| class="wikitable"<br />
|-<br />
! Возможность<br />
! XNB мод<br />
! SMAPI мод<br />
! SMAPI content packs<br />
|-<br />
| Простота установки<br />
| ✘ отличается для каждого мода<br />
|colspan="2"| ✓ добавить в директорию <tt>Mods</tt><br />
|- <br />
| Простота удаления<br />
| ✘ ручное восстановление оригинальных файлов<br />
|colspan="2"| ✓ удалить из директории <tt>Mods</tt><br />
|-<br />
| Проверка обновлений<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ автоматическое оповещение в консоли SMAPI<br />
|-<br />
| Проверка совместимости<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ несовместимые модификации отключаются. <br />✓ [[Modding:SMAPI compatibility|Список совместимых модификаций]] регулярно обновляется и дополняется<br />
|-<br />
| Совместимость модов<br />
| ✘ каждый файл может быть заменен только один раз<br />
| ✓ почти универсальные<br />
| ✓ высокая<br />
|-<br />
| Поддержка переводов<br />
| ✘ сложны в переводе<br />
| ✓ используется специальное API для переводов<br />
| ''(зависит от содержимого content pack)''<br />
|-<br />
| Игровая совместимость<br />
| ✘ часто не работает после обновления игры<br />
|colspan="2"| ✓ SMAPI автоматически перезаписывает многие моды для совместимости<br />✓ моды с открытым исходным кодом обновляются быстро<br />
|}<br />
<br />
===Работают ли они на Linux, Mac, Windows или игровых консолях?===<br />
XNB моды работают одинаково на Linux, Mac, и Windows. Игровые консоли не поддерживаются.<br />
<br />
===Могут ли они повредить сохранения?===<br />
Да, но это редкость. Перед удалением модификации убедитесь, что были сделаны резервные копии [[Сохранения|файлов сохранений]], а также удален пользовательский контент. В некоторых случаях, возможно восстановить файл [[Saves#Undo the last save|возвратом к предыдущему сохранению]].<br />
<br />
===Они отключают достижения Steam?===<br />
Нет.<br />
<br />
==Модификация Content Patcher==<br />
[https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] - это SMAPI мод, который создает XNB-подобные изменения со всеми преимуществами [[Modding:Content packs|SMAPI контент пакетов]]. Многие XNB моды имеют поддержку Content Patcher, а в некоторые она была добавлена неофициально. По возможности лучше использовать их.<br />
<br />
Смотрите [[Modding:SMAPI compatibility#XNB mods]].<br />
<br />
==Использование XNB модификаций==<br />
===Поиск модификаций===<br />
<br />
Модификации можно найти на следующих порталах:<br />
{| class="wikitable"<br />
|-<br />
! Сайт<br />
! Описание<br />
|-<br />
| '''[http://nexusmods.com/stardewvalley/ Nexus Mods]'''<br />
| Многие моды размещаются здесь.<br /><small>(Регистрация учетной записи является бесплатной, просто не выбирайте пакет при регистрации.)</small><br />
|-<br />
| [http://community.playstarbound.com/resources/categories/stardew-valley.22/ Chucklefish mods]<br />
| Некоторые из размещенных модификаций также присутствуют на Nexus Mods.<br />
|-<br />
| [http://community.playstarbound.com/forums/mods.215/ Stardew Valley forums]<br />
| Некоторые моды размещаются непосредственно на форуме. Определенные "жемчужины" находятся только здесь, но найти их может быть проблемой.<br />
|}<br />
<br />
Прежде чем скачать мод...<br />
* Работает ли она с последней версией игры? XNB моды могут быть устаревшими и вызывать проблемы. Прочитайте описание или комментарии к моду. Старайтесь избегать XNB модификаций после последнего обновления игры.<br />
* '''Не загружайте''' со stardewvalleymods.net. (Моды здесь, как правило, устарели, поскольку сайт повторно публикует их без разрешения, для получения дохода от рекламы.)<br />
<br />
===Установка модификации===<br />
Установка различается для каждого мода. Прочитайте описание мода для получения точной информации. Но в основном это:<br />
<br />
# Скачивание XNB мода и распаковка его в любую директорию(но не в директорию с игрой!).<br />
# В нем должны находится несколько <tt>.xnb</tt> файлов.<br />
# Найдите вашу [[Модификации:Директория игры|директорию с игрой]].<br />
# Замена существующих <tt>.xnb</tt> файлов в директории <tt>Content</tt> файлами мода. '''Убедитесь, что вы заменили правильные файлы!''' Существуют разные файлы с одинаковым именем (например, <tt>Content/Data/hats.xnb</tt> и <tt>Content/Characters/hats.xnb</tt>), и замена неправильного файла приведет к ошибкам или сбоям в игре.<br />
<br />
===Удаление модификации===<br />
Удаление заключается в восстановлении оригинальных файлов замененных модом (если они были сохранены заранее), или в [[Modding:Player Guide/Troubleshooting#Reset your content files|повторном скачивании файлов игры]].<br />
<br />
[[Category:Модификации]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_XNB_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B9&diff=5792Модификации:Использование XNB модификаций2018-08-11T14:16:21Z<p>GIDMYRT: Новая страница: «←Index <div style="border: 1px solid red; background: #FCC; padding: 1em;">'''XNB модификации являются устаревши…»</p>
<hr />
<div>←[[Modding:Index|Index]]<br />
<br />
<div style="border: 1px solid red; background: #FCC; padding: 1em;">'''XNB модификации являются устаревшими и не рекомендуются к использованию. SMAPI не может проверить их на совместимость. Используйте XNB модификации на свой страх и риск.'''</div><br />
<br />
Все '''XNB модификации''' заменяют собой <tt>.xnb</tt> файл для внесения изменений в игру.<br />
<br />
==FAQs==<br />
===Что такое XNB мод?===<br />
XNB мод работает посредством замены файлов игры (которые имеют расширение <tt>.xnb</tt>). Например, чтобы изменить [[Абигейл#Портреты|портреты Абигейл]] необходимо заменить файл <tt>Content/Portraits/Abigail.xnb</tt> его модифицированной версией. (Смотрите [[Модификации:Редактирование XNB файлов|редактирование XNB файлов]] для получения информации о формате XNB.)<br />
<br />
===Почему они не рекомендуются?===<br />
XNB моды имеют множество ограничений, часто конфликтуют друг с другом, обычно перестают работать при обновлении игры, а также сложны в установке и удалении.<br />
<br />
Используйте [[Modding:Player Guide|SMAPI моды и content packs]]. Они имеют определенные преимущества над XNB модами:<br />
{| class="wikitable"<br />
|-<br />
! Возможность<br />
! XNB мод<br />
! SMAPI мод<br />
! SMAPI content packs<br />
|-<br />
| Простота установки<br />
| ✘ отличается для каждого мода<br />
|colspan="2"| ✓ добавить в директорию <tt>Mods</tt><br />
|- <br />
| Простота удаления<br />
| ✘ ручное восстановление оригинальных файлов<br />
|colspan="2"| ✓ удалить из директории <tt>Mods</tt><br />
|-<br />
| Проверка обновлений<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ автоматическое оповещение в консоли SMAPI<br />
|-<br />
| Проверка совместимости<br />
| ✘ отсутствует<br />
|colspan="2"| ✓ несовместимые модификации отключаются. <br />✓ [[Modding:SMAPI compatibility|Список совместимых модификаций]] регулярно обновляется и дополняется<br />
|-<br />
| Совместимость модов<br />
| ✘ каждый файл может быть заменен только один раз<br />
| ✓ почти универсальные<br />
| ✓ высокая<br />
|-<br />
| Поддержка переводов<br />
| ✘ сложны в переводе<br />
| ✓ используется специальное API для переводов<br />
| ''(зависит от содержимого content pack)''<br />
|-<br />
| Игровая совместимость<br />
| ✘ часто не работает после обновления игры<br />
|colspan="2"| ✓ SMAPI автоматически перезаписывает многие моды для совместимости<br />✓ моды с открытым исходным кодом обновляются быстро<br />
|}<br />
<br />
===Работают ли они на Linux, Mac, Windows или игровых консолях?===<br />
XNB моды работают одинаково на Linux, Mac, и Windows. Игровые консоли не поддерживаются.<br />
<br />
===Могут ли они повредить сохранения?===<br />
Да, но это редкость. Перед удалением модификации убедитесь, что были сделаны резервные копии [[Сохранения|файлов сохранений]], а также удален пользовательский контент. В некоторых случаях, возможно восстановить файл [[Saves#Undo the last save|возвратом к предыдущему сохранению]].<br />
<br />
===Они отключают достижения Steam?===<br />
Нет.<br />
<br />
<br />
[[Category:Модификации]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5791Модификации:Индекс2018-08-11T11:04:59Z<p>GIDMYRT: </p>
<hr />
<div>{{Stub|'Неполный перевод статьи'}}<br />
'''Модификации''' — это дополнения от сторонних разработчиков, которые изменяют или дополняют оригинальный контент Stardew Valley.<br />
<br />
==Руководства==<br />
{|<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по использованию модификаций|Руководство по использованию модификаций]]'''</big><br />Установка ядра SMAPI, использование модификаций, и решение возможных проблем.<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по созданию модификаций|Руководство по созданию модификаций]]'''</big><br />Создание модификаций, использующих ядро SMAPI. Включает документацию по SMAPI API.<br />
|}<br />
<br />
==Дополнительно==<br />
===Для игроков===<br />
* [[Использование XNB модификаций|Использование XNB модификаций]] (не рекомендуется)<br />
===Для мододелов===<br />
* [[Модификации:Настройка среды разработки|Настройка среды разработки]]<br />
* [[Модификации:Редактирование XNB файлов|Редактирование XNB файлов]]<br />
* [[Модификации:Основные возможности|Основные возможности]]<br />
* [[Модификации:Карты|Создание и редактирование карт]]<br />
* Неигровые персонажы:<br />
** [[Модификации:Диалоги|Диалоги]]<br />
** [[Модификации:События|События]]<br />
** [[Модификации:Подарки|Подарки]]<br />
** [[Модификации:Расписание|Расписание]]<br />
<br />
* Объекты:<br />
** [[Модификации:Big Craftables data|Craftable items]]<br />
** [[Модификации:Crop data|Crops]]<br />
** [[Модификации:Furniture data|Furniture]]<br />
** [[Модификации:Hat data|Hats]]<br />
** [[Модификации:Object data|Objects]]<br />
<br />
* Другое:<br />
** [[Модификации:Achievement data|Achievements]]<br />
** [[Модификации:Blueprint data|Blueprints]]<br />
** [[Модификации:Debug commands|Debug commands]]<br />
** [[Модификации:Fish data|Fish]]<br />
** [[Модификации:Weather data|Weather]]<br />
<br />
===Руководства по переходу на новые версии===<br />
* [[Модификации:Переход на SMAPI 2.0|Переход на SMAPI 2.0]] (Октябрь 2017)<br />
* [[Модификации:Переход на Stardew Valley 1.3|Переход на Stardew Valley 1.3]] (Май 2018)<br />
* [[Модификации:Изменения XNB в Stardew Valley 1.3|Изменения XNB в Stardew Valley 1.3]] (Май 2018)<br />
<br />
===Смотрите также===<br />
* [[Модификации:Сообщество#Discord|Чат в Discord]] — получение помощи, общение с мододелами и разработчиками SMAPI.<br />
<br />
[[File:SMAPI mascot.png|20px]]<br />
<br />
[[Category:Модификации]]<br />
<br />
[[en:Modding:Index]]<br />
[[es:Mods]]<br />
[[pt:Modificações:Índice]]<br />
[[zh:使用模组:目录]]</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5790Модификации:Индекс2018-08-11T11:04:30Z<p>GIDMYRT: </p>
<hr />
<div>{{Stub|'Неполный перевод статьи'}}<br />
'''Модификации''' — это дополнения от сторонних разработчиков, которые изменяют или дополняют оригинальный контент Stardew Valley.<br />
<br />
==Руководства==<br />
{|<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по использованию модификаций|Руководство по использованию модификаций]]'''</big><br />Установка ядра SMAPI, использование модификаций, и решение возможных проблем.<br />
|-<br />
|style="border: 2px solid rgb(0, 116, 72); background: rgba(3, 160, 7, 0.1); padding: 1em;"| <big>'''[[Руководство по созданию модификаций|Руководство по созданию модификаций]]'''</big><br />Создание модификаций, использующих ядро SMAPI. Включает документацию по SMAPI API.<br />
|}<br />
<br />
==Дополнительно==<br />
===Для игроков===<br />
* [[Использование XNB модификаций|Использование XNB модификаций]] (не рекомендуется)</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8:%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81&diff=5789Модификации:Индекс2018-08-11T11:03:30Z<p>GIDMYRT: Новая страница: «{{Stub}}»</p>
<hr />
<div>{{Stub}}</div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD:Stub&diff=5788Шаблон:Stub2018-08-11T10:04:08Z<p>GIDMYRT: </p>
<hr />
<div><includeonly>{| class="alert" id="stub"<br />
|-<br />
! [[File:Axe.png|center]]<br />
| <span class="header">Это заготовка статьи.</span><br />
<br />
{{#if: {{{1|}}}|Статья помечена как незавершенная по следующим причинам:<br />
*''{{{1}}}''|Вы можете помочь {{SITENAME}}, ''[{{fullurl:{{FULLPAGENAME}}|action=edit}} дополнив её!]''}}<br />
|}[[Category:Заготовки]]</includeonly><noinclude>{{englishdoc}}</noinclude></div>GIDMYRThttps://ru.stardewvalleywiki.com/mediawiki/index.php?title=%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD:Stub&diff=5787Шаблон:Stub2018-08-11T10:00:11Z<p>GIDMYRT: </p>
<hr />
<div><includeonly>{| class="alert" id="stub"<br />
|-<br />
! [[File:Axe.png|center]]<br />
| <span class="header">Это заготовка статьи.</span><br />
<br />
{{#if: {{{1|}}}|Статья помечена как незавершенная по следующим причинам:<br />
*''{{{1}}}''|Эта статья является заготовкой и содержит неполную информацию. Вы можете помочь {{SITENAME}}, ''[{{fullurl:{{FULLPAGENAME}}|action=edit}} дополнив её!]''}}<br />
|}[[Category:Заготовки]]</includeonly><noinclude>{{englishdoc}}</noinclude></div>GIDMYRT