Пример того как можно использовать тип Directional у источника света вне DNC моделей.
Можно заметить что каждый раз свет падает под разными углами.
Суть в том чтобы использовать модель dummy.mdx со 180 анимациями и крепить к ней эффектом модель с источником света. Таким образом можно управлять направлением света молнии с помощью поворота юнита и сменой его анимации.
устройство модели с источником света
Version {
FormatVersion 800,
}
Model "L_1.2" {
BlendTime 0,
BoundsRadius 1.0E9,
}
Sequences 2 {
Anim "Stand" {
Interval { 1000, 1100 },
BoundsRadius 1.0E9,
}
Anim "Death" {
Interval { 10000, 10100 },
NonLooping,
BoundsRadius 1.0E9,
}
}
GlobalSequences 1 {
Duration 0,
}
Light "Lightning" {
ObjectId 0,
Directional,
static AttenuationStart 0.0,
static AttenuationEnd 0.0,
static Intensity 1.2,
static Color { 1.0, 0.7529412, 0.5019608 },
static AmbIntensity 0.0,
static AmbColor { 0.0, 0.0, 0.0 },
Visibility 2 {
DontInterp,
1000: 1.0,
10000: 0.0,
}
Rotation 1 {
DontInterp,
GlobalSeqId 0,
0: { 0.707107, 0.0, -0.707107, 0.0 },
}
}
PivotPoints 1 {
{ 0.0, 0.0, 0.0 },
}
На каждый вариант интенсивности и цвета света нужно делать отдельную модель.
- Intensity - Означает яркость вспышки света (в данном примере 1.2).
- Color - Означает цвет вспышки света (в данном примере светло-голубой).
Так же есть возможность смены цвета тумана под цвет молнии.
Если используете динамический туман, можете динамически менять соответствующие значения в глобалках чтобы оно автоматом подстраивалось.
Если используете динамический туман, можете динамически менять соответствующие значения в глобалках чтобы оно автоматом подстраивалось.
Для отображения света нужно чтобы в момент создания и удаления эффекта на даммике он был в позиции цели камеры игрока. Так что в эти моменты дамми перемещается в GetCameraTargetPosition, это не вызывает десинха само по себе.
Однако свет изредка багуется если быстро дергать камеру, тогда свет пропадает только через 5 сек (дефолт значение в константах), пока думаю как решить эту проблему. Есть идеи у кого?
Вроде стало норм когда у модели dummy.mdx установил Bounds Radius большой и время смерти дамика увеличил (мб не успевала проиграться анимация смерти эффекта).
Однако свет изредка багуется если быстро дергать камеру, тогда свет пропадает только через 5 сек (дефолт значение в константах), пока думаю как решить эту проблему. Есть идеи у кого?
Вроде стало норм когда у модели dummy.mdx установил Bounds Radius большой и время смерти дамика увеличил (мб не успевала проиграться анимация смерти эффекта).
Звук пока не проигрывается с первого раза, нужно бы заюзать прелоад для этого, но у меня почему-то никак это не получалось - звук все равно не проигрывался. Еще конечно неплохо было бы заюзать какой-нибудь ресайклер для звуков, но то уже такое.
В карте - примере присутствуют:
3 модели источника света светло-голубого цвета разной интенсивности.
3 звука грома и фоновый звук дождя которые были скомунизжены отсюда.
3 модели источника света светло-голубого цвета разной интенсивности.
3 звука грома и фоновый звук дождя которые были скомунизжены отсюда.
Сама мапа взята отсюда.
код
library Storm initializer Init
// Storm v1.1
// by OVOgenez
globals
private constant integer DUMMY_ID = 'h000' // ИД дамми
public constant integer VAR_COUNT = 3 // Количество вариаций грозы
private string array LightningPath // Путь к моделям молнии
private string array ThunderPath // Путь к звукам грома
private real array L_intensity // Интенсивность источников света
private real array L_red // Красный цвет источников света
private real array L_green // Зеленый цвет источников света
private real array L_blue // Синий цвет источников света
//------------------------------------------
// Эти значения можно динамически менять если используется динамический туман.
//
public boolean TF = true // Используется ли туман
public integer TF_style = 0 // Стиль тумана
public real TF_zstart = 1000.0 // Начало тумана по Z
public real TF_zend = 3000.0 // Конец тумана по Z
public real TF_density = 0.0 // Плотность тумана
public real TF_red = 0.0 // Красный цвет тумана
public real TF_green = 0.0 // Зеленый цвет тумана
public real TF_blue = 0.0 // Синий цвет тумана
//------------------------------------------
private location TempLocation = Location(0, 0)
endglobals
//==========================================
// Инициализация значений массивов. НЕ связано с количеством вариаций VAR_COUNT.
//
private function Init takes nothing returns nothing
set LightningPath[1] = "L1.mdx"
set LightningPath[2] = "L2.mdx"
set LightningPath[3] = "L3.mdx"
set ThunderPath[1] = "T1.wav"
set ThunderPath[2] = "T2.wav"
set ThunderPath[3] = "T3.wav"
set L_intensity[1] = 0.4
set L_intensity[2] = 0.8
set L_intensity[3] = 1.2
set L_red[1] = 0.5
set L_red[2] = 0.5
set L_red[3] = 0.5
set L_green[1] = 0.75
set L_green[2] = 0.75
set L_green[3] = 0.75
set L_blue[1] = 1.0
set L_blue[2] = 1.0
set L_blue[3] = 1.0
endfunction
private module Settings
static constant real PERIOD = 0.03125 // Период таймера
//------------------------------------------
// Эти значения можно использовать в методах ниже для определения результата.
//
readonly integer Variant // Вариация грозы (от 1 до VAR_COUNT)
readonly integer Count // Количество вспышек света (от 1 до ...)
readonly integer Current // Текущая вспышка света (от 1 до Count; 0 во время задержки перед звуком)
readonly integer Azimuth // Горизонтальный угол света (от -180 до 180)
readonly integer Zenith // Вертикальный угол света (от -90 до 90)
readonly integer LIndex // Индекс текущей модели молнии для массива LightningPath
readonly integer TIndex // Индекс текущего звука грома для массива ThunderPath
//------------------------------------------
//==========================================
// Вернуть индекс модели молнии для массива LightningPath.
//
method operator GetLightningIndex takes nothing returns integer
return .Variant
endmethod
//==========================================
// Вернуть индекс звука грома для массива ThunderPath.
//
method operator GetThunderIndex takes nothing returns integer
return .Variant
endmethod
//==========================================
// Вернуть длительность вспышки молнии.
//
method operator GetPlayDuration takes nothing returns real
return GetRandomInt(2, 4)*PERIOD
endmethod
//==========================================
// Вернуть длительность между вспышками молнии.
//
method operator GetStopDuration takes nothing returns real
return GetRandomInt(1, 3)*PERIOD
endmethod
//==========================================
// Вернуть задержку до звука грома.
//
method operator GetSoundDelay takes nothing returns real
return (10*(VAR_COUNT*VAR_COUNT - .Variant*.Variant) + GetRandomInt(0, 10))*PERIOD
endmethod
//==========================================
// Вернуть громкость звука грома.
//
method operator GetSoundVolume takes nothing returns integer
return GetRandomInt(R2I(127*0.8), 127)
endmethod
//==========================================
// Вернуть высоту звука грома.
//
method operator GetSoundPitch takes nothing returns real
return GetRandomReal(0.9, 1.1)
endmethod
endmodule
//==================================================================================================================
private module Array
private static thistype array ARRAY
private static integer SIZE = 0
private integer INDEX = 0
static method operator size takes nothing returns integer
return SIZE
endmethod
static method operator [] takes integer i returns thistype
return ARRAY[i]
endmethod
method remove takes nothing returns nothing
if INDEX != 0 then
set ARRAY[SIZE].INDEX = INDEX
set ARRAY[INDEX] = ARRAY[SIZE]
set ARRAY[SIZE] = 0
set INDEX = 0
set SIZE = SIZE - 1
endif
endmethod
method add takes nothing returns nothing
if INDEX == 0 then
set SIZE = SIZE + 1
set INDEX = SIZE
set ARRAY[SIZE] = this
endif
endmethod
endmodule
private struct TStorm
implement Array
implement Settings
private static boolean TempTF = TF
private static integer TempTF_style = TF_style
private static real TempTF_zstart = TF_zstart
private static real TempTF_zend = TF_zend
private static real TempTF_density = TF_density
private static real TempTF_red = TF_red
private static real TempTF_green = TF_green
private static real TempTF_blue = TF_blue
private static timer Timer = CreateTimer()
private unit Dummy
private effect Effect
private real Time
private boolean Mode
private method toCamera takes nothing returns nothing
call SetUnitX(.Dummy, GetCameraTargetPositionX())
call SetUnitY(.Dummy, GetCameraTargetPositionY())
endmethod
method destroy takes nothing returns nothing
call this.remove()
// ====================
call .toCamera()
call DestroyEffect(.Effect)
call KillUnit(.Dummy)
set .Effect = null
set .Dummy = null
// ====================
call this.deallocate()
endmethod
private method Function takes nothing returns nothing
local sound s
call .toCamera()
set .Time = .Time - PERIOD
if .Time <= 0 then
if .Current > 0 and .Current <= .Count then
if not .Mode then
set .Mode = true
set .Time = .GetPlayDuration
set .LIndex = .GetLightningIndex
set .Effect = AddSpecialEffectTarget(LightningPath[.LIndex], .Dummy, "origin")
else
set .Mode = false
set .Time = .GetStopDuration
set .Current = .Current + 1
if .Current > .Count then
set .Current = 0
set .Time = .GetSoundDelay
endif
call DestroyEffect(.Effect)
set .Effect = null
endif
elseif .Current == 0 then
set .TIndex = .GetThunderIndex
set s = CreateSound(ThunderPath[.TIndex], false, false, false, 10, 10, "DoodadsEAX")
call SetSoundChannel(s, 10)
call SetSoundVolume(s, .GetSoundVolume)
call SetSoundPitch(s, .GetSoundPitch)
call StartSound(s)
call KillSoundWhenDone(s)
set s = null
call this.destroy()
endif
endif
endmethod
private static method Periodic takes nothing returns nothing
local real r = TF_red
local real g = TF_green
local real b = TF_blue
local integer i = thistype.size
loop
exitwhen i <= 0
call thistype[i].Function()
if TF and thistype[i] > 0 and thistype[i].Count > 0 and thistype[i].Mode then
set r = r + L_red[thistype[i].LIndex]*L_intensity[thistype[i].LIndex]
set g = g + L_green[thistype[i].LIndex]*L_intensity[thistype[i].LIndex]
set b = b + L_blue[thistype[i].LIndex]*L_intensity[thistype[i].LIndex]
endif
set i = i - 1
endloop
if TF then
if TempTF != TF or /*
*/ TempTF_style != TF_style or /*
*/ TempTF_zstart != TF_zstart or /*
*/ TempTF_zend != TF_zend or /*
*/ TempTF_density != TF_density or /*
*/ TempTF_red != r or /*
*/ TempTF_green != g or /*
*/ TempTF_blue != b then
set TempTF_style = TF_style
set TempTF_zstart = TF_zstart
set TempTF_zend = TF_zend
set TempTF_density = TF_density
set TempTF_red = r
set TempTF_green = g
set TempTF_blue = b
call SetTerrainFogEx(TF_style, TF_zstart, TF_zend, TF_density, RMinBJ(1, r), RMinBJ(1, g), RMinBJ(1, b))
endif
elseif TempTF != TF then
call ResetTerrainFog()
endif
set TempTF = TF
endmethod
static method create takes integer variant, integer count, integer azimuth, integer zenith returns thistype
local thistype this = thistype.allocate()
// ====================
set .Variant = variant
set .Count = count
set .Current = 1
set .Azimuth = azimuth
set .Zenith = zenith
set .Time = 0
set .Mode = false
set .Dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, azimuth)
call SetUnitAnimationByIndex(.Dummy, zenith + 90)
// ====================
call this.add()
return this
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(Timer, PERIOD, true, function thistype.Periodic)
endmethod
endstruct
//==================================================================================================================
//==========================================
// Имитировать грозу:
// variant - Вариация грозы (от 1 до VAR_COUNT)
// count - Количество вспышек света (от 1 до ...)
// azimuth - Горизонтальный угол света (от -180 до 180)
// zenith - Вертикальный угол света (от -90 до 90)
//
public function Imitate takes integer variant, integer count, integer azimuth, integer zenith returns nothing
if variant > 0 and variant <= VAR_COUNT and count > 0 then
call TStorm.create(variant, count, azimuth, zenith)
endif
endfunction
//==========================================
// Имитировать грозу (случайно):
// variant - Вариация грозы (от 1 до VAR_COUNT)
//
public function ImitateSimple takes integer variant returns nothing
call Imitate(variant, GetRandomInt(2, 4), GetRandomInt(-180, 180), GetRandomInt(-90, -30))
endfunction
endlibrary
Потому не проще ли сделать 1 модельку на 10 анимаций stand, с разной случайностью, запихнуть туда источник света, прикрутить его к кости и задать кости повороты, а у самого источника заанимировать яркость и видимость, чтоб были разные вспышки?
Саму модель молнии делать не считал нужным, т.к. цель в другом состояла. Но если делать какую-нибудь мапу от 1 лица то можно понаделать всяких отдельных эффектов молний чтобы на фоне скайбокса смотрелось.
Есть баги событийников звука - если есть директионал свет - звук не работает. Пришлось делать отдельную модельку чисто со звуками, тогда заработало.
Edited by EugeAl
Edited by Jack-of-shadow
Можно просто заменять ее на время вспышки.
Спасибо)