Шестое руководство по скриптингу в Multi Theft Auto: DeathMatch


Шестое руководство пояснит вам, как сделать игровой мод "Царь горы"(King of the Hill). Пример скрипта KOTH здесь будет контролировать зону (холм) и давать поинты человеку, когда он занимает один из них. Каждую секунду, когда он остаются в зоне, получает 1 поинт. После определенного времени, игра закончится, и человек с самым высоким счетом побеждает.



Обучающее видео: scriptvideo6.avi - DivX 5.0 (640x480, 29.97fps, 25.1mb)

Готовый скрипт: script6.lua


Подготовка


Сначала мы устанавливаем таймер, который проверяет местоположение игроков каждые 500мс.

 
kothTimer = setTimer ( "checkHillArea", 500, 0 )

Затем, когда скрипт начат, мы начинаем игровой мод koth и создаем площадь, область, которую должны будут захватить игроки.

 
addEventHandler ( "onResourceStart", getRootElement(), "kothStart" )
function kothStart ( name )
     hillArea = createColSquare ( -2171.0678710938, 678.17950439453, 0, 15, 15 )

MTA:SA имеет способность создать и управлять областями радара банд Сан Андреаса, такие же, как вы могли видеть в одиночной игре. Чтобы создать их мы используем createRadarArea ( X, Y, sizeX, sizeY, R, G, B, A, [ elements visible to ] )

 
     hillRadar = createRadarArea ( -2183.5678710938, 705.67950439453, 40, -40, 0,
 255, 0, 175 )

Далее с петлей мы создаем показы текста (способ, который вы узнали из предыдущего руководства), который покажет лидеру и текущие поинты для каждого игрока. Устанавливаем для каждого поинты на 0 с помощью setElementData.

 
     local globalTextDisplay = textCreateDisplay ()
     textItemLeaderScore = textCreateTextItem ( "Leader: None", 0.15, 0.3, 0, 255,
 0, 0, 255, 1.4 )
     textDisplayAddText ( globalTextDisplay, textItemLeaderScore )
 
     for k,v in getElementsByType ( "player" ) do
          setElementData ( v, "points", 0 )
          local playerTextDisplay = textCreateDisplay ()
          local yourScore = textCreateTextItem ( "Score: "..getElementData(v, 
"points"), 0.15, 0.7, 0, 255, 0, 0, 255, 1.8 )
          textDisplayAddText ( playerTextDisplay, yourScore )
          textDisplayAddObserver ( playerTextDisplay, v )
          setElementData ( v, "textItemPoints", yourScore )
 
          textDisplayAddObserver ( globalTextDisplay, v )
          leaderPlayer = false
     end

И устанавливаем таймер, чтобы закончить раунд через 5 минут:

 
     kothEndTimer = setTimer ( "kothEnd", 300000, 1 )
end

Для каждого игрока, который присоединяется после того, как начат игровой мод, мы также должны установить показы текста и поинты.

 
addEventHandler ( "onPlayerJoin", getRootElement(), "kothJoin" )
function kothJoin ()
     setElementData ( source, "points", 0 )
     local playerTextDisplay = textCreateDisplay ()
     local yourScore = textCreateTextItem ( "Score: "..getElementData(source, 
"points"), 0.15, 0.7, 0, 255, 0, 0, 255, 1.8 )
     textDisplayAddText ( playerTextDisplay, yourScore )
     textDisplayAddObserver ( playerTextDisplay, source )
     setElementData ( source, "textItemPoints", yourScore )
     textDisplayAddObserver ( globalTextDisplay, source )
end

Когда игрок появляется:

 
addEventHandler ( "onPlayerSpawn", getRootElement(), "kothSpawn" )
function kothSpawn ( spawnpoint, team )

Мы выдаём ему ak-47 (ID 30) с 10000 патронами.

 
giveWeapon ( source, 30, 10000 )
end


Главные функции


 
function checkHillArea ()

Здесь мы перешли на главную функцию, которую вызывают каждые 500мс.
Мы создаем таблицу, которая хранит всех игроков, которые находятся в области для захвата.

 
     local hillPlayers = getElementsWithinColShape ( hillArea, "player" )

Проверять каждого игрока в таблице с помощью isPlayerDead() и если он мертв, удалять его из таблицы с помощью table.remove(), таким образом, он не получает поинты, являясь мертвым.

 
     for k,v in hillPlayers do
          if ( isPlayerDead ( v ) ) then
               table.remove(hillPlayers,k)
          end
     end

После того, как мы удалили всех мертвых игроков, мы проверяем, как много пунктов остаётся в таблице:

 
     if table.getn ( hillPlayers ) ~= 0 then

Если это не 0, мы устанавливаем цвет области радара на красный и заставляем её загореться, как это было когда вы захватывали области в одиночной игре.

 
          setRadarAreaFlashing ( hillRadar, true )
          setRadarAreaColor ( hillRadar, 255, 0, 0, 175 )

И для каждого игрока в таблице мы должны увеличить их поинты и обновить их показы текста. Таким образом, мы получаем их текущие поинты и показы текста с помощью getElementDat (), добавляем 1 поинт, и обновляем пункты текста с помощью textItemSetText()

 
          for k,v in hillPlayers do
               local currentPoints = getElementData ( v, "points" )
               local newPoints = currentPoints + 1setElementData ( v, "points",
 newPoints )
               textItemSetText ( getElementData(v,"textItemPoints"), 
"Score: "..newPoints )
          end

Иначе, если нет никаких игроков оставленных в таблице, мы устанавливаем цвет области на зеленый и делаем его, не горящим на радаре.

 
     else
          setRadarAreaFlashing ( hillRadar, false )
          setRadarAreaColor ( hillRadar, 0, 255, 0, 175 )
     end

Теперь нам надо вывести лидера.

 
     local leaderText = ""
     local leaders = 1
     for k,v in getElementsByType ( "player" ) do

Если на данный момент нет никакого лидера, то первый игрок, которого мы получим, и будет им.

 
          if leaderPlayer == false then leaderPlayer = v end

Далее, если текущий проверенный игрок, не лидер, мы получаем его и лидера поинты

 
          local leaderPoints = getElementData ( leaderPlayer, "points" ) 
          playerPoints = getElementData ( v, "points" )

Если игрок имеет больше количество поинтов, чем лидер, мы обновляем лидера

 
               if playerPoints > leaderPoints then
                    leaders = 1
                    leaderPlayer = v
                    leaderText = getClientName ( v )

Если они имеют то же самое количество поинтов, то мы имеем двух лидеров

 
               elseif playerPoints == leaderPoints then
                    leaders = leaders + 1
                    leaderText = leaderText.."/"..getClientName(v)
               end
          end
     end

И если есть меньше чем 3 лидера, и сам лидер существует, мы выводим его

 
     if leaders > 3 or leaders == getPlayerCount () or leaderPlayer == false then
          textItemSetText ( textItemLeaderScore, "Leader: None" )
     else
          textItemSetText ( textItemLeaderScore, "Leader: "..leaderText.."
 - "..getElementData(leaderPlayer,"points") )
     end
end

Когда мы заканчиваем текущий раунд

 
function kothEnd ( )

Мы убираем главный таймер, таким образом мы не получаем больше поинты

 
killTimer ( kothTimer )

Получите лидеров таким же самым путём как прежде и покажите их с новым показом текста

 
     local leaderText = ""
     local leaders = 1
     for k,v in getElementsByType ( "player" ) do
          if leaderPlayer == false then leaderPlayer = v end
 
          local leaderPoints = getElementData ( leaderPlayer, "points" ) 
          playerPoints = getElementData ( v, "points" )
          if v ~= leaderPlayer then
               if playerPoints > leaderPoints then
                    leaders = 1
                    leaderPlayer = v
                    leaderText = getClientName ( v )
               elseif playerPoints == leaderPoints then
                    leaders = leaders + 1
                    leaderText = leaderText.."/"..getClientName(v)
               end
          else
               leaderText = getClientName (leaderPlayer )
          end
     end
     local textDisplayWinner = textCreateDisplay ()
     local textItemif leaders > 3 or leaders == getPlayerCount ()
or leaderPlayer == false then
          textItem = textCreateTextItem ( "The time is out!\nWinner: None
\nNewRound!", 0.5, 0.5, 2, 255, 0, 0, 255, 255 )
     else
          textItem = textCreateTextItem ( "The time is out!\nWinner: 
"..leaderText.." with "..getElementData ( leaderPlayer, "points" 
).."points!\n\nNewRound!", 0.5, 0.5, 2, 255, 0, 0, 255, 255 )
     end
     textDisplayAddText ( textDisplay, textItem )
     for k,v in getElementsByType ( "player" ) do
          textDisplayAddObserver ( textDisplayWinner, v )
          setElementData ( v, "points", 0 )
          textItemSetText ( getElementData(v,"textItemPoints"), "Score: 0" )
     end

И напоследок перезагрузка мода

 
     restartResource ( getThisResource() )
end


Увеличение повреждения оружия


 
addEventHandler ( "onPlayerDamage", getRootElement(), "kothDamage" )
function kothDamage ( attacker, weapon, bodypart, loss )

Если мы были повреждены игроком, мы устанавливаем новое повреждение, которое является 125 % от предыдущего и проверяем, сколько жизней мы имеем.

 
          local damage = loss * 1.25
          local hpLeft = getPlayerHealth ( source ) - damage

Если больше чем 0, то мы все еще живы, таким образом, мы проверяем часть тела, в которую мы были повреждены. И если это - голова, мы убиваем игрока, если его жизни не изменяются увеличенным повреждением.

 
          if ( hpLeft > 0 ) then
               if ( bodypart == 9 ) then
                    killPlayer ( source, attacker, weapon, bodypart )
               else
                    setPlayerHealth ( source, hpLeft )
               end

Иначе, если результат здоровья игрока равен 0 или меньше, мы его только убиваем.

 
          else
               killPlayer ( source, attacker, weapon, bodypart )
          end
     end
end


Сообщения


Когда игрок вступает или оставляет зону, мы должны это вывести

 
addEventHandler ( "onColShapeHit", -- getRootElement(), "kothHillEnter" )
function kothHillEnter ( player, dim )
     if source == hillArea then
          outputMessage ( getClientName(player).." entered the zone!",
255, 255, 109, 255 )
     end
end
 
addEventHandler ( "onColShapeLeave", -- getRootElement(), "kothHillExit" )
function kothHillExit ( player, dim )
     if source == hillArea then
          if isPlayerDead ( player ) ~= true then
               outputMessage ( getClientName(player).." left the zone!",
255, 255, 109, 255 )
          end
     end
end

И наконец мы выводим сообщения о смертях:

 
addEventHandler ( "onPlayerWasted", getRootElement(),
"KillMessages_onPlayerWasted" )
function KillMessages_onPlayerWasted ( totalammo, killer, killerweapon, bodypart )

Установите, ник убитого игрока, цвет сообщения и альфы

 
     local killed_nick = getClientName ( source )
     local r,g,b = getPlayerNametagColor( source )
     local a = 120

Если игрок был в зоне koth, мы устанавливаем Альфу на немного большую переменную, таким образом, мы видим его немного лучше.

 
     if ( isElementWithinColShape ( source, hillArea ) ) then
          r = 255
          g = 255
          b = 109
          a = 255
     end

Иначе, мы только выводим сообщения, подобный тому, который был в руководстве 5b.

 
     if ( killer ) then
          if (source == killer) then
               killed_nick = "himself"
          end
          local killmessage = getClientName(killer).." killed "..killed_nick
          local killerweapon_name = getWeaponNameFromID ( killerweapon )
          if ( killerweapon_name ) then
               outputMessage( killmessage.." ("
..killerweapon_name..")",  r, g, b, a )
          else
               outputMessage( killmessage, r, g, b, a )
          end
     else
          outputMessage( killed_nick.." died", r, g, b, a )
     end
end
 
------OUTPUT MESSAGE CODE-----
addEventHandler ( "onResourceStart", getRootElement(), "createTextOnLoad" )
function createTextOnLoad ( name )
     local outputMessageTextDisplay = textCreateDisplay ()
     local distance = 0.027
     local start = 0.25
     local size = 1.2
          outputMessageTextItem1 = textCreateTextItem ( "", 0.8, start + 
distance, 1, 255, 255, 255, 255, size )
          outputMessageTextItem2 = textCreateTextItem ( "", 0.8, start + 
(distance * 2 ), 1, 255, 255, 255, 255, size )
          outputMessageTextItem3 = textCreateTextItem ( "", 0.8, start + 
(distance * 3 ), 
1, 255, 255, 255, 255, size ) 
          outputMessageTextItem4 = textCreateTextItem ( "", 0.8, start + 
(distance * 4 ), 1, 255, 255, 255, 255, size )
          outputMessageTextItem5 = textCreateTextItem ( "", 0.8, start + 
(distance * 5 ), 1, 255, 255, 255, 255, size )
          outputMessageTextItem6 = textCreateTextItem ( "", 0.8, start + 
(distance * 6 ), 1, 255, 255, 255, 255, size )
     textDisplayAddText ( outputMessageTextDisplay, outputMessageTextItem1 )
     textDisplayAddText ( outputMessageTextDisplay, outputMessageTextItem2 )
     textDisplayAddText ( outputMessageTextDisplay, outputMessageTextItem3 )
     textDisplayAddText ( outputMessageTextDisplay, outputMessageTextItem4 )
     textDisplayAddText ( outputMessageTextDisplay, outputMessageTextItem5 )
     textDisplayAddText ( outputMessageTextDisplay, outputMessageTextItem6 )
     local players = getElementsByType ( "player" )
     for k,v in players do
          textDisplayAddObserver ( outputMessageTextDisplay, v )
     end
end
 
addEventHandler ( "onPlayerJoin", getRootElement(), "showTextPlayerJoin" )
function showTextPlayerJoin ()
     textDisplayAddObserver ( outputMessageTextDisplay, source )
end
 
function outputMessage ( text, r, g, b, a )
     local text2 = textItemGetText ( outputMessageTextItem2 )
     local r2,g2,b2,a2 = textItemGetColor ( outputMessageTextItem2 )
     local text3 = textItemGetText ( outputMessageTextItem3 )
     local r3,g3,b3,a3 = textItemGetColor ( outputMessageTextItem3 )
     local text4 = textItemGetText ( outputMessageTextItem4 )
     local r4,g4,b4,a4 = textItemGetColor ( outputMessageTextItem4 )
     local text5 = textItemGetText ( outputMessageTextItem5 )
     local r5,g5,b5,a5 = textItemGetColor ( outputMessageTextItem5 )
     local text6 = textItemGetText ( outputMessageTextItem6 )
     local r6,g6,b6,a6 = textItemGetColor ( outputMessageTextItem6 )
     textItemSetText ( outputMessageTextItem5, text6 )
     textItemSetColor ( outputMessageTextItem5, r6, g6, b6, a6 )
     textItemSetText ( outputMessageTextItem4, text5 )
     textItemSetColor ( outputMessageTextItem4, r5, g5, b5, a5 )
     textItemSetText ( outputMessageTextItem3, text4 )
     textItemSetColor ( outputMessageTextItem3, r4, g4, b4, a4 )
     textItemSetText ( outputMessageTextItem2, text3 )
     textItemSetColor ( outputMessageTextItem2, r3, g3, b3, a3 )
     textItemSetText ( outputMessageTextItem1, text2 )
     textItemSetColor ( outputMessageTextItem1, r2, g2, b2, a2 )
     ---
     textItemSetText ( outputMessageTextItem6, text )
     textItemSetColor ( outputMessageTextItem6, r, g, b, a )
     --
end

На этом всё, следите за дальнейшими руководствами на нашем сайте!