Nanotech_ua | Дата: Четверг, 08.12.2011, 15:19 | Сообщение # 1 |
Майор
Группа: Администраторы
Сообщений: 95
Статус:
| В этом уроке, мы создадим торнадо, прям у себя на сервере!!
Для начала, давайте создадим новую папку с названием "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 )
Вот и всё! Урок готово . Теперь у вас на сервере будет торнадо. Для того чтоб редактировать его, жмем клавишу "M".
Вот ниже сделал скрин, где находится само торнадо. Примечание: При нажатии клавиши "M", вы телепортируетесь на место торнадо!! Ссылка на скрин: http://savepic.su/938303.png .
|
|
| |