No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gameinterface.lua 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. WALK_REPEAT_DELAY = 90
  2. WALK_STEPS_RETRY = 10
  3. gameRootPanel = nil
  4. gameMapPanel = nil
  5. gameRightPanel = nil
  6. gameLeftPanel = nil
  7. gameBottomPanel = nil
  8. logoutButton = nil
  9. mouseGrabberWidget = nil
  10. countWindow = nil
  11. logoutWindow = nil
  12. exitWindow = nil
  13. bottomSplitter = nil
  14. limitZoom = false
  15. currentViewMode = 0
  16. smartWalkDirs = {}
  17. smartWalkDir = nil
  18. walkFunction = g_game.walk
  19. function init()
  20. g_ui.importStyle('styles/countwindow')
  21. connect(g_game, {
  22. onGameStart = onGameStart,
  23. onGameEnd = onGameEnd,
  24. onLoginAdvice = onLoginAdvice
  25. }, true)
  26. gameRootPanel = g_ui.displayUI('gameinterface')
  27. gameRootPanel:hide()
  28. gameRootPanel:lower()
  29. gameRootPanel.onGeometryChange = updateStretchShrink
  30. gameRootPanel.onFocusChange = stopSmartWalk
  31. mouseGrabberWidget = gameRootPanel:getChildById('mouseGrabber')
  32. mouseGrabberWidget.onMouseRelease = onMouseGrabberRelease
  33. bottomSplitter = gameRootPanel:getChildById('bottomSplitter')
  34. gameMapPanel = gameRootPanel:getChildById('gameMapPanel')
  35. gameRightPanel = gameRootPanel:getChildById('gameRightPanel')
  36. gameLeftPanel = gameRootPanel:getChildById('gameLeftPanel')
  37. gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
  38. connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
  39. logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'), '/images/topbuttons/logout', tryLogout, true)
  40. setupViewMode(0)
  41. bindKeys()
  42. if g_game.isOnline() then
  43. show()
  44. end
  45. end
  46. function bindKeys()
  47. g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true)
  48. g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
  49. g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
  50. g_keyboard.bindKeyDown('Left', function() changeWalkDir(West) end, gameRootPanel, true)
  51. g_keyboard.bindKeyDown('Numpad8', function() changeWalkDir(North) end, gameRootPanel, true)
  52. g_keyboard.bindKeyDown('Numpad9', function() changeWalkDir(NorthEast) end, gameRootPanel, true)
  53. g_keyboard.bindKeyDown('Numpad6', function() changeWalkDir(East) end, gameRootPanel, true)
  54. g_keyboard.bindKeyDown('Numpad3', function() changeWalkDir(SouthEast) end, gameRootPanel, true)
  55. g_keyboard.bindKeyDown('Numpad2', function() changeWalkDir(South) end, gameRootPanel, true)
  56. g_keyboard.bindKeyDown('Numpad1', function() changeWalkDir(SouthWest) end, gameRootPanel, true)
  57. g_keyboard.bindKeyDown('Numpad4', function() changeWalkDir(West) end, gameRootPanel, true)
  58. g_keyboard.bindKeyDown('Numpad7', function() changeWalkDir(NorthWest) end, gameRootPanel, true)
  59. g_keyboard.bindKeyUp('Up', function() changeWalkDir(North, true) end, gameRootPanel, true)
  60. g_keyboard.bindKeyUp('Right', function() changeWalkDir(East, true) end, gameRootPanel, true)
  61. g_keyboard.bindKeyUp('Down', function() changeWalkDir(South, true) end, gameRootPanel, true)
  62. g_keyboard.bindKeyUp('Left', function() changeWalkDir(West, true) end, gameRootPanel, true)
  63. g_keyboard.bindKeyUp('Numpad8', function() changeWalkDir(North, true) end, gameRootPanel, true)
  64. g_keyboard.bindKeyUp('Numpad9', function() changeWalkDir(NorthEast, true) end, gameRootPanel, true)
  65. g_keyboard.bindKeyUp('Numpad6', function() changeWalkDir(East, true) end, gameRootPanel, true)
  66. g_keyboard.bindKeyUp('Numpad3', function() changeWalkDir(SouthEast, true) end, gameRootPanel, true)
  67. g_keyboard.bindKeyUp('Numpad2', function() changeWalkDir(South, true) end, gameRootPanel, true)
  68. g_keyboard.bindKeyUp('Numpad1', function() changeWalkDir(SouthWest, true) end, gameRootPanel, true)
  69. g_keyboard.bindKeyUp('Numpad4', function() changeWalkDir(West, true) end, gameRootPanel, true)
  70. g_keyboard.bindKeyUp('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true)
  71. g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  72. g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  73. g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  74. g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  75. g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  76. g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  77. g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  78. g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  79. g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  80. g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  81. g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  82. g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  83. g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  84. g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  85. g_keyboard.bindKeyPress('Ctrl+Down', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  86. g_keyboard.bindKeyPress('Ctrl+Left', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  87. g_keyboard.bindKeyPress('Ctrl+Numpad8', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  88. g_keyboard.bindKeyPress('Ctrl+Numpad6', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  89. g_keyboard.bindKeyPress('Ctrl+Numpad2', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  90. g_keyboard.bindKeyPress('Ctrl+Numpad4', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  91. g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
  92. g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel, 250)
  93. g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel, 250)
  94. g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
  95. g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
  96. g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
  97. g_keyboard.bindKeyDown('Ctrl+N', function() gameMapPanel:setDrawTexts(not gameMapPanel:isDrawingTexts()) end, gameRootPanel)
  98. g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
  99. end
  100. function terminate()
  101. hide()
  102. stopSmartWalk()
  103. disconnect(g_game, {
  104. onGameStart = onGameStart,
  105. onGameEnd = onGameEnd,
  106. onLoginAdvice = onLoginAdvice
  107. })
  108. disconnect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
  109. logoutButton:destroy()
  110. gameRootPanel:destroy()
  111. end
  112. function onGameStart()
  113. logoutButton:setTooltip(tr('Logout'))
  114. show()
  115. -- open tibia has delay in auto walking
  116. if not g_game.isOfficialTibia() then
  117. g_game.enableFeature(GameForceFirstAutoWalkStep)
  118. else
  119. g_game.disableFeature(GameForceFirstAutoWalkStep)
  120. end
  121. end
  122. function onGameEnd()
  123. logoutButton:setTooltip(tr('Exit'))
  124. setupViewMode(0)
  125. hide()
  126. end
  127. function show()
  128. connect(g_app, { onClose = tryExit })
  129. modules.client_background.hide()
  130. gameRootPanel:show()
  131. gameRootPanel:focus()
  132. gameMapPanel:followCreature(g_game.getLocalPlayer())
  133. updateStretchShrink()
  134. end
  135. function hide()
  136. disconnect(g_app, { onClose = tryExit })
  137. if logoutWindow then
  138. logoutWindow:destroy()
  139. logoutWindow = nil
  140. end
  141. if exitWindow then
  142. exitWindow:destroy()
  143. exitWindow = nil
  144. end
  145. if countWindow then
  146. countWindow:destroy()
  147. countWindow = nil
  148. end
  149. gameRootPanel:hide()
  150. modules.client_background.show()
  151. end
  152. function onLoginAdvice(message)
  153. displayInfoBox(tr("For Your Information"), message)
  154. end
  155. function forceExit()
  156. scheduleEvent(exit, 10)
  157. return true
  158. end
  159. function tryExit()
  160. if exitWindow then
  161. return true
  162. end
  163. local exitFunc = function() logout() forceExit() end
  164. local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
  165. local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
  166. exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
  167. { { text=tr('Force Exit'), callback=exitFunc },
  168. { text=tr('Logout'), callback=logoutFunc },
  169. { text=tr('Cancel'), callback=cancelFunc },
  170. anchor=AnchorHorizontalCenter }, logoutFunc, cancelFunc)
  171. return true
  172. end
  173. function logout()
  174. if g_game.isOnline() then
  175. g_game.safeLogout()
  176. return true
  177. end
  178. end
  179. function tryLogout()
  180. if not g_game.isOnline() then
  181. exit()
  182. end
  183. if logoutWindow then
  184. return
  185. end
  186. local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
  187. local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
  188. logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
  189. { text=tr('Yes'), callback=yesCallback },
  190. { text=tr('No'), callback=noCallback },
  191. anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
  192. end
  193. function stopSmartWalk()
  194. smartWalkDirs = {}
  195. smartWalkDir = nil
  196. end
  197. function changeWalkDir(dir, pop)
  198. while table.removevalue(smartWalkDirs, dir) do end
  199. if pop then
  200. if #smartWalkDirs == 0 then
  201. stopSmartWalk()
  202. return
  203. end
  204. else
  205. table.insert(smartWalkDirs, 1, dir)
  206. end
  207. smartWalkDir = smartWalkDirs[1]
  208. if modules.client_options.getOption('smartWalk') and #smartWalkDirs > 1 then
  209. for _,d in pairs(smartWalkDirs) do
  210. if (smartWalkDir == North and d == West) or (smartWalkDir == West and d == North) then
  211. smartWalkDir = NorthWest
  212. break
  213. elseif (smartWalkDir == North and d == East) or (smartWalkDir == East and d == North) then
  214. smartWalkDir = NorthEast
  215. break
  216. elseif (smartWalkDir == South and d == West) or (smartWalkDir == West and d == South) then
  217. smartWalkDir = SouthWest
  218. break
  219. elseif (smartWalkDir == South and d == East) or (smartWalkDir == East and d == South) then
  220. smartWalkDir = SouthEast
  221. break
  222. end
  223. end
  224. end
  225. end
  226. function smartWalk(dir)
  227. if g_keyboard.getModifiers() == KeyboardNoModifier then
  228. if smartWalkDir then
  229. walkFunction(smartWalkDir)
  230. else
  231. walkFunction(dir)
  232. end
  233. return true
  234. end
  235. return false
  236. end
  237. function updateStretchShrink()
  238. if modules.client_options.getOption('dontStretchShrink') and not alternativeView then
  239. gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
  240. -- Set gameMapPanel size to height = 11 * 32 + 2
  241. bottomSplitter:setMarginBottom(bottomSplitter:getMarginBottom() + (gameMapPanel:getHeight() - 32 * 11) - 10)
  242. end
  243. end
  244. function onMouseGrabberRelease(self, mousePosition, mouseButton)
  245. if selectedThing == nil then return false end
  246. if mouseButton == MouseLeftButton then
  247. local clickedWidget = gameRootPanel:recursiveGetChildByPos(mousePosition, false)
  248. if clickedWidget then
  249. if selectedType == 'use' then
  250. onUseWith(clickedWidget, mousePosition)
  251. elseif selectedType == 'trade' then
  252. onTradeWith(clickedWidget, mousePosition)
  253. end
  254. end
  255. end
  256. selectedThing = nil
  257. g_mouse.popCursor('target')
  258. self:ungrabMouse()
  259. return true
  260. end
  261. function onUseWith(clickedWidget, mousePosition)
  262. if clickedWidget:getClassName() == 'UIMap' then
  263. local tile = clickedWidget:getTile(mousePosition)
  264. if tile then
  265. g_game.useWith(selectedThing, tile:getTopMultiUseThing())
  266. end
  267. elseif clickedWidget:getClassName() == 'UIItem' and not clickedWidget:isVirtual() then
  268. g_game.useWith(selectedThing, clickedWidget:getItem())
  269. elseif clickedWidget:getClassName() == 'UICreatureButton' then
  270. local creature = clickedWidget:getCreature()
  271. if creature then
  272. g_game.useWith(selectedThing, creature)
  273. end
  274. end
  275. end
  276. function onTradeWith(clickedWidget, mousePosition)
  277. if clickedWidget:getClassName() == 'UIMap' then
  278. local tile = clickedWidget:getTile(mousePosition)
  279. if tile then
  280. g_game.requestTrade(selectedThing, tile:getTopCreature())
  281. end
  282. end
  283. end
  284. function startUseWith(thing)
  285. if g_ui.isMouseGrabbed() or not thing then return end
  286. selectedType = 'use'
  287. selectedThing = thing
  288. mouseGrabberWidget:grabMouse()
  289. g_mouse.pushCursor('target')
  290. end
  291. function startTradeWith(thing)
  292. if g_ui.isMouseGrabbed() or not thing then return end
  293. selectedType = 'trade'
  294. selectedThing = thing
  295. mouseGrabberWidget:grabMouse()
  296. g_mouse.pushCursor('target')
  297. end
  298. function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
  299. if not g_game.isOnline() then return end
  300. local menu = g_ui.createWidget('PopupMenu')
  301. local classic = modules.client_options.getOption('classicControl')
  302. local shortcut = nil
  303. if not classic then shortcut = '(Shift)' else shortcut = nil end
  304. if lookThing then
  305. menu:addOption(tr('Look'), function() g_game.look(lookThing) end, shortcut)
  306. end
  307. if not classic then shortcut = '(Ctrl)' else shortcut = nil end
  308. if useThing then
  309. if useThing:isContainer() then
  310. if useThing:getParentContainer() then
  311. menu:addOption(tr('Open'), function() g_game.open(useThing, useThing:getParentContainer()) end, shortcut)
  312. menu:addOption(tr('Open in new window'), function() g_game.open(useThing) end)
  313. else
  314. menu:addOption(tr('Open'), function() g_game.open(useThing) end, shortcut)
  315. end
  316. else
  317. if useThing:isMultiUse() then
  318. menu:addOption(tr('Use with ...'), function() startUseWith(useThing) end, shortcut)
  319. else
  320. menu:addOption(tr('Use'), function() g_game.use(useThing) end, shortcut)
  321. end
  322. end
  323. if useThing:isRotateable() then
  324. menu:addOption(tr('Rotate'), function() g_game.rotate(useThing) end)
  325. end
  326. end
  327. if lookThing and not lookThing:isCreature() and not lookThing:isNotMoveable() and lookThing:isPickupable() then
  328. menu:addSeparator()
  329. menu:addOption(tr('Trade with ...'), function() startTradeWith(lookThing) end)
  330. end
  331. if lookThing then
  332. local parentContainer = lookThing:getParentContainer()
  333. if parentContainer and parentContainer:hasParent() then
  334. menu:addOption(tr('Move up'), function() g_game.moveToParentContainer(lookThing, lookThing:getCount()) end)
  335. end
  336. end
  337. if creatureThing then
  338. local localPlayer = g_game.getLocalPlayer()
  339. menu:addSeparator()
  340. if creatureThing:isLocalPlayer() then
  341. menu:addOption(tr('Set Outfit'), function() g_game.requestOutfit() end)
  342. if g_game.getFeature(GamePlayerMounts) then
  343. if not localPlayer:isMounted() then
  344. menu:addOption(tr('Mount'), function() localPlayer:mount() end)
  345. else
  346. menu:addOption(tr('Dismount'), function() localPlayer:dismount() end)
  347. end
  348. end
  349. if creatureThing:isPartyMember() then
  350. if creatureThing:isPartyLeader() then
  351. if creatureThing:isPartySharedExperienceActive() then
  352. menu:addOption(tr('Disable Shared Experience'), function() g_game.partyShareExperience(false) end)
  353. else
  354. menu:addOption(tr('Enable Shared Experience'), function() g_game.partyShareExperience(true) end)
  355. end
  356. end
  357. menu:addOption(tr('Leave Party'), function() g_game.partyLeave() end)
  358. end
  359. else
  360. if not classic then shortcut = '(Alt)' else shortcut = nil end
  361. if g_game.getAttackingCreature() ~= creatureThing then
  362. menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
  363. else
  364. menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end, shortcut)
  365. end
  366. if g_game.getFollowingCreature() ~= creatureThing then
  367. menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
  368. else
  369. menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
  370. end
  371. if creatureThing:isPlayer() then
  372. menu:addSeparator()
  373. local creatureName = creatureThing:getName()
  374. menu:addOption(tr('Message to %s', creatureName), function() g_game.openPrivateChannel(creatureName) end)
  375. if modules.game_console.getOwnPrivateTab() then
  376. menu:addOption(tr('Invite to private chat'), function() g_game.inviteToOwnChannel(creatureName) end)
  377. menu:addOption(tr('Exclude from private chat'), function() g_game.excludeFromOwnChannel(creatureName) end) -- [TODO] must be removed after message's popup labels been implemented
  378. end
  379. if not localPlayer:hasVip(creatureName) then
  380. menu:addOption(tr('Add to VIP list'), function() g_game.addVip(creatureName) end)
  381. end
  382. if modules.game_console.isIgnored(creatureName) then
  383. menu:addOption(tr('Unignore') .. ' ' .. creatureName, function() modules.game_console.removeIgnoredPlayer(creatureName) end)
  384. else
  385. menu:addOption(tr('Ignore') .. ' ' .. creatureName, function() modules.game_console.addIgnoredPlayer(creatureName) end)
  386. end
  387. local localPlayerShield = localPlayer:getShield()
  388. local creatureShield = creatureThing:getShield()
  389. if localPlayerShield == ShieldNone or localPlayerShield == ShieldWhiteBlue then
  390. if creatureShield == ShieldWhiteYellow then
  391. menu:addOption(tr('Join %s\'s Party', creatureThing:getName()), function() g_game.partyJoin(creatureThing:getId()) end)
  392. else
  393. menu:addOption(tr('Invite to Party'), function() g_game.partyInvite(creatureThing:getId()) end)
  394. end
  395. elseif localPlayerShield == ShieldWhiteYellow then
  396. if creatureShield == ShieldWhiteBlue then
  397. menu:addOption(tr('Revoke %s\'s Invitation', creatureThing:getName()), function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
  398. end
  399. elseif localPlayerShield == ShieldYellow or localPlayerShield == ShieldYellowSharedExp or localPlayerShield == ShieldYellowNoSharedExpBlink or localPlayerShield == ShieldYellowNoSharedExp then
  400. if creatureShield == ShieldWhiteBlue then
  401. menu:addOption(tr('Revoke %s\'s Invitation', creatureThing:getName()), function() g_game.partyRevokeInvitation(creatureThing:getId()) end)
  402. elseif creatureShield == ShieldBlue or creatureShield == ShieldBlueSharedExp or creatureShield == ShieldBlueNoSharedExpBlink or creatureShield == ShieldBlueNoSharedExp then
  403. menu:addOption(tr('Pass Leadership to %s', creatureThing:getName()), function() g_game.partyPassLeadership(creatureThing:getId()) end)
  404. else
  405. menu:addOption(tr('Invite to Party'), function() g_game.partyInvite(creatureThing:getId()) end)
  406. end
  407. end
  408. end
  409. end
  410. if modules.game_ruleviolation.hasWindowAccess() then
  411. menu:addSeparator()
  412. menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
  413. end
  414. menu:addSeparator()
  415. menu:addOption(tr('Copy Name'), function() g_window.setClipboardText(creatureThing:getName()) end)
  416. end
  417. menu:display(menuPosition)
  418. end
  419. function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
  420. local keyboardModifiers = g_keyboard.getModifiers()
  421. if not modules.client_options.getOption('classicControl') then
  422. if keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton then
  423. createThingMenu(menuPosition, lookThing, useThing, creatureThing)
  424. return true
  425. elseif lookThing and keyboardModifiers == KeyboardShiftModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
  426. g_game.look(lookThing)
  427. return true
  428. elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
  429. if useThing:isContainer() then
  430. if useThing:getParentContainer() then
  431. g_game.open(useThing, useThing:getParentContainer())
  432. else
  433. g_game.open(useThing)
  434. end
  435. return true
  436. elseif useThing:isMultiUse() then
  437. startUseWith(useThing)
  438. return true
  439. else
  440. g_game.use(useThing)
  441. return true
  442. end
  443. return true
  444. elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
  445. g_game.attack(creatureThing)
  446. return true
  447. end
  448. -- classic control
  449. else
  450. if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
  451. local player = g_game.getLocalPlayer()
  452. if creatureThing and creatureThing ~= player then
  453. g_game.attack(creatureThing)
  454. return true
  455. elseif useThing:isContainer() then
  456. if useThing:getParentContainer() then
  457. g_game.open(useThing, useThing:getParentContainer())
  458. return true
  459. else
  460. g_game.open(useThing)
  461. return true
  462. end
  463. elseif useThing:isMultiUse() then
  464. startUseWith(useThing)
  465. return true
  466. else
  467. g_game.use(useThing)
  468. return true
  469. end
  470. return true
  471. elseif lookThing and keyboardModifiers == KeyboardShiftModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
  472. g_game.look(lookThing)
  473. return true
  474. elseif lookThing and ((g_mouse.isPressed(MouseLeftButton) and mouseButton == MouseRightButton) or (g_mouse.isPressed(MouseRightButton) and mouseButton == MouseLeftButton)) then
  475. g_game.look(lookThing)
  476. return true
  477. elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
  478. createThingMenu(menuPosition, lookThing, useThing, creatureThing)
  479. return true
  480. elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
  481. g_game.attack(creatureThing)
  482. return true
  483. end
  484. end
  485. local player = g_game.getLocalPlayer()
  486. player:stopAutoWalk()
  487. if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
  488. player.onAutoWalkFail = function() modules.game_textmessage.displayFailureMessage(tr('There is no way.')) end
  489. player:autoWalk(autoWalkPos)
  490. return true
  491. end
  492. return false
  493. end
  494. function moveStackableItem(item, toPos)
  495. if countWindow then
  496. return
  497. end
  498. if g_keyboard.isCtrlPressed() then
  499. g_game.move(item, toPos, item:getCount())
  500. return
  501. elseif g_keyboard.isShiftPressed() then
  502. g_game.move(item, toPos, 1)
  503. return
  504. end
  505. local count = item:getCount()
  506. countWindow = g_ui.createWidget('CountWindow', rootWidget)
  507. local itembox = countWindow:getChildById('item')
  508. local scrollbar = countWindow:getChildById('countScrollBar')
  509. itembox:setItemId(item:getId())
  510. itembox:setItemCount(count)
  511. scrollbar:setMaximum(count)
  512. scrollbar:setMinimum(1)
  513. scrollbar:setValue(count)
  514. local spinbox = countWindow:getChildById('spinBox')
  515. spinbox:setMaximum(count)
  516. spinbox:setMinimum(0)
  517. spinbox:setValue(0)
  518. spinbox:hideButtons()
  519. spinbox:focus()
  520. local spinBoxValueChange = function(self, value)
  521. scrollbar:setValue(value)
  522. end
  523. spinbox.onValueChange = spinBoxValueChange
  524. scrollbar.onValueChange = function(self, value)
  525. itembox:setItemCount(value)
  526. spinbox.onValueChange = nil
  527. spinbox:setValue(value)
  528. spinbox.onValueChange = spinBoxValueChange
  529. end
  530. local okButton = countWindow:getChildById('buttonOk')
  531. local moveFunc = function()
  532. g_game.move(item, toPos, itembox:getItemCount())
  533. okButton:getParent():destroy()
  534. countWindow = nil
  535. end
  536. local cancelButton = countWindow:getChildById('buttonCancel')
  537. local cancelFunc = function()
  538. cancelButton:getParent():destroy()
  539. countWindow = nil
  540. end
  541. countWindow.onEnter = moveFunc
  542. countWindow.onEscape = cancelFunc
  543. okButton.onClick = moveFunc
  544. cancelButton.onClick = cancelFunc
  545. end
  546. function getRootPanel()
  547. return gameRootPanel
  548. end
  549. function getMapPanel()
  550. return gameMapPanel
  551. end
  552. function getRightPanel()
  553. return gameRightPanel
  554. end
  555. function getLeftPanel()
  556. return gameLeftPanel
  557. end
  558. function getBottomPanel()
  559. return gameBottomPanel
  560. end
  561. function onLeftPanelVisibilityChange(leftPanel, visible)
  562. if not visible and g_game.isOnline() then
  563. local children = leftPanel:getChildren()
  564. for i=1,#children do
  565. children[i]:setParent(gameRightPanel)
  566. end
  567. end
  568. end
  569. function nextViewMode()
  570. setupViewMode((currentViewMode + 1) % 3)
  571. end
  572. function setupViewMode(mode)
  573. if mode == currentViewMode then return end
  574. if currentViewMode == 2 then
  575. gameMapPanel:addAnchor(AnchorLeft, 'gameLeftPanel', AnchorRight)
  576. gameMapPanel:addAnchor(AnchorRight, 'gameRightPanel', AnchorLeft)
  577. gameMapPanel:addAnchor(AnchorBottom, 'gameBottomPanel', AnchorTop)
  578. gameRootPanel:addAnchor(AnchorTop, 'topMenu', AnchorBottom)
  579. gameLeftPanel:setOn(modules.client_options.getOption('showLeftPanel'))
  580. gameLeftPanel:setImageColor('white')
  581. gameRightPanel:setImageColor('white')
  582. gameLeftPanel:setMarginTop(0)
  583. gameRightPanel:setMarginTop(0)
  584. gameBottomPanel:setImageColor('white')
  585. modules.client_topmenu.getTopMenu():setImageColor('white')
  586. g_game.changeMapAwareRange(18, 14)
  587. end
  588. if mode == 0 then
  589. gameMapPanel:setKeepAspectRatio(true)
  590. gameMapPanel:setLimitVisibleRange(false)
  591. gameMapPanel:setZoom(11)
  592. gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
  593. elseif mode == 1 then
  594. gameMapPanel:setKeepAspectRatio(false)
  595. gameMapPanel:setLimitVisibleRange(true)
  596. gameMapPanel:setZoom(11)
  597. gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
  598. elseif mode == 2 then
  599. gameMapPanel:setLimitVisibleRange(limitZoom)
  600. gameMapPanel:setZoom(11)
  601. gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
  602. gameMapPanel:fill('parent')
  603. gameRootPanel:fill('parent')
  604. gameLeftPanel:setImageColor('alpha')
  605. gameRightPanel:setImageColor('alpha')
  606. gameLeftPanel:setMarginTop(modules.client_topmenu.getTopMenu():getHeight() - gameLeftPanel:getPaddingTop())
  607. gameRightPanel:setMarginTop(modules.client_topmenu.getTopMenu():getHeight() - gameRightPanel:getPaddingTop())
  608. gameLeftPanel:setOn(true)
  609. gameLeftPanel:setVisible(true)
  610. gameRightPanel:setOn(true)
  611. gameMapPanel:setOn(true)
  612. gameBottomPanel:setImageColor('#ffffff88')
  613. modules.client_topmenu.getTopMenu():setImageColor('#ffffff66')
  614. if not limitZoom then
  615. g_game.changeMapAwareRange(24, 20)
  616. end
  617. end
  618. currentViewMode = mode
  619. end
  620. function limitZoom()
  621. limitZoom = true
  622. gameMapPanel:setMaxZoomOut(11)
  623. gameMapPanel:setLimitVisibleRange(true)
  624. end