Пример того как можно использовать тип 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.2
// by OVOgenez
globals
private constant integer DUMMY_ID = 'h000' // Unit unit ID
public constant integer VAR_COUNT = 3 // Number of storm variations
private string array LightningPath // Path to lightning models
private string array ThunderPath // Path to thunder sounds
private real array L_intensity // Light sources intensity
private real array L_red // Red color of light sources
private real array L_green // Green color of light sources
private real array L_blue // Blue color of light sources
//------------------------------------------
// These values can be dynamically changed if dynamic fog is used.
//
public boolean TF = true // Whether fog is used
public integer TF_style = 0 // Fog style
public real TF_zstart = 1000.0 // Fog start Z value
public real TF_zend = 3000.0 // Fog end Z value
public real TF_density = 0.0 // Fog density
public real TF_red = 0.0 // Red color of fog
public real TF_green = 0.0 // Green color of fog
public real TF_blue = 0.0 // Blue color of fog
//------------------------------------------
endglobals
//==========================================
// Initialization of array values. NOT related to the number of variations (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 // Timer period
//------------------------------------------
// These values can be used in the methods below to determine the result.
//
readonly integer Variant // Storm variation (from 1 to VAR_COUNT)
readonly integer Count // Number of light flashes (from 1 to ...)
readonly integer Current // Current light flash (from 1 to Count; 0 when delay before thunder)
readonly integer Azimuth // Horizontal light angle (from -180 to 180)
readonly integer Zenith // Vertical light angle (from -90 to 90)
readonly integer LIndex // Current lightning model index for LightningPath array
readonly integer TIndex // Current thunder sound index for ThunderPath array
//------------------------------------------
//==========================================
// Return the lightning model index for LightningPath array.
//
method operator GetLightningIndex takes nothing returns integer
return .Variant
endmethod
//==========================================
// Return the thunder sound index for ThunderPath array.
//
method operator GetThunderIndex takes nothing returns integer
return .Variant
endmethod
//==========================================
// Return the duration of lightning flash.
//
method operator GetPlayDuration takes nothing returns real
return GetRandomInt(2, 4)*PERIOD
endmethod
//==========================================
// Return the duration between lightning flashes.
//
method operator GetStopDuration takes nothing returns real
return GetRandomInt(1, 3)*PERIOD
endmethod
//==========================================
// Return the delay before thunder sound.
//
method operator GetSoundDelay takes nothing returns real
return (10*(VAR_COUNT*VAR_COUNT - .Variant*.Variant) + GetRandomInt(0, 10))*PERIOD
endmethod
//==========================================
// Return the volume of thunder sound.
//
method operator GetSoundVolume takes nothing returns integer
return GetRandomInt(R2I(127*0.8), 127)
endmethod
//==========================================
// Return the pitch of thunder sound.
//
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 Unit
private effect Effect
private real Time
private boolean Mode
private boolean Local
private method toCamera takes nothing returns nothing
call SetUnitX(.Unit, GetCameraTargetPositionX())
call SetUnitY(.Unit, GetCameraTargetPositionY())
endmethod
method destroy takes nothing returns nothing
call this.remove()
// ====================
call .toCamera()
call DestroyEffect(.Effect)
call KillUnit(.Unit)
set .Effect = null
set .Unit = 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
if .Local then
set .Effect = AddSpecialEffectTarget(LightningPath[.LIndex], .Unit, "origin")
else
set .Effect = AddSpecialEffectTarget("", .Unit, "origin")
endif
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
if .Local then
set s = CreateSound(ThunderPath[.TIndex], false, false, false, 10, 10, "DoodadsEAX")
call SetSoundChannel(s, 10)
else
set s = CreateSound("", false, false, false, 10, 10, "")
call SetSoundChannel(s, -1)
endif
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].Current > 0 and thistype[i].Mode and thistype[i].Local then
set r = RMinBJ(1, r + L_red[thistype[i].LIndex]*L_intensity[thistype[i].LIndex])
set g = RMinBJ(1, g + L_green[thistype[i].LIndex]*L_intensity[thistype[i].LIndex])
set b = RMinBJ(1, 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, r, g, 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, boolean localplayer returns thistype
local thistype this = thistype.allocate()
// ====================
set .Variant = variant
set .Count = count
set .Current = 1
set .Azimuth = azimuth
set .Zenith = zenith
set .Local = localplayer
set .Time = 0
set .Mode = false
set .Unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, azimuth)
call SetUnitAnimationByIndex(.Unit, 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
//==================================================================================================================
//==========================================
// Imitate storm with local player:
// variant - Storm variation (from 1 to VAR_COUNT)
// count - Number of light flashes (from 1 to ...)
// azimuth - Horizontal light angle (from -180 to 180)
// zenith - Vertical light angle (from -90 to 90)
// localplayer - Logical expression
//
public function ImitateLocal takes integer variant, integer count, integer azimuth, integer zenith, boolean localplayer returns nothing
if variant > 0 and variant <= VAR_COUNT and count > 0 then
call TStorm.create(variant, count, azimuth, zenith, localplayer)
endif
endfunction
//==========================================
// Imitate randomized storm with local player:
// variant - Storm variation (from 1 to VAR_COUNT)
// localplayer - Logical expression
//
public function ImitateRandomLocal takes integer variant, boolean localplayer returns nothing
call ImitateLocal(variant, GetRandomInt(2, 4), GetRandomInt(-180, 180), GetRandomInt(-90, -30), localplayer)
endfunction
//==========================================
// Imitate storm:
// variant - Storm variation (from 1 to VAR_COUNT)
// count - Number of light flashes (from 1 to ...)
// azimuth - Horizontal light angle (from -180 to 180)
// zenith - Vertical light angle (from -90 to 90)
//
public function Imitate takes integer variant, integer count, integer azimuth, integer zenith returns nothing
call ImitateLocal(variant, count, azimuth, zenith, true)
endfunction
//==========================================
// Imitate randomized storm:
// variant - Storm variation (from 1 to VAR_COUNT)
//
public function ImitateRandom takes integer variant returns nothing
call ImitateRandomLocal(variant, true)
endfunction
endlibrary
Потому не проще ли сделать 1 модельку на 10 анимаций stand, с разной случайностью, запихнуть туда источник света, прикрутить его к кости и задать кости повороты, а у самого источника заанимировать яркость и видимость, чтоб были разные вспышки?
Саму модель молнии делать не считал нужным, т.к. цель в другом состояла. Но если делать какую-нибудь мапу от 1 лица то можно понаделать всяких отдельных эффектов молний чтобы на фоне скайбокса смотрелось.
Есть баги событийников звука - если есть директионал свет - звук не работает. Пришлось делать отдельную модельку чисто со звуками, тогда заработало.
Ред. EugeAl
Только их в бд звуков добавлять придется
Ред. Jack-of-shadow
Можно просто заменять ее на время вспышки.
Спасибо)