[Уроки Jass]GetLocalPlayer - Wc3-Maps Форум













[ Главная · Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: Strateg, Melissa  
[Уроки Jass]GetLocalPlayer
-
влад10011Дата: Понедельник, 20-08-2012, 13:05:22 | Сообщение # 1

загрузка наград ...
Группа: V.I.P.
Сообщений: 1265
Репутация: 1039
Статус: Не на сайте
[Info] Локальные действия
Все мы знаем о существовании native-функции GetLocalPlayer:

Code
constant native GetLocalPlayer takes nothing returns player

Она ничего не берет, но возвращает локального игрока, то есть того, на компьютере которого запущена карта. То есть, если вы запустите ее в мультиплеере, на компьютере первого игрока функция вернет хендл идентичный Player(0), на компьютере второго - Player(1) и так далее.
Все мы когда-нибудь использовали GetLocalPlayer(), к примеру, для перемещения камеры игрока или для показа локального плавающего текста, но знали ли вы, какой на самом деле потенциал скрывает эта простая функция?
Позвольте мне пояснить. Мы знаем, что неправильное использование данной функции приводит к десинхронизации клиентов в мультиплеере и последующему разрыву связи. Но знаете ли вы, какие именно действия являются неправильными? Это любые действия, создающие объекты, наследующие тип handle, будь это юнит или destructable или влекущие за собой их создание. Действия, относящиеся к визуальной части игры, не вызывают десинхронизации.
Приведу пример.

Code
if (GetLocalPlayer() == Player(0)) then
   call CreateUnit(Player(0), 'hpea', 0., 0., 0.)
endif


Вызовет десинхронизацию, так как данным действием мы локально создаем работника для первого игрока, не создавая его у остальных.

Code
if (GetLocalPlayer() == Player(0)) then
   call SetCameraPosition(200., 200.)
endif


Данный код переместит камеру красного игрока в позицию 200 200 в декартовой системе координат. Десинхронизации не будет, так как никаких объектов не создается.
Но это лишь поверхностная сторона, рассмотрим более интересные возможности:
Почти все мы играли в карту DotA и знаем, что некоторые способности в этой карте имеют визуальный эффект, видимый не всем игрокам. Но как реализовать такое, без угрозы десинхронизации? Воспользуемся этим кодом:

Code
function AddLocalEffect takes string eff, real x, real y, player pl returns effect
   local string e = ""
   if (GetLocalPlayer() == pl) then
    set e = eff
   endif
   return AddSpecialEffect(e, x, y)
endfunction


Примечание: вообще, довольно полезно было бы занести значение GetLocalPlayer() в переменную, дабы избежать лишние вызовы. Например, так:

Code
globals
   constant player LocalPlayer = GetLocalPlayer()
endglobals

Далее, с помощью cJass'а, мы можем оптимизировать уже имеющуюся карту, без ручной замены переменных, так:

#define <GetLocalPlayer()> = LocalPlayer

Примечание: до этого вы видели использование GetLocalPlayer только в условиях, но что мешает использовать его и в других местах? Например, так:

Code
local multiboard mb = CreateMultiboard()
call MultiboardDisplay(mb, GetLocalPlayer() == Player(0))

Эти действия создадут мультиборд, видимый только красному игроку.
Или так:

Code
local force f = CreateForce()
local unit u = CreateUnit(Player(0), 'hpea', 0., 0., 0.)
call ForceAddPlayer(f, Player(1))
call ForceAddPlayer(f, Player(3))
if (IsPlayerInForce(GetLocalPlayer(), f)) then
   call SetUnitVertexColor(u, 255, 255, 255, 128)
endif

Данные действия создадут крестьянина и сделают его полупрозрачным для 2-го и 4-го игрока.
Или вот так:

Code
local multiboard mb = CreateMultiboard()
local integer id = GetPlayerId(GetLocalPlayer())
call MultiboardSetTitleText(GetUnitName(Hero[id])) // Hero - массив юнитов

Эти действия создадут мультиборд и в заголовке для каждого игрока покажут имя его героя.
Примечание: старайтесь не использовать GetLocalPlayer в действиях показа текста. Во-первых в определенных условиях это может вызвать непредвиденную десинхронизацию, а во-вторых - текст, показанный таким образом не будет виден в реплее игры.
Вы уже наверняка знаете про существование Preload Exploit, позволяющего сохранять данные на диск. Но что если, например, нужно сохранить некие данные определенному игроку? GetLocalPlayer поможет нам и тут! Воспользуемся следующим кодом:

Code
if (GetLocalPlayer() == Player(0)) then
   call PreloadGenClear()
   call PreloadGenStart()
   call PreloadGenEnd("\\code.txt")
endif


Это сохранит на диск с игрой первого игрока почти пустой файл code.txt. Довольно полезная возможность для карт типа ORPG, например.
Рассмотрим еще вот какую вещь:
Предположим, мы хотим узнать положение камеры игрока и пользуемся функцией такого рода:

Code
function GetPlayerCameraX takes player p returns real
   if (GetLocalPlayer() == p) then
    return GetCameraTargetPositionX()
   endif
   return 0.
endfunction

Вот возможность, которая была бы полезна, например, в картах жанра "Мафия". В таких картах мы имеем некоего убийцу и граждан, которым нужно найти убийцу. Чтобы сохранять анонимность, убийца имеет абсолютно идентичную с гражданами модель и имя. Но что если мы хотим, чтобы игрок-убийца визуально воспринимал своего героя по-другому? Поступим так:
Создадим двух абсолютно идентичных юнитов на основе нашего "гражданина". Пускай их равкоды будут 'h000' и 'h001' соответственно. Изменим у второго юнита имя на "Убийца" и модель на грабителя.
При создании юнитов, воспользуемся следующим кодом:

Code
local integer i = 'h000'
local integer l = 0
if (GetLocalPlayer() == Player(0)) then
   set i = 'h001'
endif
loop
   exitwhen (l == 11)
   call CreateUnit(Player(l), i, 0., 0., 0.)
   set l = l + 1
endloop


Для каждого игрока в центре карты будут созданы юниты. Но внимание, первый игрок будет видеть у своего юнита модель грабителя и имя "Убийца", остальные же игроки этого видеть не будут.
Внимание: у этого метода есть опасная сторона: если мы будем проводить сравнения с GetUnitTypeId(unit), выдающей равкод юнита или с GetUnitName(unit), будут выданы локальные значения, пользуйтесь этим с осторожностью.
То же самое работает с предметами, декорациями, разрушаемыми объектами и способностями. Причем способности могут использовать даже разные баффы, что дает возможность одному игроку видеть, например, буран, а второму огненный дождь.
Надеюсь данная статья помогла вам понять поистине огромный потенциал использования локального игрока в вашем коде и понять какие возможности может дать эта функция. Удачи в ваших начинаниях, но помните, что главное - осторожность и рациональность.
-------------------------------------------------------------------------------------------------------------------------------------------- -----------------
Автор статьи Doc

Look at my horse!
 
  • Страница 1 из 1
  • 1
Поиск:
Рейтинг@Mail.ru
Яндекс.Метрика

Copyright © 2010-2017
Вакансии :: Контакты
Мобильная версия сайта
chat