Манипуляции с кругом выделения и не только

» опубликован
» Способ реализации: cJass
» Тип: Наработка
Эта наработка позволяет получить доступ к тени и кругу выделения юнитов/предметов, а также текстуре земли зданий.

Принцип работы

На самом деле image и ubersplat — не handle, а индекс от массива, отсчет в котором ведется с нуля.
Пустому объекту соответствует значение -1, а null(0) ссылается на первый элемент.
Переменные, содержащие ссылки на эти типы, не нуждаются в обнулении.
При создании, выдается первый свободный слот, который, после освобождения, может быть сразу переиспользован.
Следующий код выведет на экран "equal":
» раскрыть
image a = CreateImage(...)
DestroyImage(a)
image b = CreateImage(...)

if a == b then
	BJDebugMsg("equal")
else
	BJDebugMsg("not equal")
endif
В результате создания и последующего уничтожения объекта, получается ссылка, которая указывает на следующий, пока не созданный.
Если после обретения подобной ссылки, игра создаст что-либо (круг выделения, например), её владелец получит контроль над новым объектом.
Файл текстуры нельзя менять напрямую, но можно пересоздать объект. Он будет занимать тот же слот, что и раньше, если все предыдущие слоты будут заняты, иначе придется заполнить дыры в таблице временными объектами (что уже делает готовая функция).
» Создание предмета со скрытой тенью
image shadow = CreateImage(...)
DestroyImage(shadow)
CreateItem(...)
SetImageColor(shadow, 0, 0, 0, 0)

Код

» ImageUtils
library ImageUtils

constant int IMAGE_TYPE_INVALID = -1
constant int IMAGE_TYPE_SHADOW = 0
constant int IMAGE_TYPE_SELECTION = 1
constant int IMAGE_TYPE_INDICATOR = 2
constant int IMAGE_TYPE_OCCLUSION_MASK = 3
constant int IMAGE_TYPE_UBERSPLAT = 4
constant int IMAGE_TYPE_TOPMOST = 5

private constant string dummy_texture = "ReplaceableTextures\\CommandButtons\\BTNWallOfFire.blp"

private image CreateDummyImage()
{
    return CreateImage(dummy_texture, 0, 0, 0, 0, 0, 0, 0, 0, 0, IMAGE_TYPE_SELECTION)
}

// 0 вернет первое свободное изображение, 1 — второе и т.д
image GetFreeImage(int offset)
{
    image images[]
    
    for (int i = 0; i < offset; i++)
    {
        images[i] = CreateDummyImage()
    }
    
    image result = CreateDummyImage()
    DestroyImage(result)
    
    for (int i = 0; i < offset; i++)
    {
        DestroyImage(images[i])
    }
    
    return result
}

void RecreateImage(image img, string file, real sizeX, real sizeY, real sizeZ, real posX, real posY, real posZ, real originX, real originY, real originZ, integer imageType)
{
    DestroyImage(img)
    
    image images[]
    int count = 0
    
    loop
    {
        image i = CreateDummyImage()
        
        if (i == img) {
            DestroyImage(i)
            break
        } else {
            images[count++] = i
        }
    }
    
    CreateImage(file, sizeX, sizeY, sizeZ, posX, posY, posZ, originX, originY, originZ, imageType)
    
    for (int i = 0; i < count; i++)
    {
        DestroyImage(images[i])
    }
}

void RecreateImageCentered(image img, string file, real sizeX, real sizeY, real sizeZ, real posX, real posY, real posZ, integer imageType)
{
    RecreateImage(img, file, sizeX, sizeY, sizeZ, posX, posY, posZ, sizeX/2, sizeY/2, sizeZ/2, imageType)
}

private ubersplat CreateDummyUbersplat()
{
    return CreateUbersplat(0, 0, "NGOL", 0, 0, 0, 0, false, false)
}

// 0 вернет первую свободную текстуру земли, 1 — вторую и т.д
ubersplat GetFreeUbersplat(int offset)
{
    ubersplat splats[]
    
    for (int i = 0; i < offset; i++)
    {
        splats[i] = CreateDummyUbersplat()
    }
    
    ubersplat result = CreateDummyUbersplat()
    DestroyUbersplat(result)
    
    for (int i = 0; i < offset; i++)
    {
        DestroyUbersplat(splats[i])
    }
    
    return result
}

void RecreateUbersplat(ubersplat splat, real x, real y, string name, integer red, integer green, integer blue, integer alpha, boolean forcePaused, boolean noBirthTime)
{
    DestroyUbersplat(splat)
    
    ubersplat splats[]
    int count = 0
    
    loop
    {
        ubersplat s = CreateDummyUbersplat()
        
        if (s == splat) {
            DestroyUbersplat(s)
            break
        } else {
            splats[count++] = s
        }
    }
    
    CreateUbersplat(x, y, name, red, green, blue, alpha, forcePaused, noBirthTime)
    
    for (int i = 0; i < count; i++)
    {
        DestroyUbersplat(splats[i])
    }

}

endlibrary
» ImageStructs
library ImageStructs uses ImageUtils

struct Unit
{
	unit object
	image shadow
	image cyrcle
	
	static thistype create(player owner, int id, float x, float y, float face)
	{
		thistype this = thistype.allocate()
        
		this.shadow = GetFreeImage(0)
		this.object = CreateUnit(owner, id, x, y, face)
		this.cyrcle = GetFreeImage(0)
        
		SelectUnit(this.object, true)
		SelectUnit(this.object, false)
        
        return this
	}
}

struct Building
{
	unit object
    image uimage
	ubersplat usplat
	image cyrcle
	
	static thistype create(player owner, int id, float x, float y, float face)
	{
		thistype this = thistype.allocate()
        
        this.uimage = GetFreeImage(0)
		this.usplat = GetFreeUbersplat(0)
		this.object = CreateUnit(owner, id, x, y, face)
		this.cyrcle = GetFreeImage(0)
        
		SelectUnit(this.object, true)
		SelectUnit(this.object, false)
        
        return this
	}
}

struct Item
{
	item object
	image shadow
	
	static thistype create(int id, float x, float y)
	{
		thistype this = thistype.allocate()
        
		this.shadow = GetFreeImage(0)
		this.object = CreateItem(id, x, y)
        
        return this
	}
}

endlibrary

Использование

Unit u = Unit.create(Player(0), 'hfoo', 0, 0, 0)

// ** Сокрытие круга выделения **
// Смена цвета не поможет, так как игра постоянно его переустанавливает.
SetImageType(u.cyrcle, IMAGE_TYPE_INVALID)

// Изменение текстуры круга выделения
RecreateImageCentered(u.cyrcle, "path\\to\\texture", 80, 80, 80, 0, 0, 0, IMAGE_TYPE_SELECTION)

// Прячем тень
SetImageColor(u.shadow, 0, 0, 0, 0)

// Обращение к самому юниту
SetUnitInvulnerable(u.object, true)

u.destroy()

Скриншот



Просмотров: 205

» Лучшие комментарии


8gabriel8 #1 - 4 недели назад 0
Круто! Только как этим пользоваться, я не знаю)
И для чего нужна скрытая тень?
IceFog #2 - 4 недели назад 4
для чего нужна скрытая тень?
Был вопрос, в котором хотели спрятать тень предмета. Не знаю зачем, но раз спросили, значит нужно. Ответ на тот вопрос, собственно, и сподвиг меня проверить: как это работает и на что оно еще способно.
8gabriel8 #3 - 4 недели назад 0
IceFog, спасибо за добавление информации о применении! Что в секции Код, надо поставить в код карты?
IceFog #4 - 4 недели назад 4
Скачай карту и скопируй все триггеры, кроме тех, что находятся в папке demo.
Из ресурса тоже можно взять код, но он здесь для тех, кому лень качать или у кого нет редактора.