- Версия(и) Minecraft
- 1.7.10
Доброго времени суток! о/
В этом туториале я расскажу вам как создать собственный эффект, а также добавить предмет для использования этого зелья.
Расширение слотов:
Для начала, нам лучше бы расширить кол-во ванильных слотов под зелья, так как изначально их всего 32. Если вы уверены, что в сборке с вашим модом больше не будет зелий или наоборот, стоят такие моды как таумкрафт или ботания (вы делаете к ним аддон) - смело пропускайте этот шаг.
Добавьте вызов этого метода в ваш preInit чтобы убедиться, что слотов хватит:
Итак, когда мы убедились, что у нас точно не возникнет
Создание и регистрация эффекта:
Мы будем делать зелье полёта, позволяющее нам летать как в креативе.
В классе регистрации вашего мода объявите новую переменную:
В preInit методе (после проверки, если она у вас есть) присвоим зелью экземпляр собственного класса зелья:
У вас высветится ошибка, но пока что игнорируйте её.
Давайте для начала создадим базовый класс для всех наших зелий:
Немного про иконки:
Мне никогда не нравилась эта система индексирования, но вкратце, у вас есть[неограниченное] поле размером 256x256, в котором вы можете размещать иконки зелий 18x18 в строгом порядке, после чего майнкрафт сам будет получать нужную область картинки. Верхняя левая картинка - 0, правее - 1, ещё правее - 2 и так далее. Ряд состоит из 8 картинок, после чего происходит смещение вниз. "Шаблон" такого поля можно найти в папке с текстурами по пути
Если для вас это слишком сложно, используйте метод
Продолжаем:
А теперь исправляем ошибку выше и создаём класс нашего зелья PotionFlight:
Готово! Ваше зелье создано, зарегистрировано и может быть наложено. Но пока что оно ничего не делает. Время добавить функционал!
Добавление функционала:
Для этого изменим наш класс PotionFlight таким образом:
Есть второй способ добавления функционала на случай если вам не нужна особо гибкая обработка, как в этом примере.
Кода тут побольше, зато нагрузка на сервер меньше, так что лучше использовать эти методы, а там как вам удобнее.
Отлично! Теперь, если игрок будет под эффектом нашего зелья он сможет летать.
Эффект готов, а это значит что пора обеспечить возможность его получение в самой игре!
Накладывание на игрока:
Думаю, как создавать и регистрировать предметы рассказывать смысла нет, поэтому вкратце расскажу как сделать предмет, дающий эффект зелья при выпивании:
Вот и всё! Осталось дропнуть этот предмет с какого-нибудь босса, и когда игрок его выпьет - получит креативный полёт на 10 секунд.
Всем спасибо за внимание!
В этом туториале я расскажу вам как создать собственный эффект, а также добавить предмет для использования этого зелья.
Расширение слотов:
Для начала, нам лучше бы расширить кол-во ванильных слотов под зелья, так как изначально их всего 32. Если вы уверены, что в сборке с вашим модом больше не будет зелий или наоборот, стоят такие моды как таумкрафт или ботания (вы делаете к ним аддон) - смело пропускайте этот шаг.
Java:
// Код взят у Vazkii и слегка переделан
static void extendPotionArray() {
Potion[] potionTypes = null;
for (Field f : Potion.class.getDeclaredFields()) { // получаем все поля из класса зелья
f.setAccessible(true); // даём к ним доступ (локально убираем private)
try {
if (f.getName().equals("potionTypes") || f.getName().equals("field_76425_a")) { // проверка что это поле именно со списком зелий
Field modfield = Field.class.getDeclaredField("modifiers");
modfield.setAccessible(true);
modfield.setInt(f, f.getModifiers() & ~Modifier.FINAL); // убираем final модфикатор
potionTypes = (Potion[])f.get(null);
final Potion[] newPotionTypes = new Potion[256]; // создаём новый массив зелий на 256 элементов
System.arraycopy(potionTypes, 0, newPotionTypes, 0, potionTypes.length); // копируем старые зелья в новый массив
f.set(null, newPotionTypes); // и заменяем
return;
}
} catch (Exception e) {
System.err.println(e); // на случай ошибки выводим её в лог
}
}
}
if(Potion.potionTypes.length < 256) extendPotionArray();
Итак, когда мы убедились, что у нас точно не возникнет
ArrayIndexOutOfBoundsException
, можно приступать к созданию самого зелья.Создание и регистрация эффекта:
Мы будем делать зелье полёта, позволяющее нам летать как в креативе.
В классе регистрации вашего мода объявите новую переменную:
public static Potion flight;
В preInit методе (после проверки, если она у вас есть) присвоим зелью экземпляр собственного класса зелья:
possession = new PotionFlight();
У вас высветится ошибка, но пока что игнорируйте её.
Давайте для начала создадим базовый класс для всех наших зелий:
Java:
public class PotionMod extends Potion {
// это файл с текстурами наших иконок
private static final ResourceLocation icons = new ResourceLocation(ModID, "path/to/your/icons.png");
// конструктор зелья: ID в массиве зелий, его название, хороший эффект или плохой, цвет партиклов и индекс иконки
public PotionMod(int id, String name, boolean badEffect, int color, int iconIndex) {
super(id, badEffect, color);
setPotionName("potion." + name);
setIconIndex(iconIndex % 8, iconIndex / 8);
}
/* *
* Функция получения иконки зелья для инвентаря. В ней мы привязываем нашу текстуру
* Небольшой лайфхак, можно было бы использовать renderInventoryEffect, но по мне этот вариант проще
*/
@Override
@SideOnly(Side.CLIENT)
public int getStatusIconIndex() {
Minecraft.getMinecraft().renderEngine.bindTexture(resource);
return super.getStatusIconIndex();
}
}
Немного про иконки:
Мне никогда не нравилась эта система индексирования, но вкратце, у вас есть
\assets\minecraft\textures\gui\container\inventory.png
Если для вас это слишком сложно, используйте метод
renderInventoryEffect
, предоставляемый форджем.Продолжаем:
А теперь исправляем ошибку выше и создаём класс нашего зелья PotionFlight:
Java:
public class PotionFlight extends PotionMod {
public PotionFlight() {
// Совет: вынесите ID в конфиг, чтобы при случае его можно было поменять
super(40, "flight", false, 0xFFFFEE, 2);
}
}
Добавление функционала:
Для этого изменим наш класс PotionFlight таким образом:
Java:
public class PotionFlight extends PotionMod {
public PotionFlight() {
super(40, "flight", false, 0xFFFFEE, 2);
// Регистрируем этот класс обработчиком событий чтобы можно было управлять поведением зелья
MinecraftForge.EVENT_BUS.register(this);
}
// Добавляем эвент обновления живого существва
// Здесь мы проверяем, что обновился игрок и что у него есть наше зелье
// В случае когда время ещё есть даём креативный полёт, иначе забираем и чистим эффект зелья
@SubscribeEvent
public void onEntityUpdate(LivingUpdateEvent e) {
if (e.entityLiving instanceof EntityPlayer) {
if (e.entityLiving.getActivePotionEffect(this) != null && e.entityLiving.getActivePotionEffect(this).getDuration() > 0) {
((EntityPlayer) e.entityLiving).capabilities.allowFlying =
((EntityPlayer) e.entityLiving).capabilities.isFlying = true;
} else {
((EntityPlayer) e.entityLiving).capabilities.allowFlying =
((EntityPlayer) e.entityLiving).capabilities.isFlying = false;
}
}
}
}
Есть второй способ добавления функционала на случай если вам не нужна особо гибкая обработка, как в этом примере.
isReady
- метод, который вызывается каждый тик, служит для проверки можно ли применить эффект в данный момент (например, для применения раз в 10 тиков). Параметры - время действия и модификатор уровня.performEffect
- вызывается каждый тик, но только еслиisReady
вернул до этогоtrue
. Служит для выполнения действий (например, для лечения). Параметры - сущность под эффектом и модификатор.isInstant
- мгновенный ли этот эффект (вроде моментального лечения).affectEntity
- обычно вызывается единожды для применения мгновенного эффекта. Параметры - тот кто применил зелье, тот на кого его применили, модификатор и коэффициент эффективности (зависит, например, насколько далеко от сущности упало взрывное зелье)applyAttributesModifiersToEntity
- вызывается единожды при наложении эффекта. Обычно служит для добавления модификаторов, вроде доп. сердец. Параметры - сущность под эффектом, список атрибутов (идентичен списку при вызовеgetAttributeMap
у сущности), модификатор.removeAttributesModifiersFromEntity
- вызывается единожды при снятии эффекта. Служит для удаления модификаторов. Параметры те же.
Java:
public class PotionFlight extends PotionMod {
public PotionFlight() {
super(40, "flight", false, 0xFFFFEE, 2);
}
@Override
public boolean isReady(int time, int mod) {
return true; // всегда готово
}
@Override
public void performEffect(EntityLivingBase living, int mod) {
// каждый тик заставляем лететь (немного читерно для данжа из таумкрафта, лучше так не делать)
if (living instanceof EntityPlayer) ((EntityPlayer) living).capabilities.isFlying = true;
}
@Override
public void applyAttributesModifiersToEntity(EntityLivingBase living, BaseAttributeMap map, int mod) {
// даём полёт
if (living instanceof EntityPlayer) {
EntityPlayer player = ((EntityPlayer) living);
player.capabilities.allowFlying = true;
player.capabilities.isFlying = true;
player.sendPlayerAbilities();
}
}
@Override
public void removeAttributesModifiersFromEntity(EntityLivingBase living, BaseAttributeMap map, int mod) {
// забираем полёт
if (living instanceof EntityPlayer) {
EntityPlayer player = ((EntityPlayer) living);
player.capabilities.allowFlying = false;
player.capabilities.isFlying = false;
player.sendPlayerAbilities(); // синхронизация атрибутов. Без неё полёт не снимается.
}
}
}
Отлично! Теперь, если игрок будет под эффектом нашего зелья он сможет летать.
Эффект готов, а это значит что пора обеспечить возможность его получение в самой игре!
Накладывание на игрока:
Думаю, как создавать и регистрировать предметы рассказывать смысла нет, поэтому вкратце расскажу как сделать предмет, дающий эффект зелья при выпивании:
Java:
public class ItemFlight extends ItemFood { // наследуем еду
public ItemFlight() {
// Оно не будет восстанавливать голод и сытость, и им нельзя кормить волка
super(0, 0, false);
// Добавление зелья к еде: ID, длительность (с), сила (-1 чтобы убрать частицы), шанс наложения (1.0 - 100%)
setPotionEffect(40, 10, -1, 1.0F);
}
@Override
public EnumAction getItemUseAction(ItemStack stack) {
return EnumAction.drink; // анимация и звук питья
}
}
Вот и всё! Осталось дропнуть этот предмет с какого-нибудь босса, и когда игрок его выпьет - получит креативный полёт на 10 секунд.
Всем спасибо за внимание!