Модификации:Основные возможности: различия между версиями

Материал из Stardew Valley Wiki
Перейти к навигации Перейти к поиску
м
(Выполнен основной перевод статьи)
Строка 1: Строка 1:
 
← [[Модификации]]
 
← [[Модификации]]
{{Переведите}}
 
  
 
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''
 
В этой статье описываются основные возможности SMAPI. '''Перед прочтением данной статьи, рекомендуется прочитать [[Modding:Modder Guide|Modder Guide]] и [[Modding:Modder Guide/Game Fundamentals|Game Fundamentals]].'''
Строка 6: Строка 5:
 
==Основы==
 
==Основы==
 
===Отслеживание изменений переменной===
 
===Отслеживание изменений переменной===
Модам часто приходится отслеживать изменение какого-либо значения. Если для значения в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле] для отслеживания значения, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:
+
Модам часто приходится отслеживать изменение какого-либо значения. Если для параметра в SMAPI нет события, можно создать [https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/fields приватное поле], и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:
  
 
<source lang="c#">
 
<source lang="c#">
Строка 64: Строка 63:
  
 
==Предметы==  
 
==Предметы==  
Предметы - это объекты, которые могут быть помещены в инвентарь. Инструменты, культуры и т.п.
+
Предметы - это объекты, которые могут быть помещены в инвентарь. Предметами являются инструменты, семена, урожай и т.п.
  
 
===Создание предмета (Объекта)===
 
===Создание предмета (Объекта)===
Строка 78: Строка 77:
 
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).
 
Где '''parentSheetIndex''' это ID предмета (может быть найдено в ObjectInformation.xnb).
  
===Создание предмета на поверхности===
+
===Создание предмета на клетке===
  
 
<source lang='c#'>
 
<source lang='c#'>
Строка 99: Строка 98:
 
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)
 
''Игровой локацией'' является любое место в игре (Ферма, Город, Шахта)
  
''Game1.currentLocation'' является ссылкой на локацию в которой находится игрок.
+
''Game1.currentLocation'' является ссылкой на текущую локацию в которой находится игрок.
  
 
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.
 
'''Важное предупреждение''': Начиная с версии 1.3 ''Game1.currentLocation'' использовать в мультиплеере не рекомендуется.
  
 
===Свойства карты===
 
===Свойства карты===
Многие свойства карты, а также тайлов на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]
+
Многие свойства карты, а также клеток на ней можно изменить. Для детальной информации читайте [[Модификации:Карты#Свойства карты|свойства карты]]
  
===Обработка тайлов===
+
===Обработка клетки===
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора тайлов (земля, трава, грядка).  
+
Поле ''.terrainFeatures'' содержит свойство .Pairs, которое используется для получения доступа к элементу набора клеток (земля, трава, грядка).  
  
Ниже приведен фрагмент для обработки тайла с [[Культуры|культурой]]:
+
Ниже приведен фрагмент для обработки клетки с [[Культуры|культурой]]:
 
<source lang="c#">
 
<source lang="c#">
  
Строка 123: Строка 122:
 
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!
 
Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!
  
===Обработка объектов на тайле===
+
===Обработка объектов на клетке===
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах на тайле (семена, камень, древесина).
+
Для обработки объектов есть несколько полей, но чаще всего используется ''.objects''. В нем содержится информация об объектах (семена, камень, древесина).
  
 
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.
 
Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.
  
 
==Игрок==
 
==Игрок==
//добавить описание
+
 
 
===Местоположение===
 
===Местоположение===
 
Позиция персонажа указывает координаты персонажа в текущей локации.
 
Позиция персонажа указывает координаты персонажа в текущей локации.
====Позиция игрока на карте====
 
Каждая локация представлена ``xTile`` картой, где левых верхний угол имеет координаты ''(0, 0)'' пикселей, а правый нижний - ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' пикселей.
 
  
There are two ways to get a Character's position in the current location: by absolute position and by tile position.
+
====Позиция игрока в локации====
Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам тайла.
+
Каждая локация представлена ''xTile'' картой, где левый верхний угол имеет координаты ''(0, 0)'', а правый нижний - ''(location.Map.DisplayWidth, location.Map.DisplayHeight)'' пикселей.
 +
 
 +
Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам клетки.
  
 
<code>Position.X</code> и <code>Position.Y</code> вернут координаты XY в пикселях.
 
<code>Position.X</code> и <code>Position.Y</code> вернут координаты XY в пикселях.
  
<code>getTileX()</code> и <code>getTileY()</code> вернут координаты XY тайла в сетке тайл-листа.
+
<code>getTileX()</code> и <code>getTileY()</code> вернут координаты XY клетки в сетке тайл-листа.
  
Согласно <code>Game1.tileSize</code> тайл имеет размер 64x64  пикселей. Это дает возможность конвертировать абсолютную и относительную позиции:
+
Согласно <code>Game1.tileSize</code> клетка имеет размер 64x64  пикселей, что дает возможность конвертировать абсолютную и относительную позиции:
  
 
<source lang='c#'>
 
<source lang='c#'>
// Абсолютная позиция => Позиция тайла
+
// Абсолютная позиция => Позиция клетки
 
Math.Floor(Game1.player.Position.X / Game1.tileSize)
 
Math.Floor(Game1.player.Position.X / Game1.tileSize)
 
Math.Floor(Game1.player.Position.Y / Game1.tileSize)
 
Math.Floor(Game1.player.Position.Y / Game1.tileSize)
  
// Позиция тайла => Абсолютная позиция
+
// Позиция клетки => Абсолютная позиция
 
Game1.player.getTileX() * Game1.tileSize
 
Game1.player.getTileX() * Game1.tileSize
 
Game1.player.getTileY() * Game1.tileSize
 
Game1.player.getTileY() * Game1.tileSize
  
// Размеры тайла
+
// Размеры клетки
 
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)
 
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)
 
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)
 
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)
Строка 169: Строка 168:
 
</source>
 
</source>
  
==NPC==
+
==Неигровые персонажи==
===Creating Custom NPCs===
+
===Создание пользовательского НИПа===
Adding new NPCs involves editing a number of files:
+
Добавление нового НИПа включает в себя редактирование нескольких файлов:
  
* New file: Characters\Dialogue\<name>
+
* Создание файла: Characters\Dialogue\<имя>
* New file: Characters\schedules\<name>
+
* Создание файла: Characters\schedules\<имя>
* New file: Portraits\<name>
+
* Создание файла: Portraits\<имя>
* New file: Characters\<name>
+
* Создание файла: Characters\<имя>
* Add entries Data\EngagementDialogue for NPCs that are marriable
+
* Добавление записей Data\EngagementDialogue для НИПов, с которыми можно заключить брак
* Add entry to Data\NPCDispositions
+
* Добавление записи в Data\NPCDispositions
* Add entry to Data\NPCGiftTastes
+
* Добавление записи в Data\NPCGiftTastes
* Add entries to Characters\Dialogue\rainy
+
* Добавление записей в Characters\Dialogue\rainy
* Add entries to Data\animationDescriptions (if you want custom animations in their schedule)
+
* Добавление записей в Data\animationDescriptions (если нужны пользовательские анимации в расписании)
  
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:
+
Все это можно сделать с помощью IAssetLoaders/IAssetEditors или Content Patcher. В завершении, создается НИП, используя конструкторы SMAPI:
  
 
<source lang='c#'>
 
<source lang='c#'>
Строка 191: Строка 190:
 
</source>
 
</source>
  
For spawning:
+
Для спавна:
  
 
<source lang='c#'>
 
<source lang='c#'>
Строка 197: Строка 196:
 
</source>
 
</source>
  
==UI==
+
==Пользовательский интерфейс==
  
The UI is a collection of separate elements which make up the HUD and occasional popups.
+
Пользовательский интерфейс представляет собой набор отдельных элементов, которые составляют [https://ru.wikipedia.org/wiki/Head-Up_Display_(игры) HUD] и всплывающие окна.
  
//todo expand section.
+
//необходимо дополнить раздел.
  
  
===Banner Message===
+
===Всплывающие сообщения===
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):
+
HUDMessage - это всплывающие сообщения в нижнем левом углу экрана. У них есть несколько конструкторов, которые указаны ниже (несколько не релевантных были пропущены):
  
 
<source lang="c#">
 
<source lang="c#">
Строка 216: Строка 215:
  
  
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)
+
Ниже даны описания основных аргументов, которые требуются для создания сообщения. (Для полного описания рекомендуется читать информацию о классе, но в большинстве ситуации информации ниже достаточно)
 
 
  
 
WhatType:
 
WhatType:
*1 - Achievement
+
*1 - Достижение
*2 - New Quest
+
*2 - Новый квест
*3 - Error
+
*3 - Ошибка
*4 - Stamina
+
*4 - Выносливость
*5 - Health
+
*5 - Здоровье
 
 
  
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.
 
  
 +
Color:  Цвет. В первых двух конструкторах используется цвет по умолчанию (''Color:OrangeRed''), а в четвертом - параметр 'leaveMeNull' отображается тем же цветом, что и текст игры.
  
For specifics:
 
*'' 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.
 
*''  public HUDMessage(string message, string leaveMeNull)'' - Also displays no icon.
 
*''  public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Displays a message that fades in for a set amount of time.
 
  
 +
Для примера:
 +
*'' public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);'' - Подходит для кастомизации сообщения. Чаще всего используется для денег.
 +
*'' public HUDMessage(string message, string leaveMeNull)'' - Сообщение без иконки.
 +
*'' public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)'' - Выводит сообщение, которое исчезает в течении установленного времени.
  
Note: For those of you who want a custom HUDMessage:
 
- Almost all of these variables are public, excluding messageSubject, so feel free to customize!
 
  
 +
Примечание:
 +
- Все переменные являются публичными, кроме messageSubject, поэтому не стесняйтесь кастомизировать!
  
  
For example: add a new HUDMessage to show [insert image] toaster popup.
+
Пример: Всплывающее сообщение об [[Файл:error-image-ingame.png]] ошибке:
 
<source lang="c#">
 
<source lang="c#">
 
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));
 
Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));
 
</source>
 
</source>
  
==Menus==
+
==МЕню==
//todo describe section
+
//добавить описание раздела
===Get the Active Menu===
+
 
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.
+
===Получение информации о активной вкладки меню===
 +
Используйте ''Reflection'', чтобы узнать какая вкладка ''GameMenu'' сейчас активна. ''GameMenu'' содержит вкладки Инвентарь, Навыки, Светское, Карта, Изготовление предметов, Коллекции, и Настройки в указанном порядке. То есть вкладка ''inventoryTab'' имеет индекс 0.
  
 
<source lang="c#">
 
<source lang="c#">
Строка 256: Строка 254:
 
   IClickableMenu page = pages[menu.currentTab];
 
   IClickableMenu page = pages[menu.currentTab];
  
   // Example for getting the MapPage
+
   // Получение вкладки Карта
 
   MapPage mapPage = (MapPage) pages[menu.currentTab];
 
   MapPage mapPage = (MapPage) pages[menu.currentTab];
  
   // Two examples of checking if MapPage is open
+
   // Два примера проверки, что вкладка Карта открыта
 
   pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;
 
   pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;
 
}
 
}
 
</source>
 
</source>
  
===Set the Active Menu===
+
===Установка активной вкладки меню===
 
Game1.activeClickableMenu = <Menu>
 
Game1.activeClickableMenu = <Menu>
===Simple Menu===
 
Copy the menu you want from the game and make it your own
 
  
 
==Harmony==
 
==Harmony==
 
{{quote|Here be dragons. Thou art forewarned.}}
 
{{quote|Here be dragons. Thou art forewarned.}}
  
[https://github.com/pardeike/Harmony Harmony] lets you patch Stardew Valley methods directly. This is very powerful, but comes with major caveats:
+
[https://github.com/pardeike/Harmony Harmony] позволяет напрямую использовать методы игры. Это очень мощный инструмент, но есть серьезные оговорки:
  
* It's very easy to cause crashes, errors, or subtle bugs.
+
* Очень легко вызвать сбои, ошибки или неотлавливаемые баги.
* It may cause difficult-to-diagnose memory corruption errors.
+
* Это может привести к затруднению диагностики ошибок повреждения памяти.
* Crossplatform compatibility is not guaranteed, and should be tested on all three platforms.
+
* Кроссплатформенная совместимость не гарантируется и должна быть протестирована на всех трех платформах.
* 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).
+
* Может конфликтовать с другими модами Harmony (например, если два мода используют один и тот же метод, или два мода пытаются загрузить разные версии Harmony).
* Harmony patch errors may have unpredictable effects on other mods that aren't using Harmony.
+
* Патчи Harmony могут иметь непредсказуемые эффекты для других модов, которые не используют Harmony.
  
Using Harmony should be a last resort, and is deliberately not documented.
+
Использование Harmony должно быть последним средством, и поэтому намеренно не документировано.
  
==Other==
+
==Другое==
===Add a small animation===
+
===Добавление небольшой анимации===
 
<source lang="c#">
 
<source lang="c#">
 
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))
 
location.temporarySprites.Add(new TemporaryAnimatedSprite(...))
 
</source>
 
</source>
See ''TemporaryAnimatedSprite'' for more details
+
Смотрите ''TemporaryAnimatedSprite'' для детальной информации
  
===Play a sound===
+
===Воспроизведение звука===
 
<source lang="c#">
 
<source lang="c#">
 
location.playSound("SOUND");  
 
location.playSound("SOUND");  
Строка 295: Строка 291:
 
(e.g. "junimoMeep1")
 
(e.g. "junimoMeep1")
  
===Send a letter===
+
===Отправка письма===
  
Use IAssetEditor to inject new mail into Data\Mail.xnb. Then use Game1.addMailForTomorrow to send it to the player.
+
Используйте IAssetEditor, чтобы добавить новое письмо в Data\Mail.xnb. Затем вызывайте метод Game1.addMailForTomorrow, чтобы отправить его игроку.
  
 
<source lang="c#">
 
<source lang="c#">
Строка 303: Строка 299:
 
</source>
 
</source>
  
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.
+
Где mailName ключ в Mail.xnb. Если использовать строку '''wizard''' где угодно в ключе, то письмо будет иметь волшебный фон[?] (начиная с 1.3) автоматически.
 
 
==Open source==
 
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.
 
  
[[Category:Modding]]
+
==Исходные коды==
 +
Если что-то не получается, в большинстве случаев есть возможность подсмотреть реализацию в исходном коде другого мода. Смотрите столбец 'Исходный коды' в [[Modding:SMAPI compatibility|списке совместимых модификаций]].
 +
[[Category:Модификации]]
  
 
[[en:Modding:Common tasks]]
 
[[en:Modding:Common tasks]]

Версия 10:06, 14 августа 2018

Модификации

В этой статье описываются основные возможности SMAPI. Перед прочтением данной статьи, рекомендуется прочитать Modder Guide и Game Fundamentals.

Основы

Отслеживание изменений переменной

Модам часто приходится отслеживать изменение какого-либо значения. Если для параметра в SMAPI нет события, можно создать приватное поле, и обновлять его, используя событие обновления. Например, вот полностью работающий мод, который выводит сообщение в консоль, когда выносливость игрока изменяется:

/// <summary>Входная точка мода.</summary>
internal class ModEntry : Mod
{
    /*********
    ** Свойства
    *********/
    /// <summary>Последнее значение выносливости игрока.</summary>
    private float LastStamina;


    /*********
    ** Публичные методы
    *********/
    /// <summary>При первой загрузке мода вызывается метод Entry</summary>
    /// <param name="helper">Provides simplified APIs for writing mods.</param>
    public override void Entry(IModHelper helper)
    {
        SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
        GameEvents.UpdateTick += this.GameEvents_UpdateTick;
    }


    /*********
    ** Приватные методы
    *********/
    /// <summary>Метод вызываемый при загрузке сохранения.</summary>
    /// <param name="sender">The event sender.</param>
    /// <param name="e">The event arguments.</param>
    private void SaveEvents_AfterLoad(object sender, EventArgs e)
    {
        this.LastStamina = Game1.player.Stamina;
    }

    /// <summary>Метод вызывается после события обновления (около 60 раз в секунду).</summary>
    /// <param name="sender">The event sender.</param>
    /// <param name="e">The event arguments.</param>
    private void GameEvents_UpdateTick(object sender, EventArgs e)
    {
        // выходим, если сохранение еще не загружено
        if (!Context.IsWorldReady)
            return;

        // выходим, если значение выносливости не изменилось
        float currentStamina = Game1.player.Stamina;
        if (currentStamina == this.LastStamina)
            return;

        // выводим сообщение и обновляем значение свойства LastStamina 
        this.Monitor.Log($"Player stamina changed from {currentStamina} to {this.LastStamina}");
        this.LastStamina = currentStamina;
    }
}

Предметы

Предметы - это объекты, которые могут быть помещены в инвентарь. Предметами являются инструменты, семена, урожай и т.п.

Создание предмета (Объекта)

Конструкторы класса для создания предмета:

 public Object(Vector2 tileLocation, int parentSheetIndex, int initialStack);
 public Object(Vector2 tileLocation, int parentSheetIndex, bool isRecipe = false);
 public Object(int parentSheetIndex, int initialStack, bool isRecipe = false, int price = -1, int quality = 0);
 public Object(Vector2 tileLocation, int parentSheetIndex, string Givenname, bool canBeSetDown, bool canBeGrabbed, bool isHoedirt, bool isSpawnedObject);

Где parentSheetIndex это ID предмета (может быть найдено в ObjectInformation.xnb).

Создание предмета на клетке

 public virtual bool dropObject(Object obj, Vector2 dropLocation, xTile.Dimensions.Rectangle viewport, bool initialPlacement, Farmer who = null);

 // Спавн предмета в локации:
 Game1.getLocationFromName("Farm").dropObject(new StardewValley.Object(itemId, 1, false, -1, 0), new Vector2(x, y) * 64f, Game1.viewport, true, (Farmer)null);

Добавление предмета в инвентарь

//todo

Удаление предмета из инвентаря

Удаление зависит от инвентаря. Чаще всего вызывается метод класса Player, расположенного в пространстве имен Farmer.

Чтобы удалить предмет в большинстве ситуаций необходимо просто вызвать метод .removeItemFromInventory(Item)

Локации

Игровой локацией является любое место в игре (Ферма, Город, Шахта)

Game1.currentLocation является ссылкой на текущую локацию в которой находится игрок.

Важное предупреждение: Начиная с версии 1.3 Game1.currentLocation использовать в мультиплеере не рекомендуется.

Свойства карты

Многие свойства карты, а также клеток на ней можно изменить. Для детальной информации читайте свойства карты

Обработка клетки

Поле .terrainFeatures содержит свойство .Pairs, которое используется для получения доступа к элементу набора клеток (земля, трава, грядка).

Ниже приведен фрагмент для обработки клетки с культурой:

foreach (var tf in Game1.getFarm().terrainFeatures.Pairs)
{
    if ((tf.Value is HoeDirt hd) && hd.crop != null)
    {
        // do crop like things here.
    }
}

Для указания другой локации необходимо заменить Game1.getFarm(). Обратите внимание: в примере не производится проверка локации на существование (null check)!

Обработка объектов на клетке

Для обработки объектов есть несколько полей, но чаще всего используется .objects. В нем содержится информация об объектах (семена, камень, древесина).

Действия аналогичны TerrainFeatures, за исключением того, что нельзя размещать объекты за пределами карты.

Игрок

Местоположение

Позиция персонажа указывает координаты персонажа в текущей локации.

Позиция игрока в локации

Каждая локация представлена xTile картой, где левый верхний угол имеет координаты (0, 0), а правый нижний - (location.Map.DisplayWidth, location.Map.DisplayHeight) пикселей.

Существуют два способа узнать текущее местоположение персонажа в локации: по абсолютной позиции или по координатам клетки.

Position.X и Position.Y вернут координаты XY в пикселях.

getTileX() и getTileY() вернут координаты XY клетки в сетке тайл-листа.

Согласно Game1.tileSize клетка имеет размер 64x64 пикселей, что дает возможность конвертировать абсолютную и относительную позиции:

// Абсолютная позиция => Позиция клетки
Math.Floor(Game1.player.Position.X / Game1.tileSize)
Math.Floor(Game1.player.Position.Y / Game1.tileSize)

// Позиция клетки => Абсолютная позиция
Game1.player.getTileX() * Game1.tileSize
Game1.player.getTileY() * Game1.tileSize

// Размеры клетки
Math.Floor(Game1.player.currentLocation.Map.DisplayWidth / Game1.tileSize)
Math.Floor(Game1.player.currentLocation.Map.DisplayHeight / Game1.tileSize)

Позиция игрока в видимой области

Размеры видимой области экрана можно узнать используя Game1.viewport.Width и Game1.viewport.Height. Размеры указаны в пикселях и соответствуют разрешению экрана игры.

Также видимая область имеет абсолютную позицию относительно карты, где левый верхний угол находится в (Game1.viewport.X, Game1.viewport.Y).

Позиция игрока относительно видимой области вычисляется следующим образом:

Game1.player.Position.X - Game1.viewport.X
Game1.player.Position.Y - Game1.viewport.Y

Неигровые персонажи

Создание пользовательского НИПа

Добавление нового НИПа включает в себя редактирование нескольких файлов:

  • Создание файла: Characters\Dialogue\<имя>
  • Создание файла: Characters\schedules\<имя>
  • Создание файла: Portraits\<имя>
  • Создание файла: Characters\<имя>
  • Добавление записей Data\EngagementDialogue для НИПов, с которыми можно заключить брак
  • Добавление записи в Data\NPCDispositions
  • Добавление записи в Data\NPCGiftTastes
  • Добавление записей в Characters\Dialogue\rainy
  • Добавление записей в Data\animationDescriptions (если нужны пользовательские анимации в расписании)

Все это можно сделать с помощью IAssetLoaders/IAssetEditors или Content Patcher. В завершении, создается НИП, используя конструкторы SMAPI:

 public NPC(AnimatedSprite sprite, Vector2 position, int facingDir, string name, LocalizedContentManager content = null);
 public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDir, string name, Dictionary<int, int[]> schedule, Texture2D portrait, bool eventActor);
 public NPC(AnimatedSprite sprite, Vector2 position, string defaultMap, int facingDirection, string name, bool datable, Dictionary<int, int[]> schedule, Texture2D portrait);

Для спавна:

 Game1.getLocationFromName("Town").addCharacter(npc);

Пользовательский интерфейс

Пользовательский интерфейс представляет собой набор отдельных элементов, которые составляют HUD и всплывающие окна.

//необходимо дополнить раздел.


Всплывающие сообщения

HUDMessage - это всплывающие сообщения в нижнем левом углу экрана. У них есть несколько конструкторов, которые указаны ниже (несколько не релевантных были пропущены):

  public HUDMessage(string message);
  public HUDMessage(string message, int whatType);
  public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null);
  public HUDMessage(string message, string leaveMeNull)
  public HUDMessage(string message, Color color, float timeLeft, bool fadeIn)


Ниже даны описания основных аргументов, которые требуются для создания сообщения. (Для полного описания рекомендуется читать информацию о классе, но в большинстве ситуации информации ниже достаточно)

WhatType:

  • 1 - Достижение
  • 2 - Новый квест
  • 3 - Ошибка
  • 4 - Выносливость
  • 5 - Здоровье


Color: Цвет. В первых двух конструкторах используется цвет по умолчанию (Color:OrangeRed), а в четвертом - параметр 'leaveMeNull' отображается тем же цветом, что и текст игры.


Для примера:

  • public HUDMessage(string type, int number, bool add, Color color, Item messageSubject = null); - Подходит для кастомизации сообщения. Чаще всего используется для денег.
  • public HUDMessage(string message, string leaveMeNull) - Сообщение без иконки.
  • public HUDMessage(string message, Color color, float timeLeft, bool fadeIn) - Выводит сообщение, которое исчезает в течении установленного времени.


Примечание: - Все переменные являются публичными, кроме messageSubject, поэтому не стесняйтесь кастомизировать!


Пример: Всплывающее сообщение об Error-image-ingame.png ошибке:

Game1.addHUDMessage(new HUDMessage("MESSAGE", 3));

МЕню

//добавить описание раздела

Получение информации о активной вкладки меню

Используйте Reflection, чтобы узнать какая вкладка GameMenu сейчас активна. GameMenu содержит вкладки Инвентарь, Навыки, Светское, Карта, Изготовление предметов, Коллекции, и Настройки в указанном порядке. То есть вкладка inventoryTab имеет индекс 0.

if (Game1.activeClickableMenu is GameMenu menu) {
  IList<IClickableMenu> pages = this.Helper.Reflection.GetField<List<IClickableMenu>>(menu, "pages").GetValue();
  IClickableMenu page = pages[menu.currentTab];

  // Получение вкладки Карта
  MapPage mapPage = (MapPage) pages[menu.currentTab];

  // Два примера проверки, что вкладка Карта открыта
  pages[menu.currentTab] is MapPage || menu.currentTab == GameMenu.mapTab;
}

Установка активной вкладки меню

Game1.activeClickableMenu = <Menu>

Harmony

“Here be dragons. Thou art forewarned.”

Harmony позволяет напрямую использовать методы игры. Это очень мощный инструмент, но есть серьезные оговорки:

  • Очень легко вызвать сбои, ошибки или неотлавливаемые баги.
  • Это может привести к затруднению диагностики ошибок повреждения памяти.
  • Кроссплатформенная совместимость не гарантируется и должна быть протестирована на всех трех платформах.
  • Может конфликтовать с другими модами Harmony (например, если два мода используют один и тот же метод, или два мода пытаются загрузить разные версии Harmony).
  • Патчи Harmony могут иметь непредсказуемые эффекты для других модов, которые не используют Harmony.

Использование Harmony должно быть последним средством, и поэтому намеренно не документировано.

Другое

Добавление небольшой анимации

location.temporarySprites.Add(new TemporaryAnimatedSprite(...))

Смотрите TemporaryAnimatedSprite для детальной информации

Воспроизведение звука

location.playSound("SOUND");

(e.g. "junimoMeep1")

Отправка письма

Используйте IAssetEditor, чтобы добавить новое письмо в Data\Mail.xnb. Затем вызывайте метод Game1.addMailForTomorrow, чтобы отправить его игроку.

 public static void addMailForTomorrow(string mailName, bool noLetter = false, bool sendToEveryone = false);

Где mailName ключ в Mail.xnb. Если использовать строку wizard где угодно в ключе, то письмо будет иметь волшебный фон[?] (начиная с 1.3) автоматически.

Исходные коды

Если что-то не получается, в большинстве случаев есть возможность подсмотреть реализацию в исходном коде другого мода. Смотрите столбец 'Исходный коды' в списке совместимых модификаций.