Приветствую Вас, Гость! Регистрация RSS

Мой сайт

Четверг, 02.05.2024
Главная страница форума
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » MTA | Multi Theft Auto » Lua скриптинг (Уроки, FAQ) » [Урок] Торнадо
[Урок] Торнадо
Nanotech_uaДата: Четверг, 08.12.2011, 15:19 | Сообщение # 1
Майор
Группа: Администраторы
Сообщений: 95
Репутация: 4
Статус: :-(
В этом уроке, мы создадим торнадо, прям у себя на сервере!!

Для начала, давайте создадим новую папку с названием "265_tornado".

Далее что нам надо сделать:

1) Создать файл "meta.xml", в него вставить следующий код:

Code
<meta>
      <info author="norby89" version="1.0.1" type="script" name="Tornado"/>
      <config src="help.xml" type="client"/>
      <script src="tornado_s.lua" />
      <script src="gui.lua" type="client" />
      <script src="tornado.lua" type="client" />
</meta>


2) Создать "help.xml", и в него код:

Code
<help popup="yes">
This resource will spawn all players at the farm where the tornado is at coordinates 0,0,0. The tornado control menu can be brought back up with the "M" key. Note that this is a clientside script.   

NOTE: The tornado is NOT synced. When tornado settings are changed on the GUI they will only affect you. When someone joins the server the tornado will recreate. It seems difficult to fix this due to the way it was structured.

Currently it has no purpose. It is just for demonstration. Concept and original scripting by norby89. The final version with the GUI was lost and rebuilt by Ransom.   
</help>


3) Создать "gui.lua", и в него код:

Code
local resourceRoot = getResourceRootElement ( getThisResource() )
local root = getRootElement()
local scrollFields = { "height", "width", "thickness", "fog", "count" }
local elementData = {}
local guiElements = {}

function setLocalElementData ( element, field, value )
   if ( not elementData[element] ) then
    elementData[element] = {}
   end
   elementData[element][field] = value
end

function getLocalElementData ( element, field )
   return elementData[element][field]
end

function getRange ( field )
   if field == "height" then
    return 1, 30
   elseif field == "width" then
    return 1, 20
   elseif field == "thickness" then
    return 0.1, 2
   elseif field == "fog" then
    return 0, 1
   elseif field == "count" then
    return 1, 1000
   end
end   

function getOption ( field )   
   if field == "height" then
    return 20
   elseif field == "width" then
    return 10
   elseif field == "thickness" then
    return 0.1
   elseif field == "fog" then
    return 0.05
   elseif field == "count" then
    return 100
   end
end   

--Whole naming system is interlinked so I'm just injecting hax here with the below table and function
labelName = { "Height", "Cone Shape", "Diameter", "Fog Object %", "Total Objects" }   

function crossReference(field)
   for k,v in pairs(scrollFields) do
    if field == scrollFields[k] then
     return k
    end
   end   
end
-----------------------------------------------------------------------------------------------------

function createScroll ( x, y, width, height, maxLength, space, window, field )
   local begin, finish = getRange ( field )
   local default = getOption ( field )
   local scrollBar = guiCreateScrollBar ( x, y, width, height, true, true, window )
     
   guiSetProperty ( scrollBar, "StepSize", ".01" )
   local scrollBox = guiCreateEdit ( 0.8, y, 0.16, height, tostring ( default ) , true, window )
   local percentage = getNewPercentage ( field, default )
   guiScrollBarSetScrollPosition ( scrollBar, percentage )
   guiEditSetMaxLength ( scrollBox, maxLength )
   addEventHandler ( "onClientGUIScroll", scrollBar, checkBar, false )
   addEventHandler ( "onClientGUIChanged", scrollBox, checkBox, false )   
   local name = guiCreateLabel ( x + 0.05, y - ( space / 2 ), 0.3, height, labelName[crossReference(field)], true, window )
   local label_01 = guiCreateLabel ( x - 0.1, y, 0.09, height, tostring ( begin ), true, window )
   local label_02 = guiCreateLabel ( x + width, y, 0.09, height, tostring ( finish ), true, window )
   guiLabelSetVerticalAlign ( name, "center" )
   guiLabelSetVerticalAlign ( label_01, "center" )
   guiLabelSetVerticalAlign ( label_02, "center" )
   guiLabelSetHorizontalAlign ( name, "left" )
   guiLabelSetHorizontalAlign ( label_01, "right" )
   guiLabelSetHorizontalAlign ( label_02, "right" )
   setLocalElementData ( scrollBar, "field", field )
   setLocalElementData ( scrollBar, "box", scrollBox )
   setLocalElementData ( scrollBar, "name", label_02 )
   setLocalElementData ( scrollBar, "label_01", label_01 )
   setLocalElementData ( scrollBar, "label_02", label_02 )
   return scrollBar
end

function createWindow()
   local window = guiCreateWindow ( 0.62, 0.25, 0.35, 0.55, "Tornado Options", true )
   showCursor ( true )
   toggleAllControls ( false, false, true )
   guiWindowSetMovable ( window, true )
   guiWindowSetSizable ( window, false )
   bindKey ( "m", "down", toggleWindow )
   guiElements.window = window
   guiElements.isWindowActive = true
     
   -- local editBox = guiCreateEdit ( 0.3, 0.085, 0.4, 0.08, "", true, window )
   -- guiCreateLabel ( 0.07, 0.1, 0.3, 0.2, "Name: ", true, window )
     
   guiEditSetMaxLength ( editBox, 24 )
   guiElements.editBox = editBox
     
   local closeButton = guiCreateButton ( 0.89, 0.085, 0.08, 0.08, "x", true, window )
   addEventHandler ( "onClientGUIClick", closeButton, hideWindow, false )
   guiElements.closeButton = closeButton
     
   local scrollTable = {}
   local scrolls = 5
   local space = 0.8 / ( scrolls + 1 )
   for i=1, scrolls do
    local y = 0.1 + i * space
    local scroll = createScroll ( 0.1, y, 0.55, 0.06, 6, space, window, scrollFields[i] )
    table.insert ( scrollTable, scroll )
   end
   guiElements.scrollTable = scrollTable
end

function getNewPosition ( field, percentage )
   local begin, finish = getRange ( field )
   local newPosition = begin + ( finish - begin ) * percentage / 100
   return ( field == "count" ) and math.floor ( newPosition ) or newPosition
end

function getNewPercentage ( field, position )
   local begin, finish = getRange ( field )
   local newPercentage = ( position - begin ) * 100 / ( finish - begin )
   return newPercentage
end

function getScrollBar ( scrollBox )
   local scrollBar = nil
   for i, v in ipairs ( guiElements.scrollTable ) do
    local box = getLocalElementData ( v, "box" )
    if ( scrollBox == box ) then
     scrollBar = v
     break
    end
   end
   return scrollBar
end

-- string.format( "%.4f", 0.023232323 ) -- 4 places
function roundToString ( num, places )
   num = tostring ( num )
   if num:match ( '%.' ) then
    num = num:gsub ( '(%.' .. ( '%d' ):rep ( places ) .. ')%d+', '%1' )
   end
   return num
end

function checkBar ( scrollBar )
   local field = getLocalElementData ( scrollBar, "field" )
   if field == "fog" or field == "count" then
    if ( not guiElements.isInUse ) then
     local scrollBox = getLocalElementData ( scrollBar, "box" )
     local field = getLocalElementData ( scrollBar, "field" )
     local percentage = guiScrollBarGetScrollPosition ( scrollBar )
     local position = getNewPosition ( field, percentage )
       
     guiElements.isInUse = true
     guiSetText ( scrollBox, roundToString ( position, 2 ) )
     setOption ( field, position )
     guiElements.isInUse = false
    end   
      
    if not regenerateDelay then
     destroyTornado()
     if pieces then
      if pieces.count then
       for i=1, pieces.count do
        if pieces.createPieceDelay then
         killTimer ( pieces.createPieceDelay )
         outputChatBox ( "got it." )
        end
       end
      end
     end
     regenerateDelay = setTimer ( function ()
      onStart()    
      regenerateDelay = nil
      -- outputChatBox ( "regenerateDelay ENDED" ) --DEBUG
     end, 500, 1 )
    end
   else
    if ( not guiElements.isInUse ) then
     local scrollBox = getLocalElementData ( scrollBar, "box" )
     local field = getLocalElementData ( scrollBar, "field" )
     local percentage = guiScrollBarGetScrollPosition ( scrollBar )
     local position = getNewPosition ( field, percentage )
       
     guiElements.isInUse = true
     guiSetText ( scrollBox, roundToString ( position, 2 ) )
     setOption ( field, position )
     guiElements.isInUse = false
    end
   end
end

function checkBox ( scrollBox )
     
   if ( not guiElements.isInUse ) then
    local scrollBar = getScrollBar ( scrollBox )
    local field = getLocalElementData ( scrollBar, "field" )
    local percentage = guiScrollBarGetScrollPosition ( scrollBar )
    local position = tonumber ( guiGetText ( scrollBox ) )
      
    guiElements.isInUse = true
    if ( position ) then
     local begin, finish = getRange ( field )
     if ( position >= begin ) and ( position <= finish ) then
      percentage = getNewPercentage ( field, position )
      guiScrollBarSetScrollPosition ( scrollBar, percentage )
      setOption ( field, position )
     else
      position = getNewPosition ( field, percentage )
      guiSetText ( scrollBox, roundToString ( position, 2 ) )
     end
    else
     position = getNewPosition ( field, percentage )
     guiSetText ( scrollBox, roundToString ( position, 2 ) )
    end
    guiElements.isInUse = false
   end
end

function toggleWindow()
   local active = guiElements.isWindowActive
   if ( active ) then
    hideWindow ( "left" )
   else
    showWindow()
   end
end      

function hideWindow ( button )
   if ( button == "left" ) then
    local window = guiElements.window
    showCursor ( false )
    guiSetVisible ( window, false )
    toggleAllControls ( true )
    guiElements.isWindowActive = false
   end
end

function showWindow()
   local window = guiElements.window
   showCursor ( true )
   guiSetVisible ( window, true )
   toggleAllControls ( false, false, true )
   guiElements.isWindowActive = true
end

addEvent ( "onClientWindowReady" )
addEventHandler ( "onClientWindowReady", root, createWindow )

createWindow()


4) Создать "tornado.lua", и в него код:

Code
-- tits = 33 % 2232
-- outputChatBox ( tits )   

local root = getRootElement()
   local ids = { 2780, 701, 702 }    -- fog machine, tumbleweed 1/2
local pieces = { height = 20,  -- shouldn't be 0
      width = 10,   -- top radius
      thickness = 0.1,    -- 0 < * ( 1 being the width )
      fog = .75,   -- between 0 and 1
      count = 100 }  -- including fogmachines
-- local previous = { fog = pieces.fog,
         -- count = pieces.count }

function setOption ( field, value )
   pieces[field] = value
end

function getOption ( field )
   return pieces[field]
end

function randomObject ( spacing, majorityIsFogMachines )   
   if majorityIsFogMachines == false then
    if spaceCount == spacing then
     spaceCount = 0
     -- fogCount = fogCount + 1 --debug
     -- outputChatBox ( "fogCount = "..fogCount ) --debug
     return ids[1]
    else
     spaceCount = spaceCount + 1
     -- tumbleCount = tumbleCount + 1 --debug
     -- outputChatBox ( "tumbleCount = "..tumbleCount ) --debug    
     return ids[math.random ( 2, #ids )]   
    end
   elseif majorityIsFogMachines == true then --When over fifty, tumble weed becomes what is spaced, not fog machines
    if spaceCount == spacing then
     spaceCount = 0     
     -- tumbleCount = tumbleCount + 1 --debug
     -- outputChatBox ( "tumbleCountB = "..tumbleCount ) --debug   
     return ids[math.random ( 2, #ids )]
    else
     spaceCount = spaceCount + 1
     -- fogCount = fogCount + 1 --debug
     -- outputChatBox ( "fogCountB = "..fogCount ) --debug
     return ids[1]
    end    
   end
end

function getRandomPositionOffsets ( x, y, z )
   local a, b = -1, 1
   x, y, z = x + randFloat ( a, b ), y + randFloat ( a, b ), z + randFloat ( a, b )
   return x, y, z
end

function getRandomRotationOffsets()
   local rx, ry, rz = math.random ( 0, 10 ), math.random ( 0 , 10 ), math.random ( 0 , 5 )
   return rx, ry, rz
end

function getRandomAngleOffsets()
   local angle1, angle2 = randFloat ( 0.005, 0.1 ), randFloat ( 0.01, 0.03 )
   return angle1, angle2
end

function randFloat ( a, b )
   return a + math.random() * ( b - a )
end

function updateElementsPosition()
   local count = #pieces
   if ( count > 0 ) then
    for i=1, count do
     local piece = pieces[i]
     local object = piece.object
       
     local oldPosX, oldPosY, oldPosZ = getElementPosition ( object )
     local oldRotX, oldRotY, oldRotZ = getElementRotation ( object )
     local posXOffset, posYOffset, posZOffset = piece.posXOffset, piece.posYOffset, piece.posZOffset
     local tx, ty, tz = getElementPosition ( pieces.dummyTornado )
     local height, width, thickness = pieces.height, pieces.width, pieces.thickness
       
     local newRotX, newRotY, newRotZ = oldRotX + piece.rotXOffset, oldRotY + piece.rotYOffset, oldRotZ + piece.rotZOffset
     local newAngle1, newAngle2 = piece.angle1 + piece.angle1Offset, piece.angle2 + piece.angle2Offset
       
     local newWidth = width * ( 1 + thickness - math.cos ( math.asin ( ( oldPosZ - posZOffset - tz ) / ( height * 1.05 ) ) ) )
     local newPosX = tx + posXOffset + newWidth * ( math.cos ( newAngle1 ) )
     local newPosY = ty + posYOffset + newWidth * ( math.sin ( newAngle1 ) )
     local newPosZ = tz + posZOffset + ( height / 2 ) * ( 1 + math.sin ( newAngle2 ) )
       
     piece.angle1 = ( newAngle1 > 2 * math.pi ) and ( newAngle1 - 2 * math.pi ) or newAngle1
     piece.angle2 = ( newAngle2 > 2 * math.pi ) and ( newAngle2 - 2 * math.pi ) or newAngle2
       
     setElementPosition ( object, newPosX, newPosY, newPosZ )
     setElementRotation ( object, newRotX, newRotY, newRotZ )
    end
   end
end

function createTornadoPiece ( i, spacing, majorityIsFogMachines )
   if ( i ) then
    local tx, ty, tz = getElementPosition ( pieces.dummyTornado )
    local piece = {}
    local model = randomObject ( spacing, majorityIsFogMachines )
    piece.object = createObject ( model, tx, ty, tz, rx, ry, rz )
    piece.posXOffset, piece.posYOffset, piece.posZOffset = getRandomPositionOffsets ( tx, ty, tz )
    piece.rotXOffset, piece.rotYOffset, piece.rotZOffset = getRandomRotationOffsets()
    piece.angle1Offset, piece.angle2Offset = getRandomAngleOffsets()
    piece.angle1, piece.angle2 = piece.angle1Offset, - math.pi / 2
    pieces[i] = piece
    if model == 2780 then --fog machine
     setTimer ( setElementAlpha, 500, 1, piece.object, 0 )   
    end
    setTimer ( setElementCollidableWith, 500, 1, getLocalPlayer(), piece.object, false )
   else   
    return false
   end
end

function createTornado()
   outputChatBox ( "Tornado started." )
   pieces.dummyTornado = source
   onStart() --!!
end

addEvent ( "onTornado", true )
addEventHandler ( "onTornado", root, createTornado )

function destroyTornado()
   local timers = getTimers ()
   for k, v in ipairs(timers) do
      killTimer ( v )
   end
   removeEventHandler ( "onClientRender", root, updateElementsPosition )
   for i=1, #pieces do
    local object = pieces[i].object
    destroyElement ( object )
    pieces[i] = nil
   end
end

addEvent ( "onTornadoStop", true )
addEventHandler ( "onTornadoStop", root, destroyTornado )

function onStart()
   -- tumbleCount = 0 --debug
   -- fogCount = 0 --debug

   tornadoRender = addEventHandler ( "onClientRender", root, updateElementsPosition )
   local fogMachines = math.floor(pieces.count * pieces.fog) --Percentage of objects to be fog machines
   local tumbleWeeds = math.floor(pieces.count * (1-pieces.fog))
   local spacing = math.floor(tumbleWeeds / fogMachines)
   local majorityIsFogMachines = false   
   spaceCount = 0
   if spacing < 1 then
    majorityIsFogMachines = true
    spacing = math.floor(fogMachines / tumbleWeeds)
   end
   --debug
   -- outputChatBox ( "pieces.fog = "..pieces.fog )
   -- outputChatBox ( "pieces.count = "..pieces.count )
   -- outputChatBox ( "fogMachines = "..fogMachines )
   -- outputChatBox ( "tumbleWeeds = "..tumbleWeeds )
   -- outputChatBox ( "majorityIsFogMachines == "..tostring(majorityIsFogMachines) )   
   -- outputChatBox ( "spacing = "..spacing )
   --debug
   for i=1, pieces.count do
    setTimer ( createTornadoPiece, i * 50, 1, i, spacing, majorityIsFogMachines )
   end
end

function clientPlayerJoin ()
   setTimer ( function ()
    if not tornadoRender then
     onStart(source)
    end
   end, 1000, 1 )
end
addEventHandler ( "onClientResourceStart", getResourceRootElement ( getThisResource() ), clientPlayerJoin )

--addEventHandler ( "onClientResourceStart", getResourceRootElement ( getThisResource() ), onStart )
--local newPosX = tx + pieces[i].posXOffset + pieces.width * ( 1 + thickness - math.cos ( math.asin ( ( oldPosZ - posZOffset - tz ) / ( height * 1.05 ) ) ) ) * ( math.cos ( pieces[i].angle1 + pieces[i].angle1Offset ) )


5) Создать "tornado_s.lua", и вставить код:

Code
local root = getRootElement()
local resourceRoot = getResourceRootElement ( getThisResource() )
local dummy = nil
--local dummy2 = createObject ( 1337, 0, 10, 4 )

function spawnAllPlayers()
players = getElementsByType ( "player" )
for k,v in pairs(players) do
r = 5
angle = math.random(0, 359.99) --random angle between 0 and 359.99
centerX = 38.977
centerY = -19.282
spawnX = r*math.cos(angle) + centerX --circle trig math
spawnY = r*math.sin(angle) + centerY --circle trig math
spawnAngle = 360 - math.deg( math.atan2 ( (0 - spawnX), (0 - spawnY) ) )
spawnPlayer ( v, spawnX, spawnY, 2.5, spawnAngle )
end
end

function spawnAndBindJoinedPlayer()
local player = source
setTimer ( createTornado, 1000, 1 )
setTimer ( function()
r = 5
angle = math.random(0, 359.99) --random angle between 0 and 359.99
centerX = 38.977
centerY = -19.282
spawnX = r*math.cos(angle) + centerX --circle trig math
spawnY = r*math.sin(angle) + centerY --circle trig math
spawnAngle = 360 - math.deg( math.atan2 ( (0 - spawnX), (0 - spawnY) ) )
spawnPlayer ( player, spawnX, spawnY, 2.5, spawnAngle )

bindKey ( player, "num_8", "down", move, "up" )
bindKey ( player, "num_4", "down", move, "left" )
bindKey ( player, "num_6", "down", move, "right" )
bindKey ( player, "num_5", "down", move, "down" )
end, 1500, 1 )
end

function createTornado()
dummy = createObject ( 1337, 0, 0, 2 )
setElementDimension ( dummy, 69 )
triggerClientEvent ( "onTornado", dummy )
-- outputChatBox ( "..." )
end

-- function lol()
-- local x, y, z = getElementPosition ( dummy2 )
-- local rotX, rotY, rotZ = getObjectRotation ( dummy2 )
-- local x2, y2, z2 = getElementPosition ( getPlayerFromNick ( "norby89" ) )
-- local newRotZ = math.deg ( math.asin ( ( x - x2 ) / getDistanceBetweenPoints2D ( x, y, x2, y2 ) ) )
-- outputChatBox ( newRotZ )
-- setObjectRotation ( dummy2, rotX, rotY, newRotZ )

-- end
-- setTimer ( lol, 100, 0 )

function move ( player, cmd, state, direction )
local x, y, z = getElementPosition ( dummy )
if ( direction == "up" ) then
moveObject ( dummy, 10000, x, y + 100, z )
elseif ( direction == "left" ) then
moveObject ( dummy, 10000, x - 100, y, z )
elseif ( direction == "right" ) then
moveObject ( dummy, 10000, x + 100, y, z )
elseif ( direction == "down" ) then
moveObject ( dummy, 10000, x, y - 100, z )
end
end

function bindKeys()
spawnAllPlayers()
setTimer ( createTornado, 1000, 1 )
for i, v in ipairs ( getElementsByType ( "player" ) ) do
bindKey ( v, "num_8", "down", move, "up" )
bindKey ( v, "num_4", "down", move, "left" )
bindKey ( v, "num_6", "down", move, "right" )
bindKey ( v, "num_5", "down", move, "down" )
end
end

addEventHandler ( "onResourceStart", resourceRoot, bindKeys )
addEventHandler ( "onPlayerJoin", root, spawnAndBindJoinedPlayer )


Вот и всё! Урок готово smile . Теперь у вас на сервере будет торнадо. Для того чтоб редактировать его, жмем клавишу "M".

Вот ниже сделал скрин, где находится само торнадо. Примечание: При нажатии клавиши "M", вы телепортируетесь на место торнадо!! smile
Ссылка на скрин: http://savepic.su/938303.png .
 
Форум » MTA | Multi Theft Auto » Lua скриптинг (Уроки, FAQ) » [Урок] Торнадо
  • Страница 1 из 1
  • 1
Поиск:

Последние сообщения:
Самые активные:
Лучшая репутация:
Новые пользователи:
1 | Какой жанр музыки вы любите больше всего слушаеть?[Alexandr]

2 | [Урок] Создание макрера[kryuchin_sasha]

3 | [MTA:SA] FAQ По скриптингу в MTA[nebolskaya]

4 | Считаем до 100[mryagotv]

5 | [Урок] Анимация движения объекта по заданной траектории[NEW][mryagotv]

6 | [MTA:SA] FAQ по ресурсам. Куда, и как их ставить/запускать[osnovik123]

7 | [Урок] Настройка voice чата на сервере[Dano_97_]

8 | [Урок] Картинка в левой части экрана[BISMARCK100]

9 | Помогите в создании сервера![Nick]

10 | Видео уроки по скриптингу в мта са.[Tommy]

1 Nanotech_ua (95|0)

2 Fast_C (17|0)

3 S4n_n1 (14|0)

4 Sucre (6|0)

5 eshka (6|0)

6 Onlines (4|0)

7 drako (3|0)

8 startsmart (3|0)

9 Leone1e (3|0)

10 Step_uP (2|0)

11 Nik (2|0)

12 Fani (2|0)

1 Nanotech_ua

2 S4n_n1

3 eshka

4 LM34

5 Nick

6 xYaroslavGTx

7 Tommy

8 мромг

9 убейте

10 Pavlik1505

11 ty4a

12 bwvsana1

1 faradejfeed

2 sackijvalentin5

3 Alexandr

4 guni3310

5 adilgereevarslanbek6

6 vpyti2020

7 stepaskhasid017

8 dobitnormalnoauf

9 faerpro135

10 boltyshev06

11 brawlstarstop1425

12 hambaryansergo